c/c++ 编译MakeFile入门指南

本文介绍了Makefile的基础知识及其在软件构建中的应用。讲解了如何利用Makefile自动化编译流程,提高开发效率。涵盖规则设置、变量使用及常见函数介绍。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Make 指南

引言

  • makefile的优点:自动识别编译文件生成的时间戳,实现对最后修改的文件重新编译,而其他未修改的文件无需重新编译,加速了编译的速度。
  • 预备知识:熟悉GCC编译器的常见编译的参数;makefile简单语法

makefile

规则
  • GNU Make 工具通过读一个名为Makefile的文件,根据对应的规则来执行相应的命令,生成对应的目标文件可执行文件以及动态库,静态库。
  • 命令规则如下:
    target: dependencies
    (tab)command
    (tab)command
  • target:规则的目标文件,可执行文件,动态库等的变量名,如xx.oxx.so
  • dependencies表示生成目标文件的依赖项列表,依赖项之间空格隔开;
  • (tab):表示tab键,[Tab]字符告诉make此行是一个命令行,每一个命令行必须以[Tab]字符开始。
概念
  • 伪目标:指Makefile中把那些没有任何依赖只有执行动作的目标phony targets

    • clean:是典型的伪目标,该动作用于清理make命令生成的中间文件以及目的文件,执行make clean;
    • 规则为:
      • .PHONY:clean #声明是伪目标
      • clean:
      • (tab)rm xx.o temp #动作执行,删除的目标文件和temp文件
      • 注:#表示Makefile的注释标志符
  • make变量:类似C语言的宏,是一系列字符串,即变量的值,通常表示编译的参数列表,目录列表,编译选项列表等;

    • 变量名是不包括“:”、“#”、“=”、前置空白和尾空白的任何字符串;
    • 变量名区分大小写,一个包含除字母、数字和下划线以外的变量的做法是不可取的
    • Makefile的变量名风格是通常采用大写的方式;如编译选项CFLAGS,包含目录include_dirs
    • 变量名包含很少的几个特殊的符号:自动化变量,如$<$@$?$*
    • 变量的引用:采用$(VARIABLE_NAME)${ VARIABLE_NAME }方式引用变量的定义;
    • 变量引用的展开过程是严格的文本替换过程,就是说变量值的字符串被精确的展开在此变量被引用的地方;
  • make函数:介绍两种常见的函数:

    • wildcard:通配符函数:如$(wildcard *.c)来获取工作目录下所有的.c文件列表。
    • patsubst:patten substitude, 匹配替换的缩写,通常和wildcard函数结合使用;
    • $(patsubst %.c,%.o,$(wildcard *.c)):使用wildcard函数获取工作目录下的.c文件列表;之后将列表中后缀.c替换为.o,得到在当前目录可生成的.o文件列表;
    # 仅编译可执行程序
    CC = g++
    # LINK = g++
    CFLAGS = -std=c++11 -fpermissive -O2
    INCLUDES = -I./include -I/usr/local/include
    LIBS = -L./lib  -Wl,-rpath=./lib -lyour_libname -lopencv_core -lopencv_highgui -lopencv_imgproc
    SRCS := src/main.cpp
    OBJS :=  $(SRCS:.cpp=.o)
    #OBJS = $(patsubst %.cpp,%.o,$(wildcard *.cpp)) # replace the *.o  filename of *.cpp filename 
    TESTDEMO = demo
    
    $(OBJS): $(SRCS)
    	$(CC) $(CFLAGS) -c $< -o $@
    
    $(TESTDEMO): $(OBJS)
    	$(CC) $< -o $@ $(CFLAGS) $(INCLUDES) $(LIBS)
    
    #compile: $(SRCS)
    #	$(LINK) $^ -o $(TESTDEMO) $(CFLAGS) $(INCLUDES) $(LIBS)
    
    .PHONY: clean
    clean:
    	rm -f $(TESTDEMO) $(OBJS)
    
  • 同时编译动态库与可执行文件

    CC := g++
    CFLAGS := -Wall -Wextra -O3 -fPIC -std=c++11
    LDFLAGS := -shared
    INCS := $(wildcard include/*.h)
    
    
    ifeq ($(TARGET_DEVICE),aarch64)
      CFLAGS+= -DPLATFORM_TEGRA
    endif
    
    
    PKGS:= gstreamer-1.0 gstreamer-pbutils-1.0
    
    CFLAGS+= -I ./include
    CFLAGS+= $(shell pkg-config --cflags $(PKGS))
    
    LIBS:= $(shell pkg-config --libs $(PKGS))
    
    LIBS+= $(shell pkg-config --libs gdk-pixbuf-2.0)
    LIBS+= -L./lib -lvideo_embed_api
    
    TARGET_EXEC := demo 
    TARGET_LIB := lib/libvideo_embed_sdk.so
    SRC_DIR := src
    OBJ_DIR := obj
    
    SRCS := $(wildcard $(SRC_DIR)/*.cpp)
    OBJS := $(patsubst $(SRC_DIR)/%.cpp, $(OBJ_DIR)/%.o, $(SRCS))
    
    APP_SRCS := test.cpp
    
    LIB_OBJS := $(filter-out $(APP_OBJS), $(OBJS))
    
    all: $(TARGET_LIB) $(TARGET_EXEC)
    
    $(TARGET_EXEC): $(TARGET_LIB)
    	$(CC) -o $@ $(APP_SRCS) $(CFLAGS) -L./lib -lvideo_embed_sdk 
    
    $(TARGET_LIB): $(OBJS)
    	$(CC) $^ -o $@ $(LDFLAGS) $(CFLAGS) $(LIBS)
    
    $(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp
    	@mkdir -p $(OBJ_DIR)
    	$(CC) $(CFLAGS) -c $< -o $@
    
    .PHONY: clean
    clean:
    	rm -rf $(OBJ_DIR) $(TARGET_EXEC) $(TARGET_LIB)
    
    
    • 模板3
    
    default: all
    
    ifndef OUT_DIR
    #  OUT_DIR := build/$(build_prefix)$(build)$(build_suffix)
      OUT_DIR := ./
    endif
    
    CC = g++
    # -std=c++11
    CFLAGS = -Wall -fPIC -Wl,-soname -w -D_REENTRANT -fpermissive -O2 -std=gnu++11
    CFLAGS += $(XCFLAGS)
    
    LDFLAGS = -shared
    INCLUDES = -I./include -I./3rdparty
    
    
    # --- Commands ---
    ifneq ($(verbose),yes)
      QUIET_AR = @ echo "    AR $@" ;
      QUIET_RANLIB = @ echo "    RANLIB $@" ;
      QUIET_CC = @ echo "    CC $@" ;
      QUIET_CXX = @ echo "    CXX $@" ;
      QUIET_GEN = @ echo "    GEN $@" ;
      QUIET_LINK = @ echo "    LINK $@" ;
      QUIET_RM = @ echo "    RM $@" ;
      QUIET_TAGS = @ echo "    TAGS $@" ;
      QUIET_WINDRES = @ echo "    WINDRES $@" ;
      QUIET_OBJCOPY = @ echo "    OBJCOPY $@" ;
      QUIET_DLLTOOL = @ echo "    DLLTOOL $@" ;
      QUIET_GENDEF = @ echo "    GENDEF $@" ;
    endif
    
    MKTGTDIR = mkdir -p $(dir $@)
    LINK_CMD = $(QUIET_LINK) $(MKTGTDIR) ; $(CC) $(LDFLAGS) -o $@ $^ $(CFLAGS) $(INCLUDES)
    AR_CMD = $(QUIET_AR) $(MKTGTDIR) ; $(AR) cr $@ $^
    
    # --- Rules ---
    
    $(OUT_DIR)/%.a :
    	$(AR_CMD)
    
    $(OUT_DIR)/%.so:
    	$(LINK_CMD)
    
    HDD_Code_LIB = $(OUT_DIR)/libhdd_code_api.so
    
    SOURCES := $(sort $(wildcard src/*.cpp))
    SOURCES += $(sort $(wildcard 3rdparty/aes/*.cpp))
    SOURCES += $(sort $(wildcard 3rdparty/bch/*.c))
    SOURCES += $(sort $(wildcard 3rdparty/md5/*.cpp))
    
    $(HDD_Code_LIB) : $(SOURCES)
    LIBS_TO_INSTALL_IN_LIB = $(HDD_Code_LIB)
    
    DEMO = test/test_api.cpp
    LIBS_TO_INSTALL_IN_BIN = demoApi
    
    LIBS = -L$(OUT_DIR) -lhdd_code_api -Wl,-rpath=$(OUT_DIR) -Wl,-rpath-link=$(OUT_DIR) 
    LIBS += $(XLIBS)
    
    $(LIBS_TO_INSTALL_IN_LIB): $(SOURCES) 
    	$(CC) -o $@ $^ $(INCLUDES) $(CFLAGS) -shared
    
    $(LIBS_TO_INSTALL_IN_BIN): $(DEMO)
    	$(CC) -o $@ $^ $(INCLUDES) $(CFLAGS) $(LIBS)
    
    libs: $(LIBS_TO_INSTALL_IN_LIB) 
    apps: $(LIBS_TO_INSTALL_IN_BIN) 
    
    # prefix ?= build/local
    # bindir ?= $(prefix)/bin
    # libdir ?= $(prefix)/lib
    # incdir ?= $(prefix)/include
    # install: libs apps
    # 	install -d $(DESTDIR)$(incdir)/
    # 	install -m 644 include/*.h $(DESTDIR)$(incdir)/
    
    # ifneq ($(LIBS_TO_INSTALL_IN_LIB),)
    # 	install -d $(DESTDIR)$(libdir)
    # 	install -m 644 $(LIBS_TO_INSTALL_IN_LIB) $(DESTDIR)$(libdir)
    # endif
    # 	install -d $(DESTDIR)$(bindir)
    # 	install -m 755 $(LIBS_TO_INSTALL_IN_BIN) $(DESTDIR)$(bindir)
    
    all: libs apps
    clean:
    	rm -f $(LIBS_TO_INSTALL_IN_LIB)
    	rm -f $(LIBS_TO_INSTALL_IN_BIN)
    rebuild: clean build
    
    # Avoid conflicts with files of the same name
    .PHONY: all clean libs apps
    
  • gcc编译的头文件路径

    #gcc
    C_INCLUDE_PATH=$C_INCLUDE_PATH:your_path
    export C_INCLUDE_PATH
    #g++
    CPLUS_INCLUDE_PATH=$CPLUS_INCLUDE_PATH:your_path
    export CPLUS_INCLUDE_PATH
    
  • 重启终端即可生效, 可用以下命令查看搜索路径

    echo | gcc -x c -v -E -
    echo | gcc -x c++ -v -E -
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值