深入Makefile解析及模板
一. Makefile 基础知识
1.1. makefile常见符号
$@ 表示目标文件
$^ 表示所有的依赖文件
$< 表示第一个依赖文件
$? 表示比目标还要新的依赖文件列表
1.2. 关于等于号
+=的含义显而易见,将右值增加到左边的变量基础上。空格是自动添加的。
=的含义是在右值在遍历整个Makefile,完全展开后再赋值给左边的变量。
?=的含义是如果左值未被赋值过,则将右值赋值给它,可见这里y不会再被赋值一次。
:=的含义是将右值当前的值赋值给左值,不会遍历Makefile获取右值的最终值
1.3. makefile 重要规则
1.3.1. 每条规则前面都要用tab缩进
1.3.2. 第一条规则的目标是“终极目标”,也就是直接执行make时默认使用的规则,比如此处就是test
1.3.3. 关于@:用echo xxx会输出“echo xxx”,用@echo xxx才会会出“xxx”
1.3.4. 关于-:删除不存在的文件会出错导致make终止,前面加上-表示忽略可能的错误
1.3.5. clean并不是目标文件,而是希望make执行清除操作;通过.PHONY把clean标记成伪目标,避免了当前目录下真的有文件clean时,由于没有更“新”的依赖文件,导致清除操作不执行
1.4. Makefile 默认符号
@echo $(CXX)
@echo $(CC)
@echo $(AR)
@echo $(RM)
@echo $(CXXFLAGS)
@echo $(CFLAGS)
@echo $(ARFLAGS)
二. Makefile 模板
2.1. 单文件项目
all: Hello Hello: gcc -o Hello hello.c clean: rm -rf Hello
2.2. 多文件项目
1. 假设一个工程下,有main.c和有多个.c源文件以及同名的.h头文件,虽然可以类似上述例子一样把每条gcc语句都写出来,但是这么就太啰嗦了。可以使用一些Makefile自带的规则简化着写
# 方便起见一般都会先定义编译器链接器 CC = gcc LD = gcc # 正则表达式表示目录下所有.c文件,相当于:SRCS = main.c a.c b.c SRCS = $(wildcard *.c) # OBJS表示SRCS中把列表中的.c全部替换为.o,相当于:OBJS = main.o a.o b.o OBJS = $(patsubst %c, %o, $(SRCS)) # 可执行文件的名字 TARGET = Hello # .PHONE伪目标,具体含义百度一下一大堆介绍 .PHONY:all clean # 要生成的目标文件 all: $(TARGET) # 第一行依赖关系:冒号后面为依赖的文件,相当于Hello: main.o a.o b.o # 第二行规则:$@表示目标文件,$^表示所有依赖文件,$<表示第一个依赖文件 $(TARGET): $(OBJS) $(LD) -o $@ $^ # 上一句目标文件依赖一大堆.o文件,这句表示所有.o都由相应名字的.c文件自动生成 %o:%c $(CC) -c $^ # make clean删除所有.o和目标文件 clean: rm -f $(OBJS) $(TARGET)
2. 指定头文件目录以及库文件目录(假设程需要用到libs目录下的libtomcrypt.a静态库和include目录下libtom的头文件)
CC = cc LD = cc SRCS = $(wildcard *.cpp) OBJS = $(patsubst %cpp, %o, $(SRCS)) # -I指定头文件目录 INCLUDE = -I./include # -L指定库文件目录,-l指定静态库名字(去掉文件名中的lib前缀和.a后缀) LIB = -L./libs -ltomcrypt # 开启编译warning和设置优化等级 CFLAGS = -Wall -O2 TARGET = LibtomDemo .PHONY:all clean all: $(TARGET) # 链接时候指定库文件目录及库文件名 $(TARGET): $(OBJS) $(LD) -o $@ $^ $(LIB) # 编译时候指定头文件目录 %o:%cpp $(CC) -c $^ $(INCLUDE) $(CFLAGS) clean: rm -f $(OBJS) $(TARGET)
三. linux下C/C++编译时系统搜索 include 和 链接库 文件路径的指定
四. 实战
#Target TARGET = test INCLUDES := -I./includes SRCS := $(wildcard *.cpp xxxDir/*.cpp yyyDir/*.cpp) OBJS := $(patsubst %cpp, %o, $(SRCS)) USEDLIB := -lxxx #Compilers CXX := $(CROSS_PREFIX)g++ CPPFLAGS = -std=c++11 -g -Wall -O0 LD_LIBRARY_PATH := -L$(shell pwd)/.. .PHONY: all #Rules all: $(TARGET) @echo $(INCLUDES) @echo $(SRCS) @echo $(OBJS) $(TARGET): $(OBJS) $(CXX) -o $@ $? $(LD_LIBRARY_PATH) $(USEDLIB) %.o: %.cpp $(CXX) -c $^ -o $@ $(INCLUDES) $(CPPFLAGS) .PHONY: clean clean: rm -f $(OBJS) $(TARGET)
参考文献:https://blog.csdn.net/shaosunrise/article/details/79968921