第三章 Makefile 快速入门
注意:makefile 仅仅是一个编译期的一个过程,随时可以修改,应尽量简单化,避免太复杂的逻辑,修改不便。 从工程中来看makefile 尽量在短时间内完成需要的时候可以修改。不用占据很长世间。 在这里我强烈建议手写makefile ,避免使用automaker autoconfig 之类的工具生成makefile 即使编译出错手写的也容易检查。本文只列出常用makefile 特性,对于其它不常用的建议参考gun make手册。
(1) makefile 的三条规则
1> 如果这个工程没有编译过,那么我们的所有C文件都要编译并被链接。
2> 如果这个工程的某几个C 文件被修改,那么我们只编译被修改的C 文件,并链接目标程序。
3> 如果这个工程的头文件被改变了,那么我们需要编译引用了这几个头文件的C 文件,并链接目标程序。
(2) makefile 的基本格式
TARGET... : PREREQUISITES...
COMMAND
TARGET 代表目标文件 ,可以是可执行文件 ,中间文件*.o 或者伪目标
PREREQUISITES 生成目标文件所依赖的文件
COMMAND 编译命令
注意:每一个命令行必须以[Tab]字符开始,[Tab] 字符告诉make此行是一个命令行。
main : main.o add.o gcc main.o add.o -O main add.o : add.c add.h gcc -c test.c main.o : main.c add.h gcc -c main.c clean: rm *.o
(3) make 工作方式
1> make会在当前目录下找名字叫“Makefile” 或“makefile”的文件。
2> 如果找到,它会找文件中的第一个目标文件(target ),在上面的例子中,他会找到“main”这个文件,并把这个文件作为最终的目标文件。
3> 如果main文件不存在,或是 main所依赖的后面的 .o 文件的文件修改时间要比 main这个文件新,那么,他就会执行后面所定义的命令来生成main。
4> 如果main所依赖的.o 文件也存在,那么 make会在当前文件中找目标为.o 文件的依赖性,如果找到则再根据那一个规则生成.o 文件。
5> 当然,你的 C 文件和H 文件是存在的啦,于是make会生成 .o 文件,然后再用 .o 文件生命make的终极任务,也就是执行文件edit 了
(4) 通配符使用
* ? [...] ~ 注意 以~开始的文件名代表当前用户的宿主目录 可以通过 echo ~ 查看
(5) 目录搜寻
1> 一般搜寻 VPATH 变量 VPATH = src:../headers 注意目录以:隔开
2> 选择性搜寻
vpath PATTERN DIRECTORIES 为所有符合模式“PATTERN”的文件指定搜索目录“DIRECTORIES ”。多个目录使用空格或者冒号(:)分开。
vpath PATTERN 清除之前为符合模式“PATTERN”的文件设置的搜索路径。
vpath 清除所有已被设置的文件搜索路径
eg: vpath %.h ../headers
3> 库文件和搜寻目录
依赖规则中书写-lNAME
eg: foo : foo.c -lcurses ;cc $^ -o $@
目录搜寻过程 当前路径->VPATH顺序路径 对于库文件继续搜索 "/lib" ->"/usr/lib" 库文件先按搜索路径搜索动态库,在搜索静态库。
(6)伪目标
规则所定义的命令不是去创建目标文件,而是通过make命令行明确指定它来执一些特定的命令。
eg: clean:
rm *.o temp
.PHONY : clean
(7) make 的递归执行
subsystem:
cd subdir && $(MAKE) 或者 $(MAKE) -C subdir
(8) 变量
1> 自定义变量 VAR=main.o add.o 使用变量 $(VAR) 建议变量用大些字母表示
VAR = main.o 递归展开式
VAR := main.o 直接展开式
VAR ?= main.o 没有定义则赋值
VAR += main.o 追加赋值
2> 自动化变量
$@ 表示规则的目标文件名
$< 规则依赖所有的文件名
(9)make 隐含规则与隐含变量
1> 命令变量
AR 函数库打包程序,可创建静态库.a 文档。默认是“ar ”
AS 汇编程序。默认是“as”。
CC C编译程序。默认是“cc”。
CXX C++ 编译程序。默认是“g++ ”
RM 删除命令。默认是“rm -f”。
2> 参数变量
ARFLAGS 执行“AR”命令的命令行参数。默认值是“rv ”
ASFLAGS 执行汇编语器“AS”的命令行参数
CFLAGS 执行“CC”编译器的命令行参数(编译.c 源文件的选项)
CXXFLAGS 执行“g++ ”编译器的命令行参数(编译.cc 源文件的选项)。
3> 模式规则
%.o : %.c ; COMMAND...
eg : %.o : %.c
$(CC) -c $(CFLAGS) $( CPPFLAGS) $< -o $@
(10) makefile举例
这里不再单独举例书写makefile ,放到后面的代码编写之中,对应相应的工程做makefile 更为实际。