Linux环境下的程序员如果不会使用GNU make来构建和管理自己的工程,应该不能算是一个合格的专业程序员,至少不能称得上是 Unix 程序员。
在 Linux(unix)环 境下使用 GNU 的 make 工具能够比较容易的构建一个属于你自己的工程,整个工程的 编译只需要一个命令就可以完成编译、连接以至于最后的执行。不过这需要我们投入一 些时间去完成一个或者多个称之为 Makefile 文件的编写。
在执行 make 之前,需要一个命名为 Makefile 文件来告诉 make 需要做什么(完成什么任务),该 怎么做。通常,make 工具主要被用来进行工程编译和程序链接。
当使用 make 工具进行编译时,工程中以下几种文件在执行 make 时将会被编译(重新编译):
1.所有的源文件没有被编译过,则对各个C源文件进行编译并进行链接,生成最 后的可执行程序;
2.每一个在上次执行make之后修改过的C源代码文件在本次执行make时将会 被重新编译;
3.头文件在上一次执行make之后被修改。则所有包含此头文件的C源文件在本 次执行 make 时将会被重新编译。
后两种情况是 make 只将修改过的 C 源文件重新编译生成 .o 文件,对于没有修改 的文件不进行任何工作。重新编译过程中,任何一个源文件的修改将产生新的对应的 .o 文件,新的 .o 文件将和以前的已经存在、此次没有重新编译的 .o 文件重新连接生成最 后的可执行程序。
总得来说Makefile的用途:
目标:依赖 (tab)命令 #例如: add.o:add.c (一个tab缩进)gcc -Wall -g -c add.c -o add.o
目标:要生成的目标文件
依赖:目标文件由哪些文件生成
命令:通过执行该命令由依赖文件生成目标
Makefile工作原理
基本原则:
- 若想生成目标,检查规则中的依赖条件是否存在,若不存在,就寻找是否有规则用来生成依赖文件
- 检查规则中的目标是否需要更新,必须先检查他的所有依赖,依赖中有任一个被更新,则目标必须更新
分享各个目标和依赖之间的关系
根据依赖关系自底向上执行命令
根据修改文件最后修改时间如果比目标文件新,那么就确定更新
如果目标不依赖任何条件,则执行对应命令,以示更新
Makefile变量
在makefile中使用变量有点类似于 C语言中的宏定义,使用该变量相当于内容替换,使用变量可以是makefile抑郁维护,修改内容变得简单。
变量的定义和使用:
foo = abc #变量定义之间使用 ‘=’ bar = $(foo) #使用变量值用 $(变量名)
定义了两个变量foo和bar,其中bar的值是foo变量值的引用。
通常我们在makefile中会定义一些变量,方便makefile的修改维护
src = main.c func1.c func2.c CC = gcc #arm-linux-gcc CPPFLAGS : C预处理的选项 如:-I CFLAGS : C编译器的选项 –Wall –g -c LDFLAGS : 链接器选项 –L -l
自动变量:
- $@ : 表示规则中的目标
- $< : 表示规则中的第一个条件
- $^ : 表示规则中的所有条件,组成一个列表,以空格隔开,如果这个列表中有重复的项则消除重复项。
模式规则:
至少在规则的目标定义中要包含‘%’,% 表示一个或者多个,在依赖条件中同样可以使用 ‘%’,依赖条件中的 % 的取值,取决于其目标。
%.o:%.c $(CC) –c $(CFLAGS) $(CPPFLAGS) $< -o $@ #其中,“$@”表示依次取出目标值,$<表示依次取出依赖条件。
注意:只有写成模式规则的时候,$<才表示了所有依赖条件的依次取值,否则只是取依 赖条件中的第一个。
Makefile 函数
GNU make 函数的调用格式类似于变量的引用,以“$”开始表示一个引用。语法
格式如下:
$(FUNCTION ARGUMENTS)
或者:
${FUNCTION ARGUMENTS}
src = $(wildcard *.c) #找到当前目录下所有后缀为.c的文件,赋值给src obj = $(patsubst %.c,%.o, $(src)) #把src变量里所有后缀为.c的文件替换成.o
make clean
用途:清除编译生成的中间.o文件和最终目标文件
#clean的用途演示 clean: rm *.o temp
但是如果在当前工作目录下存在文件“clean”,情况就不一样了,同样我们输入 “make clean”,由于这个规则没有任何依赖文件,所以目标被认为是最新的而不去执 行规则所定义的命令,因此命令“rm”将不会被执行。
这并不是我们的初衷。为了解 决这个问题,我们需要将目标“clean”声明为伪目标。将一个目标声明为伪目标的方 法是将它作为特殊目标.PHONY”的依赖。如下:
.PHONY : clean
这样目标“clean”就被声明为一个伪目标,无论在当前目录下是否存在“clean”这个 文件。我们输入“make clean”之后。“rm”命令都会被执行。
make常用参数
- make 默认执行第一个出现的目标,可通过make dest指定要执行的目标distclean目标
- install目标
- make -C 指定目录 进入指定目录,调用里面的Makefile
- make -n:只打印要执行的命令,不会真正执行命令
- make -p:显示隐含规则数据库中的信息
- make -C:切换到另一个目录中执行该目录下的Makefile
- make -f:-f执行一个makefile文件名称,使用make执行指定的makefile