以往的C语言编程,我们一般都在一些像VS2019这样的集成开发环境(IDE)下编写,一个工程中的源文件不计其数,其按类型、功能、模块分别放在若干个目录中,但是在Linux下怎么做类似VS下的工作呢?这就要用到make和makefile了。
例子一:拿一个最简单的程序输出hello world为例。先创建一个test.c,使用vim工具来写我们的hello word代码。
$ touch test.c
$ vim test.c
#include int main(){printf("hello world\n");return 0;}
然后再创建一个makefile文件,使用vim工具
$ touch makefile
$ vim makefile
来编写makefile里的依赖关系和依赖方法。
hello:test.c #依赖关系gcc test.c -o hello #依赖方法
拿很简单的一个生活例子来解释依赖关系和依赖方法,每月的月底上学的孩子就会跟父母要这个月的生活费,那么依赖关系就是 孩子:父母,也就是前者依赖后者;依赖方法就是 要生活费,二者缺一不可。
这里也一样hello是我们通过gcc命令编译test.c这个源文件最后生成的可执行文件。所以依赖关系hello:test.c,(hello依赖test.c)依赖方法就是编译test.c这个源文件然后把形成的可执行程序放在hello中这个过程。而且千万要注意写完依赖关系,依赖方法必须是以Tab键开头的。
当然像上面的gcc一步到位很爽,但是其实也可以把预处理、编译、汇编、链接这四个过程再makefile中分开来写。对于gcc预处理、编译、汇编、链接各个过程生成的i、s、o文件有不了解的老铁可以看这篇文章Linux编译器-gcc/g++的使用
mycode:mycode.ogcc mycode.o -o mycode
mycode.o:mycode.sgcc-c mycode.s -o mycode.o
mycode.s:mycode.igcc-S mycode.i -o mycode.s
mycode.i :mycode.cgcc -E mycode.c -o mycode.i
分析:像上面这样写我们在外面输入make之后从上到下执行,我想要得到mycode文件需要mycode.o文件,但是mycode.o还需要mycode.s,想要得到mycode.s就需要mycode.i文件,就这样顺着这个关系一直向下执行,直到最后 gcc -E mycode.c -o mycode.i
执行完之后才能得到mycode,类似于栈结构。总结来说使用makefile你可以自己给他定义推导结构。
工程是需要被清理的。
如下所示我们可以在makefile文件中添加一些清理的代码
hello:test.c #依赖关系gcc test.c -o hello #依赖方法.PHONY:clean #伪目标
clean:rm -f hello
像clean这种,没有被第一个目标文件直接或间接关联,那么它后面所定义的命令将不会被自动执行,不过,我们可以显式要make执行。即命令“make clean
”,以此来清除所有的目标文件,以便重编译。
但是一般我们这种clean的目标文件,
我们将它设置为伪目标,用 .PHONY
修饰,伪目标的特性是:总是可以被执行的。
对于“总是可以被执行的”的解释:
就像上面的hello目标文件生成完一次之后,如果你没有改变test.c的内容,那么hello目标文件是不能再次被生成的。
原因:我们随便创建一个文件使用stat指令来显示文件/文件系统的详细信息就可以看到这里有三个时间。从上往下分别是访问时间、内容修改时间、属性修改时间。
返回我们刚才的hello world程序,make之后会产生一个hello可执行文件,那么这个内容修改时间就必定比test.cC语言源文件的内容修改时间新,它内部根据这个时间的新旧就可以判断本次程序该不该再次编译。
而我们给它在前面加上.PHONY
变成了伪目标就可以重复的执行而不受上面这个规则的限制。当然可以将我们的 hello 目标文件声明成伪目标。
好了今天的分享就到此为止了
最后:如果你觉得对你有用就一键三连吧,哪里有没看懂的地方或者哪里有错误可以在评论区留言欢迎批评指正,作者看到的话会第一时间回复。
end