- 一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作
- makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。
- make是一个命令工具,是一个解释makefile中指令的命令工具,一般来说,大多数的IDE都有这个命令,比如:Delphi的make,Visual C++的nmake,Linux下GNU的make。可见,makefile都成为了一种在工程方面的编译方法。
- make是一条命令,makefile是一个文件,两个搭配使用,完成项目自动化构建。
make/makefile实例代码
每次编译文件都要[ gcc -o 目标文件 源文件] 非常的麻烦。
首先我们要创建一个makefile的文件夹.
touch makefile
首字母大小写都可以
touch Makefile
我们首先 vim makefile 打开makefile文件夹写上这样两行命令。
写完之后我们可以直接通过make命令生成可执行,它可以代替我们执行gcc命令。
makefile的本质是依赖方法和依赖关系的结合。我们要做成一件事,都必须有依赖关系+依赖方法。
如下:
写上这样的代码则可以通过执行 [make clean] 完成资源的清理。
因为[porc:]与[clean:]是两组依赖关系所以我们也能这样执行proc:
理解make/makefile基本原理
如果交换了proc与clean目标的顺序,make执行的就是clean(make默认执行的是makefile文件中的第一个目标名)
- makefile文件,会被make从上到下开始扫描,第一个目标名,是缺省形成的。如果我们想执行其他组的依赖关系和依赖方法:make [name]
- makefile在执行gcc命令的时候,如果发生了语法错误,就会中中止推导过程。
依赖方法可以是任意指令
依赖方法可以是任意指令,如果我们将其改成如下:
执行make 就会输出haha.
如何不打印所执行的命令
如果想要不打印我们所执行的命令,我们可以在每一条命令之前带上@符号。
因此我们可以进行一些骚操作:
为什么连续运行make有时不执行命令
如果我们连续运行make,就会报错(proc已经是最新生成的文件)
只需改成下面这样
因为.PHONY:让目标文件,对应的方法,总是被执行。
我们将代码改回去:
接下来我们更改proc.c中的代码
为什么make编译的时候有时候需要重新编,有时候又不需要重新编?
这是因为make会检查源文件的属性与可执行文件的属性。
进行chmod操作,发现文件属性时间进行了修改 。
对文件进行cat访问,access时间进行了修改。
我们更改源文件里面的内容的话:就会发现内容时间与属性时间都进行了更改,这是正常的,因为文件大小发生了变化。
所以可以知道可执行程序的内容修改时间(Modify)一定是比源文件的要新的,一旦源文件内容发生了修改就可以重新编译。
.PHONY:让依赖方法,忽略掉时间的对比,总是被执行。
证明:
make是如何工作的
make的推导
看下面代码:
make执行的时候明明没有 proc.o 目标文件为什么能生成proc可执行文件?
因为make解释makefile的时候,是会自动推导的。
proc.o不存在则会寻找proc.o的生成方式,将依赖方法入栈。proc.o需要由proc.s来生成,proc.s不存在则会找它的生成方式,一直到proc.i生成,然后命令依次执行,依次执行完成出栈。
- make解释makefile的时候,是会自动推导的,一直推导,推导过程不执行依赖方法,直到推导到有依赖文件存在,然后在逆向的执行所有依赖方法。
不过一般我们不会向上面那样写。如下:
make是如何工作的,在默认的方式下,也就是我们只输入make命令。那么,
- 1. make会在当前目录下找名字叫“Makefile”或“makefile”的文件。
- 2. 如果找到,它会找文件中的第一个目标文件(target),在上面的例子中,他会找到“proc”这个文件,并把这个文件作为最终的目标文件。
- 3. 如果proc文件不存在,或是proc所依赖的后面的proc.o文件的文件修改时间要比hello这个文件新(可以用 touch 测试),那么,他就会执行后面所定义的命令来生成proc这个文件。
- 4. 如果proc所依赖的proc.o文件不存在,那么make会在当前文件中找目标为proc.o文件的依赖性,如果找到则再根据那一个规则生成proc.o文件。(这有点像一个堆栈的过程)
- 5. 当然,你的C文件和H文件是存在的啦,于是make会生成 proc.o 文件,然后再用 proc.o 文件声明make的终极任务,也就是执行文件proc了。
- 6. 这就是整个make的依赖性,make会一层又一层地去找文件的依赖关系,直到最终编译出第一个目标文件。
- 7. 在找寻的过程中,如果出现错误,比如最后被依赖的文件找不到,那么make就会直接退出,并报错,而对于所定义的命令的错误,或是编译不成功,make根本不理。
- 8. make只管文件的依赖性,即,如果在我找了依赖关系之后,冒号后面的文件还是不在,那么对不起,我就不工作啦。
make/makefile进阶
文件名替代
makefile定义变量
makefile定义的变量没有类型。
演示:
$():的意思是直接替换括号中变量的内容。
make/makefile如何生成多个可执行
make默认只形成一个可执行程序。
一旦生成可执行makefile将不会继续往下执行。
那要如何让makefile生成多个可执行呢?
我们可以利用make会自动推导这一特性。
我们先定义一个伪目标all(make在执行时会以为自己要生成的目标文件是all),如果要执行all的依赖方法就要有bin1,bin2这两个依赖文件,如果没有这两个文件,那么make会在当前文件中找目标为bin1,bin2依赖关系,如果找到则再根据规则生成目标文件。但是all并没有执行方法,程序就结束了。
终于写完了!