人生路漫漫,越长大,越明白,每个人的路都是漫长而又艰辛的
无论我们有多累,我们都无路可退。就像马丁说的那样,每一个强大的人都曾咬牙
度过一段,没人帮忙,没人支持,没人嘘寒问暖的自己。过去了,这就是你的成人礼,过不去
求饶了,这就是你的无底洞,我们都要熬过一段灰暗,孤独,无人能懂的岁月里,别无他法,谁也无法逃避。
蔡康永曾说,人生前期越是嫌麻烦,越是懒得学习,后来就越可能错过让你,心动的人和事。
错过新风景,生活有太多的磨难和挫折,但那些打不倒我们的,将会让我们变得更加强大,尝遍人生百味的我们,将会更加生动而干劲。
—————— 一禅心灵庙语
会不会写makefile ,从一个侧面说明了一个人是否具备完成大型工程的能力
一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile 定义了一系列的规
则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功
能操作
makefile 带来的好处就是——“自动化编译” ,一旦写好,只需要一个make 命令,整个工程完全自动编译,
极大的提高了软件开发的效率。
make 是一个命令工具 ,是一个解释makefile 中指令的命令工具,一般来说,大多数的IDE都有这个命令,
比如:Delphi的make,Visual C++的nmake,Linux下GNU的make。可见,makefile都成为了一种在工
程方面的编译方法。
make是一条命令,makefile是一个文件,两个搭配使用,完成项目自动化构建 。
首先我们创建一个C程序项目:
[linux@localhost dir]$ touch main.c
[linux@localhost dir]$ touch mytest.c
[linux@localhost dir]$ touch mytest.h
main.c 文件内容
#include"mytest.h"
int main()
{
show();
return 0;
}
mytest.h 文件的内容
pragma once
#include
extern void show();
mytest.c 文件内容
#include"mytest.h"
void show()
{
int i = 0;
for(;i < 10; i++)
{
printf("hello %d\n",i);
}
}
创建 Makefile文件 : 在该项目,文件夹中创建 makefile 或者是 Makefile 文件名的大小写无关,因为 Linux 是不区分大小写的
[linux@localhost dir]$ touch Makefile
编写Makefile文件内容
mybin:mytest.c main.c
gcc mytest.c main.c -o mybin
编写好 Makefile 内容后,就可以直接使用 make命令 ,就会自动一键,编译生成可执行程序了
[linux@localhost dir]$ make
从下图中我们可以看到,当我们使用 make命令 ,就自动执行了,我们在 Makefile 文件中所写的 脚本内容:gcc mytest.c main.c -o mybin ,生成了,可执行程序 mybin ,对于该脚本的作用以及详细信息,大家可以移步到:
Linux编译器-gcc的使用
运行看看
[linux@localhost dir]$ ./mybin
工程是需要被清理的,我们还可以编写一个清理项目的
像clean 这种,没有被第一个目标文件直接或间接关联,那么它后面所定义的命令将不会被自动执行,不
过,我们可以显示要make执行。即命令——“make clean”,以此来清除所有的目标文件,以便重编译。脚本内容,打开 Makefile 写入如下:内容
mybin:mytest.c main.c
gcc mytest.c main.c -o mybin
.PHONY:clean
clean:
rm -f mybin
编写好后,就可以使用命令 make clean 清除项目了
[linux@localhost dir]$ make clean
从图下,我们可以看到当我们,使用 make clean 命令的时候,执行了 我们在 Makefile 中编写的脚本:rm -f mybin 强制删除 mybin 文件,
Makefile 主要是由 “依赖关系" 和 “依赖方法” 所对应的,缺一不可, 编写:Makefile ,本质上是在编写依赖关系和依赖方法
mybin:mytest.c main.c
gcc mytest.c main.c -o mybin
.PHONY:clean
clean:
rm -f mybin
//
解析:
mybin 是为目标文件 :冒号后面的为 依赖关系 main.c mytest.c ,就是mybin目标文件(可执行程序)的产生需要对应的源文件,不然没有源文件,又如何生成 mybin目标文件(可执行程序) ,注意语法细节:要顶格写入
gcc mytest.c main.c -o mybin 为依赖方法,就是如何通过依赖关系中的(main.c mytest.c)文件,生成,产生,目标文件mybin, 注意语法细节:要以Tab键开头,不可以是空格这是语法规定,依赖关系与依法方法之间不可以有空行的存在,必须相互紧挨着
.PHONY: 可以理解成是 Makefile的关键字,凡是被.PHONY:clean(伪目标),总是会被执行的,达到无障碍运行,记住一点就是 (伪目标)可以无障碍运行,
clean 是目标文件
rm -f mybin 依赖方法,强制删除文件(mybin)
这里解释一下:.PHONY:的总是被执行
当我们已经产生了目标文件 比如这里的 mybin ,可我们还是继续使用 make 命令想要继续产出的时候,不会执行了,报出 make: `mybin’ is up to date. 以是最新的了,该make 命令被迫,不执行了,
而我们多次使用被 .PHONY 修饰的 clean(伪目标) 命令就不会被停止,可以一直使用,就算我们删除的文件不存在了,也还是会执行的,如下图:
我们的 mybin 也是可以被 .PHONY修饰的,从而达到 make的无障碍运行的 操作如下:
.PHONY:mybin mybin:mytest.c main.c
gcc mytest.c main.c -o mybin
.PHONY:clean
clean:
rm -f mybin
问题 : 为什么 不要让 make 被修饰 .PHONY 成伪目标
因为,对于项目而言,一般都是比较大的,完整编译一次,可能需要消耗 1~3 个小时,大一点的话,可能更多,成本太大了,太消耗时间了,所以不建议 被 .PHONY ,修饰,而清除项目,就不需要了,这么多时间成本,而且可能一次没有清除干净,需要多次清除。
问题: 为什么 编译使用 make命令 就可以了,不需要带选项标签,而清除项目,却需要make clean 带上标签
因为命令 默认是从上往下执行的,默认make 执行第一个语句的,所以不需要带上标签,而我们的清除项目,clean 命令,不是位于第一个语句,所以需要使用到 标签,跳转到相对应的位置 make clean
大家发现没有,如果使用上述的方式,编写的Makefile 依赖关系和依赖方法,太过于死板了,如果项目中的依赖关系的文件,太多了的话,我们需要一个一个的输入,难免会输错,而且一旦在项目中我们添加了,对应的依赖关系中的文件,我们又要对 Makefile 内容上做修改,太麻烦了,有没有什么,一劳永逸的方法,当然,是用的,我们可以使用上 通配符以及一些特殊的符号,代替大量重复类似的文件上的操作
mybin:main.o mytest.o
gcc $^ -o $@
%.o:%.c
gcc -c $<
.PHONY:clean
clean:
rm -f *.o mybin
试试看
[linux@localhost dir]$ make
[linux@localhost dir]$ ./mybin
[linux@localhost dir]$ make clean
解析
mybin:main.o mytest.o
gcc $^ -o $@
%.o:%.c
gcc -c $<
.PHONY:clean
clean:
rm -f *.o mybin
mybin 目标文件
main.o mytest.o 依赖关系,生成目标文件(mybin)所依赖的源文件 main.o mytest.o
$^ 表示依赖文件列表中的:冒号右侧的源文件(main.o mytest.o)
$@ 表示代指目标文件(mybin)
gcc $^ -o $@ 依赖方法,生成目标文件(mybin),在这里就等于是 gcc main.o mytest.o -o mybin
%.c 依赖关系表示当前目录下的所有后缀为.c文件
%.o 目标文件表示当前目录下的所有后缀为.o 文件,就是依赖关系中的.c 文件产生的.o 目标文件
$< 表示在依赖关系中的%.c的源文件,用 gcc 进行汇编成同名的.o 文件
gcc -c $< 依赖方法表示使用 gcc 依赖关系中的%.c的源文件对进行汇编生成同名的.o文件(%.o目标文件),因为 gcc -c 没有重定向默认是创建同名的.o二进制目标文件,在这里等于是 gcc -c main.c mytest.c
.PHONY:clean(伪目标) 表示无障碍运行
clean 表示目标文件
*.o 通配符,表示当前目录下的所有以.o 为后缀的文件
rm-f *.o mybin 表示强制删除当前目录下的以.o为后缀的文件以及名为mybin的文件
make是如何工作的,在默认的方式下,也就是我们只输入 make 命令。那么
make 会在当前目录下找名字叫 “Makefile" 或**“makefile”** 的文件,如果找到了,它会找文件中的第一个目标文件(target), 在上面的例子中,它会找到 ”mybin" 这个文件,并把这个文件作为最终的目标文件,
如果 “mybin" 文件不存在,或是 ”mybin" 所依赖的后面的 main.c mybin.c 文件的文件修改时间比 ”mybin“ 这个文件新(可以用touch测试),那么 ,它就会执行后面所定义的命令来生成 mybin 这个目标文件。
如果**”mybin"** 所依赖的**“main.c mybin.c"** 文件不存在,那么 make 会在当前文件中找目标为 main.c mybin.c 文件的依赖性,如果找到了,则再根据那一个规则生成 ”main.c mybin.c 文件(这有点像一个堆栈的过程)
当然,如果你的C文件,和H文件都是存在的,于是make 会生成main.o mybin.o 文件,然后再用 maIn.o mybin.o 文件声明make 的终极任务,也就是执行文件 mybIn 了
这就是整个 make 的依赖性,make 会一层一层地去找文件之间的依赖关系,直到最终编译出第一个目标文件,在找寻的过程中,如果出现错误,比如:最后被依赖的文件找不到,那么make 就会直接退出,并报错,而对于所定义的命令的错误,或是编译不成功,make 根本不会理会
make 只管文件的依赖性,即使如果在我找了依赖关系之后,冒火后面的文件还是否存在,那么对不起,我就不工作了。
其中大家如果不理解的 gcc 的使用,大家可以移步到: Linux编译器-gcc的使用
限于自身水平,其中存在的错误,希望大家给予指教,韩信点兵——多多益善,谢谢大家,后会有期,江湖再见!