目录
前言:
1 makefile的简单使用
2 makefile介绍
前言:
我们上文介绍了gcc和g++的基本使用,带了许多的子指令,但是有的时候啊,一个一个敲指令确实有点麻烦了,此时,一个工具就能派上用场,即自动化工具makefile。
我们不妨理解为语言中的宏,命令的重新命名都可以通过makefile来表示,这就大大简化了工程量了,所以,有的时候makefile的使用从侧面也决定了工程的完备程序以及效率问题。
通过简单的介绍,我们知道了makefile是一个自动化命令工具,那么使用方法第一个是要创建makefile文件,makefile或者是Makefile都可以,我们在文件里面写入一些指令加上一点操作,我们就可以实现自动化指令了。
1 makefile的简单使用
我们不妨,先看看makefile的简单使用:
第一步是创建一个makefile文件并往里面写入一些指令->后面会介绍。
第二步则是先来一个实例代码:
然后,我们直接make一下,就可以创建一个test的可执行文件了,我们执行也是没有问题的:
其中,clean指令也是可以完成我们的预期操作的。
2 makefile介绍
我们从makefile文件中的第一个点开始:
第一行的test:test.c,其中test:test.c成为构成了依赖关系,test叫做目标文件,test.c是被test依赖的。
其中:后面的叫做依赖文件列表,不同的依赖文件可以用空格进行分割,也可以为空。那么下面的指令就是依赖方法,依赖方法前面只能使用Tab来空位置,不能使用四个空格,会报错。
这的理解我们可以理解为父子,儿子问父亲要钱,这里面存在父子之间的依赖关系,依赖方法是养育,所以给钱。
那么我们如果重复使用该命令呢?
它第一次是成功执行了的,但是后面就告诉说,test is up to date,表明test文件已经是最新文件了。
此时,前面文章埋的伏笔就可以拉出来了->文件的ACM时间。
我们首先看看test.c的ACM时间:
这里为什么不让多次执行编译的命令就是因为makefile工具比较的是源文件和可执行文件的ACM时间,如果可执行文件和源文件的ACM时间,在修改上有差别,make检测到源文件更新了,才会重新编译源文件,这样做的目的是提高效率,比如不能总一直编译已经编译好了的文件吧。
以及,不同的自动化工具对于时间的判断是不一样的,比如我们平时使用的VS,有的时候出现bug,重新清理一下解决方案,再运行就可以了,大多数就是因为时间的判断准则出现问题了,此时清空解决方案就是为了更新一下可执行文件的ACM时间,一比较,欸源代码早一点,重新编译就成功了。
但是,前面我们介绍了一个指令叫做touch,是用来创建文件的,好像在这里没有啥用处,但是使用touch可以改变ACM时间:
所以我们想要重复编译也可以使用touch改变ACM时间再进行编译即可。
此时,再引出一个关键词,.PHONY:
我们会发现clean总是可以执行的,这就是.PHONY做的事,被.PHONY修饰了的指令,默认可以重复执行,所以我们可以重复执行,那么我们同样可以把.PHONY给test修饰了
就可以重复编译了,此时clean也是可以重复执行的,因为clean是特殊的方法,后面也不用跟任何东西:
那么现在来深究原理部分,为什么我们直接make是执行的第一个指令呢?
因为makefile执行方向就是从上往下进行执行的,所以我们直接make,默认执行的是第一个指令,那么我们换个位置:
此时make就是执行的第一个语句了。
此时啊,学到这里,不免会觉得我每次使用指令都要给我打印出来,一点神秘感都没有,能不能不打印呢?
当然是可以的,此时用到的符号是@,@任意的指令,就能让指令不显示出来:
此时make了一下之后,rm -rf之后也没显示:
此时同理。
所以@是只能应用一个指令,不是多行的,此时对echo@一下就可以了:
这里还有一个有意思的点是,makefile里面的注释是#,并且允许变量的存在,虽然说是变量,但是实际上就是宏了:
执行的操作实际上就是替换。
但是这样使用就会导致如上错误。
需要搭配$使用:
此时就没问题了。
这里涉及了替换,我们不妨再看看$@ $^:
不难看出,$@ $^分别代替的是目标文件和依赖文件。
好了,现在又提到了依赖关系,那么,我们看一段代码:
我们不难发现依赖关系是连着的,所以我们可以直接创建编译的三个阶段的文件。
那么既然依赖关系是连着的,试试打乱顺序呢?
可以发现,还是可以创建,难道是说随意打乱顺序都没有问题的吗?
当然不是;
此时只能创建预处理期间的文件,可执行文件就创建不了了,凡事都要有一个带头的不是,所以可执行文件要放最开始:
感谢阅读!