1.Makefile文件命令的使用
一般有两种用法
#1
make
#2
make command
第一种用法会自动执行Makefile中的所有指令,第二种用法会执行Makefile中的指定指令。
2.Makefile文件命令的一般写法
目标: 依赖项1 依赖项2
(tab)命令1
(tab)命令2
(tab)......
例如:
helloworld: main.cpp
g++ -c main.cpp -o main.o
g++ main.o -o helloworld
clean:
rm -rf main.o
3.Makefile中的变量
OBJS = programA.o programB.o
OBJS-ADD = $(OBJS) programC.o
OBJS-ADD += programD.o
其中OBJS,OBJS-ADD都表示字符串变量,可用'='赋值。
$(变量)表示取得该变量的值。
+=表示对字符串变量追加字符串操作。
4.Makefile中的自动变量
$@ #1指代目标集合
$< #2指代第一个依赖项
$? #3指代比目标新的依赖目标的集合
$^ #4指代所有依赖目标的集合, 会去除重复的依赖目标
$+ #5指代所有依赖目标的集合, 不会去除重复的依赖目标
#1指代目标集合
#2指代第一个依赖项
#3指代比目标新的依赖目标的集合
#4指代所有依赖目标的集合, 会去除重复的依赖目标
#5指代所有依赖目标的集合, 不会去除重复的依赖目标
5.Makefile中函数的使用
一般的函数调用语法
$(<function> <arguments1>,<arguments2>...)
# 或者
${<function> <arguments1>,<arguments2>...}
function是函数名,arguments是函数参数。
5.Makefile中常用的函数
字符串替换函数: $(subst <from>,<to>,<text>)
功能: 把字符串<text> 中的 <from> 替换为 <to>
返回: 替换过的字符串
# Makefile 内容
all:
@echo $(subst t,e,maktfilt) <-- 将t替换为e
# bash 中执行 make
$ make
makefile
模式字符串替换函数: $(patsubst <pattern>,<replacement>,<text>)
功能: 查找<text>中的单词(单词以"空格", "tab", "换行"来分割) 是否符合 <pattern>, 符合的话, 用 <replacement> 替代.
返回: 替换过的字符串
# Makefile 内容
all:
@echo $(patsubst %.c,%.o,programA.c programB.c)
# bash 中执行 make
$ make
programA.o programB.o
执行内部指令函数: $(shell <shell command>)
它的作用就是执行一个shell命令, 并将shell命令的结果作为函数的返回.
作用和 `<shell command>` 一样, ` 是反引号
模式文件列表函数$(wildcard <pattern>)
功能:获取工作目录下匹配<pattern>模式的所有文件列表
返回:获取到的文件列表
# Makefile 内容
all:
@echo $(wildcard *.c)
# bash 中执行 make
$ make
programA.c programB.c
6.Makefile中的通配符
- * :: 表示任意一个或多个字符
- ? :: 表示任意一个字符
- [...] :: ex. [abcd] 表示a,b,c,d中任意一个字符, [^abcd]表示除a,b,c,d以外的字符, [0-9]表示 0~9中任意一个数字
- ~ :: 表示用户的home目录
7.Makefile 命令前缀
Makefile 中书写shell命令时可以加2种前缀 @ 和 -, 或者不用前缀.
3种格式的shell命令区别如下:
- 不用前缀 :: 输出执行的命令以及命令执行的结果, 出错的话停止执行
- 前缀 @ :: 只输出命令执行的结果, 出错的话停止执行
- 前缀 - :: 命令执行有错的话, 忽略错误, 继续执行
8.Makefile头文件依赖
g++ -c -MMD main.cpp -o main.o
该指令在编译main.cpp时会生成一个main.d的文件,其内容为main.cpp的所有依赖项。
进而我们可以使用指令符"-include"将其包含进来
#DEP_FILE为.d文件的文件列表
-include$(DEP_FILE)
实现头文件依赖
9.使Makefile支持多个子目录
该处使用foreach函数实现
CXX_SOURCES = $(foreach dir,$(SUBDIR),$(wildcard $(dir)/*.cpp))
dir为变量,SUBDIR为目录列表,该函数依次访问SUBDIR中的各个目录,创建.cpp文件列表。
10.已经写好的Makefile模板
#单个目录下的全自动Makefile
#EXE表示生成的可执行文件的文件名,此处以helloworld为例
EXE = helloworld
CXX_SOURCES = $(wildcard *.cpp)
CXX_OBJECTS = $(patsubst %.cpp, %.o, $(CXX_SOURCES))
DEP_FILES = $(patsubst %.o, %.d, $(CXX_OBJECTS))
$(EXE): $(CXX_OBJECTS)
g++ $(CXX_OBJECTS) -o $@
%.o: %.cpp
g++ -c -MMD $< -o $@
-include $(DEP_FILES)
clean:
rm -rf $(CXX_OBJECTS) $(DEP_FILES) $(EXE)
#多个目录下的半自动Makefile
#EXE表示生成的可执行文件的文件名,此处以helloworld为例
#SUBDIR为目录列表,需手动添加
#该Makefile应放置在项目目录下
EXE = helloworld
SUBDIR = src object
#CXX_SOURCES = $(wildcard *.cpp)
CXX_SOURCES = $(foreach dir,$(SUBDIR),$(wildcard $(dir)/*.cpp))
CXX_OBJECTS = $(patsubst %.cpp, %.o, $(CXX_SOURCES))
DEP_FILES = $(patsubst %.o, %.d, $(CXX_OBJECTS))
$(EXE): $(CXX_OBJECTS)
g++ $(CXX_OBJECTS) -o $@
%.o: %.cpp
g++ -c -MMD $< -o $@
-include $(DEP_FILES)
clean:
rm -rf $(CXX_OBJECTS) $(DEP_FILES) $(EXE)
本文部分借鉴了https://www.cnblogs.com/wang_yb/p/3990952.html
上述博主总结的比本人更加完整,全面。