Makefile中的ifeq
多条件判断
ifeq ($(TARGET_ARCH), arm) LOCAL_SRC_FILES := ... else ifeq ($(TARGET_ARCH), x86) LOCAL_SRC_FILES := ... else ifeq ($(TARGET_ARCH), mips) LOCAL_SRC_FILES := ... else LOCAL_SRC_FILES := ... endif
删除中间文件:
clean: rm -f $(ALL_OBJS)
或:
.PHONY : clean
clean :
-rm edit $(objects)
1、在rm命令前面加了一个小减号的意思就是,也许某些文件出现问题,但不要管,继续做后面的事。当然,clean的规则不要放在文件的开头,不然,这就会变成make的默认目标,——“clean从来都是放在文件的最后”。
在Makefile的命令行前加一个减号“-”(在Tab键之后),标记为不管命令出不出错都认为是成功的。如:
2、还有一个全局的办法是,给make加上“-i”或是“--ignore-errors”参数,那么,Makefile中所有命令都会忽略错误。
3、而如果一个规则是以“.IGNORE”作为目标的,那么这个规则中的所有命令将会忽略错误。
4、make的参数的是“-k”或是“--keep-going”,这个参数的意思是,如果某规则中的命令出错了,那么就终目该规则的执行,但继续执行其它规则。
这些是不同级别的防止命令出错的方法,你可以根据你的不同喜欢设置。
为了避免和文件重名的这种情况,我们可以使用一个特殊的标记“.PHONY”来显示地指明一个目标是“伪目标”,向make说明,不管是否有这个文件,这个目标就是“伪目标”
make是如何工作的
在默认的方式下,也就是我们只输入make命令。那么,
- make会在当前目录下找名字叫“Makefile”或“makefile”的文件。
- 如果找到,它会找文件中的第一个目标文件(target),并把这个文件作为最终的目标文件。
- 如果目标文件不存在,或是目标文件所依赖的后面的 .o 文件的修改时间要比目标文件新,那么,他就会执行后面所定义的命令来生成目标文件。
- 如果目标文件所依赖的.o文件也存在,那么make会在当前文件中找目标为.o文件的依赖性,如果找到则再根据那一个规则生成.o文件。(这有点像一个堆栈的过程)
- 当然,你的C文件和H文件是存在的啦,于是make会生成 .o 文件,然后再用 .o 文件声明make的终极任务,也就是执行目标文件。
冒号(:)表示依赖关系
反斜杠(\)是换行符的意思
Makefile中的命令,必须要以[Tab]键开始,除非,命令是紧跟在依赖规则后面的分号后的
波浪号(“~”)字符在文件名中也有比较特殊的用途。如果是“~/test”,这就表示当前用户的$HOME目录下的test目录。
“%.h”表示所有以“.h”结尾的文件
如果make执行时,带入make参数“-n”或“--just-print”,那么其只是显示命令,但不会执行命令,这个功能很有利于我们调试我们的Makefile
参数“-s”或“--slient”则是全面禁止命令的显示。
如果你要让上一条命令的结果应用在下一条命令时,你应该使用分号分隔这两条命令。比如你的第一条命令是cd命令,你希望第二条命令得在cd之后的基础上运行,那么你就不能把这两条命令写在两行上,而应该把这两条命令写在一行上,用分号分隔。如: cd /home/hchen; pwd
$@ 表示目标文件
$^ 表示所有的依赖文件
$< 表示第一个依赖文件
$? 表示比目标还要新的依赖文件列表
vpath %.h ../headers
该语句表示,要求make在“../headers”目录下搜索所有以“.h”结尾的文件。(如果某文件在当前目录没有找到的话)
cc -MM main.c -M选项,即自动找寻源文件中包含的头文件,并生成一个依赖关系。
如果你使用GNU的C/C++编译器,你得用“-MM”参数,不然,“-M”参数会把一些标准库的头文件也包含进来。
.c.o: gcc -c $< .c.o: 这个规则表示所有的 .o文件都是依赖与之相应的.c文件。例如mytool.o 依赖于 mytool.c
编译的四个阶段:
-E:仅执行编译预处理;
-c:仅执行编译操作,不进行链接操作;
-S:将C代码转换为汇编代码;
-o:指定生成的输出文件。
-C 在预处理的时候,不删除注释信息,一般和-E使用,有时候分析程序,用这个很方便的
编译、链接
一般来说,无论是C、C++、还是pas,首先要把源文件编译成中间代码文件,在Windows下也就是.obj文件,UNIX下是.o文件,即Object File,这个动作叫做编译(compile)。
然后再把大量的Object File合成执行文件,这个动作叫作链接(link)。
编译时,编译器需要的是语法的正确,函数与变量的声明的正确。对于后者,通常是你需要告诉编译器头文件的所在位置(头文件中应该只是声明,而定义应该放在C/C++文件中),只要所有的语法正确,编译器就可以编译出中间目标文件。一般来说,每个源文件都应该对应于一个中间目标文件(O文件或是OBJ文件)。
链接时,主要是链接函数和全局变量,所以,我们可以使用这些中间目标文件(O文件或是OBJ文件)来链接我们的应用程序。链接器并不管函数所在的源文件,只管函数的中间目标文件(Object File),在大多数时候,由于源文件太多,编译生成的中间目标文件太多,而在链接时需要明显地指出中间目标文件名,这对于编译很不方便,所以,我们要给中间目标文件打个包,在Windows下这种包叫“库文件”(LibraryFile),也就是 .lib文件,在UNIX下,是Archive File,也就是 .a文件。
= 是最基本的赋值
:= 是覆盖之前的值
?= 是如果没有被赋值过就赋予等号后面的值
+= 是添加等号后面的值
1、“=”
make会将整个makefile展开后,再决定变量的值。也就是说,变量的值将会是整个makefile中最后被指定的值。看例子:
x = foo
y = $(x) bar
x = xyz
在上例中,y的值将会是 xyz bar ,而不是 foo bar 。
2、“:=”
“:=”表示变量的值决定于它在makefile中的位置,而不是整个makefile展开后的最终值。
x := foo
y := $(x) bar
x := xyz
在上例中,y的值将会是 foo bar ,而不是 xyz bar 了。