最近轩少闲来无事,乘建国各个社交媒体账号解封并要挪窝,pdd即将走出舆论旋涡之际,好好了解了一下Makefile。
我觉得大多数人学编程都是从visual studio开始的,默认配置下f7编译,ctrl+f5执行自在得一批,这导致了一个问题,让我在编程初期以为f7就叫编译,ctrl+f5的组合就叫执行。当我只有一个vim和gcc被要求编程手足无措之时,我发现了makefile,并对编译的过程逐渐有了一点了解,在此来聊一聊。
在Makefile文件中充斥着大量的隐式规则和和难以理解的符号,直接看成熟的makefile工程文件能直接给你整自闭了,为此,我们来一点一点看起。
首先要问的是为什么要有Makefile这种东西
在C/C++文件需要被编译时,Makefile能够帮助你决定在一个大项目中哪一部分需要被重编,其他语言也有自己的工具用于实现和make相似的功能,当你工程中的文件发生变化时工程所要做出相应改变的一系列操作,这些工具可以帮你实现。我们这里主要以ubuntu平台C++的编译过程为例,windows上有vs这种无敌的东西还要什么makefile啊。
先来上一张依赖图,在这个依赖关系中,任何文件发生改变,mian.cpp文件就要被重编
先来看一个简单例子,在一个文件夹下新建名为Makefile的文件并在文件夹中输入
在当前文件夹打开命令行输入make就得到了一下运行结果
以上已经是一个简单的makefile了,它主要由以下结构组成
targets是目标文件名,通常只有一个,与后续的依赖用空格分割
command是一系列用于生成targets的步骤,起始需要用一个tab分割,
prerequisites也是一些文件名,也被称为依赖,因为只有它们存在targets才会被生成
来看三个例子
根据依赖关系,第一条命令发现自己的依赖不满足,于是开始执行第二条命令,但是第二条命令发现自己的依赖也不满足,于是执行第三条命令,第三条命令无任何依赖,make会先去执行它,也就是创建blah.c文件,无后续操作,于是会返回到第二条命令,第二条命令此时发现自己的依赖关系满足了,于是开始执行,编译出了blah.o文件,无后续操作,于是返回第一条命令,第一条命令发现自己的依赖关系也满足了,于是开始执行,最终产生blah可执行文件。看到这些makefile文件你就会发现做一个容易被满足的人其实也挺好。
还有比较简单的一个
当你第二次执行这个Makefile文件时,就会报出"some_file is up to date"的警告,因为当你第第二次执行它时,make发现我要生成的目标文件make_file已经存在且没有发生过任何变化,所以它不会再去执行后面的命令。而
由于other_file永远不会被创建,所以它每次都会打印"nothing"和创建some_file。
通过以上例子我们就可以发现使用Makefile时,它会去检查你编译过程的每一个文件及其依赖是否被更新过,就像递归一样要查询完整条"链路",假如某项被更新了,那么从更新的位置开始这个这一条所谓的"链路"都要被更新,以此达到部分更新文件被重编的目的。
最后还想说的一点是在编译过程中会产生一些中间文件,比如像blah.o这种,makefile提供了clean选项让你在编译完成时可以去做一些操作,比如像打印或者删除一些中间文件这种
运行clean选项只要输入make clean就可以了。
以上就是关于makefile的一些基本内容,这些都只是演示,当你的项目中有几百个文件时一个一个的去写依赖显然不行,于是makefile就有了变量,隐式规则等一系列sao东西,这些我们下一篇再聊。
以上内容部分取自https://makefiletutorial.com/#top,如果雷同,不是巧合。