makefile——基础

makefile好处

makefile 定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作,比如可以执行操作系统的命令。

makefile可以带来自动化编译的好处,一旦写好,只需要一个 make 命令,整个工程完全自动编译,极大的提高了软件开发的效率。makefile 可以说已成为了一种在工程方面的编译方法。

程序编译与连接

程序编译的一些规范和方法,一般来说,首先要把源文件编译成中间目标文件,这个动作叫做编译(compile),然后再把大量的中间目标文件合成执行文件,这个动作叫作链接(link)。

编译时,编译器需要的是语法的正确,函数与变量的声明的正确。通常需要告诉编译器头文件的所在位置,只要所有的语法正确,编译器就可以编译出中间目标文件,一般来说,每个源文件都应该对应于一个中间目标文件。

链接时,主要是链接函数和全局变量,使用中间目标文件来链接我们的应用程序。链接器并不管函数所在的源文件,只管函 数的中间目标文件,由于存在源文件太多,编译生成的中间目标文件太多的情况,而在链接时需要明显地指出中间目标文件名,这对于编译很不方便, 这时我们需要给中间目标文件打个包,在Windows下这种包叫“库文件”(Library File),也就是.lib文件,在Linux下,是 Archive File,也就是.a文件。

总结:程序的源文件首先会生成中间目标文件,再由中间目标文件生成执行文件。在编译时,编译器只检测程序语法,和函数、变量是否被声明,如果函数未被声明,编译器会给出一个警告,但是可以生成中间目标文件;而在链接程序时,链接器会在所有的中间目标文件中找寻函数的实现,如果找不到,那到就会报链接错误码(Linker Error),也就是链接器未能找到函数的实现。

makefile规则

make 命令执行时,需要一个 makefile 文件,以告诉 make 命令需要怎么样的去编译和链接程序。

  • 如果这个工程没有编译过,那么我们的所有文件都要编译并被链接。
  • 如果这个工程的某几个文件被修改,那么我们只编译被修改的文件,并链接目标程序。
  • 如果这个工程的头文件被改变了,那么我们需要编译引用了这几个头文件的文件, 并链接目标程序。
target ... : prerequisites ...
command
...

说明:prerequisites (所需要的文件或目标)中如果有一个以上的文件比 target (目标文件,可以是中间目标文件,也可以是执行文件,还可以是一个标签)文件要新的话,command (make需要执行的命令)所定义的命令就会被执行,这就是 makefile 的规则。
示例:

	test : main.o
	cc -o test main.o

	main.o : main.cpp def.h 
	cc -c main.cpp

clean :
	rm test main.o #每一行文本除非顶头开始,如果需要格式编排,必须以Tab键作为开头

将这段内容保存到makefile文件中,然后使用命令"make",即可生成执行文件test,如果要删除执行文件或所有的中间目标文件,使用命令"make clean"。

上述示例很好的定义了依赖关系,依赖关系的实质上就是说明了目标文件是由哪些文件生成的,或者说目标文件是哪些文件更新的。make 并不管命令是怎么工作的,他只管执行所定义的命令,make 会比较 targets 文件和 prerequisites 文件的修改日期,如果 prerequisites 文件的日期要比 targets 文件的日期要新,或者 target 不存在的话,make 就会执行后续定义的命令。

clean 不是一个文件,只是一个动作名字,就像是标签,要执行其后的命令,就要在 make 命令后明显的指出这个名字。这样就可以在一个 makefile 中定义不用的编译或是和编译无关的命令。

make命令

make命令工作方式:

  • make 会在当前目录下找名字叫“makefile”的文件
  • 如果找到,它会找文件中的第一个目标文件(target),并把这个文件作为最终的目标文件。
  • 如果最终的目标文件不存在,或是最终的目标文件所依赖的后面的文件的修改时间要比最终的目标文件新,那么,他就会执行后面所定义的命令来生成最终的目标文件。
  • 如果最终的目标文件所依赖的文件存在,那么 make 会在当前文件中找目标为中间目标文件的依赖性,如果找到,则再根据规则生成中间目标文件,然后再根据中间目标文件生成最终目标文件

在找寻的过程中,如果出现错误,比如最后被依赖的文件找不到, 那么 make 就会直接退出,并报错,而对于所定义的命令的错误,或是编译不成功,make 根本不理,make 只管文件的依赖性

makefile变量

makefile 的变量也就是一个字符串,相当于 C 语言中的宏。
示例:

OBJECTS = main.o
	test : $(OBJECTS)
	cc -o test $(OBJECTS)

	main.o : main.cpp def.h 
	cc -c main.cpp

clean :
	rm test $(OBJECTS) #每一行文本除非顶头开始,如果需要格式编排,必须以Tab键作为开头

简化makefile文件内容

make是可以自动推导文件以及文件依赖关系后面的命令的
示例:

OBJECTS = main.o
	test : $(OBJECTS)
	cc -o test $(OBJECTS)

	main.o : main.cpp def.h
	.PHONY : clean #表示clean是一个伪目标文件
clean :
	rm test $(OBJECTS) #每一行文本除非顶头开始,如果需要格式编排,必须以Tab键作为开头

目标文件清空规则

示例:

	...
	.PHONY : clean
clean :
	-rm edit $(OBJECTS) #有个"-"的意思是不管文件有无问题,继续做后面的事

文件开头一般是放make的默认目标,那么通常 clean 从来都是放在文件的最后。每个 makefile 中都应该写一个清空目标文件的规则,这不仅便于重编译,也利于保持生成文件的整洁干净。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值