目录
1.make/makefile介绍
1.1基本认识
1.2依赖关系、依赖方法
1.3具体操作步骤
1.4进一步理解
1.5默认设置
1.6make二次使用的解释
1.7两个文件的时间问题
1.8总是被执行
1.9特殊符号介绍
1.make/makefile介绍
1.1基本认识
make是一个指令,makefile是一个文件(Makefile也是一样的,两个实际上就是一个东西,M大小写都没有影响),这个是我们首先应该意识到的问题;
1.2依赖关系、依赖方法
为什么会有这个自动化构建工具,就是我们自己创建一个文件,在这个文件里面写入相关的内容之后,这个时候我们需要使用gcc或者是g++工具进行相关的编译,我们如果要对于这个文件进行修改之后,就需要重新进行编译,这个时候还是需要输入这个指令gcc -o 目标文件 源文件,如果每一次进行修改,这个编译的指令很麻烦,这个时候我们就可以使用这个自动化构建工具,运用依赖关系和依赖方法解决这个问题;
1.3具体操作步骤
创建一个test.c文件,并在里面写入相关的内容,可以使用vim运用不同的模式之间的相互切换实现这个内容的写入;然后创建一个makefile文件,这个里面就是依赖关系和依赖方法的内容;
这个test:test.c就是依赖关系,怎么理解呢,这个test文件就是test.c文件编译之后的文件结果,第二行就是依赖方法,实际上就是进行编译的指令;
clean就是一个文件创建之后的清理的命令,我们使用的就是这个rm -f test清除这个生成的编译文件;
上述的这个makefile问价创建完成之后,test.c文件写入之后,这个时候,我们直接使用这个make指令,这个时候就显示出来我们的makefile文件里面的第一个指令,就是这个编译test.c文件的指令,这样的话,我们就可以直接使用这个make对于我们指定的文件进行编译处理,而不需要重复的输入指令,但是这个确定就是我们只能使用一次这个make指令,当我们再次进行使用这个指令的时候,系统就会提示我们这个test up to date,这个意思是说这个test文件(编译之后的文件)已经保存在了相关的目录里面,除非我们对于这个test.c的内容进行修改,这个时候我们才可以重新编译,重新使用这个make指令,因为这个重新编译之后的内容发生了更新和变化;
我们输入make clean指令,就可以实现对于这个生成的编译文件的清除;
1.4进一步理解
源文件到可执行文件,我们可以把这个过程写复杂一些,把这个中间文件的生成过程也显示出来,然后重新进行编译,分析依赖关系,依赖方法;
这个里面的过程稍微复杂一些,test文件依赖于这个test.o文件,test.o又依赖于test.s文件,test.s文件又依赖于test.i文件,test.i文件又依赖于test.c文件,这个过程很类似于我们之前学过的这个递归的过程(这个只是为了说明问题,我们的这个实际操作的时候直接按照上面的简便写法就可以了);
这个例子只是为了说明多层依赖关系在执行的时候,这个顺序的问题,我们使用这个make指令的时候,就会发现这个顺序和我们写入到makefile文件里面的顺序恰好是相反的,我们可以类比这个递归的归的过程,归的时候后调用的函数会限制性,这个里面因为依赖关系,后出现的指令会先被执行,因为这个里面最先被需要的就是这个test.i文件,他是直接有这个test.c文件得到的,按照这个顺序才可以实现这个编译的过程;
实际上我们上面输入的时候是4组指令,每一组都是有这个依赖关系和依赖方法,我们把这个4组的顺序随意更换,这个输出的结果是不变的,是可以正常运行的,因此我们可以知道这个make会自动推导这个makefile文件里面的依赖关系,所以这个和顺序没有关系;
但是一旦我们缺少任意一个中间环节,这个过程都是没有办法正常运行的,因为他们之间是相互依赖的;
1.5默认设置
make会自顶向下访问这个命令,我们在这个makefile文件里面添加新的内容,就是这个文件的清理,什么叫做默认设置呢?就是这个make指令的时候,就会默认执行前面的这个文件编译的中间过程。我们要想要清理这个文件就需要make clean指令,这个就是因为在默认的make指令作用下,我们会先执行上面文件指令,如果我们把这个清理的指令放到gcc的上面,这个时候就会优先执行清理的命令;
但是我们一般不会把这个文件的清理放到前面,因为我们还需要对于这个相关的文件进行操作,删除清理就没有办法操作了;
1.6make二次使用的解释
我们第一次编译之后使用make就会执行相关的操作,但是第二次甚至更多次使用这个make就无法有效发挥作用,这个一个原因是为了提高我们的编译效率;
怎么做到的:源文件编译成可执行文件,源文件最近被修改的时间早于可执行文件,我们对于这个原文件修改之后(没有编译),这个新文件比可执行程序要更新,这个时候就可以直接使用make指令(这个时候回重新编译);
这个也是为什么我们的文件编译一次之后只能make一次,但是修改之后就可以再次使用这个make指令了的原因;
1.7两个文件的时间问题
我们上面介绍这个源文件和可执行文件的时间的早晚问题以确定这个make指令能否有效使用,在linux里面,我们可以使用这个stat指令查看相关的时间;
stat test.c就是显示这个源文件的相关的时间,stat test指令就是显示这个生成编译之后的可执行文件的相关的时间,stat指令就是查看时间的,这个指令后面可以跟上这个文件名字;
显示的内容都是一样的,只不过这个对应的选项的具体的数值会有所区别:
这个下面显示了这个文件的相关的信息,access就是访问这个文件的最新时间(访问就比较宽泛,我们使用cat查看相关的文件内容也是访问,修改文件内容也是访问,打开这个文件也是访问等等),modify是修改的时间,change 也是相当于改变,两个很相似,有什么区别呢?简称ACM
之前我们介绍权限的时候说过这个文件==文件内容+文件的属性,这个modify是相当于改变这个文件的内容,只对于文件的属性进行修改,我们称之为change,所以我们对于文件操作的时候,可能修改文件的内容和属性,内容就是modify ,属性就是change;
但是这三个时间不是割裂的,我们对于这个文件内容改变了,modify时间肯定变,但是这个文件内容改变会引起这个文件的大小改变,这个change时间也会改变,我们想要修改内容肯定要打开这个文件,这个时候access时间也会改变,因此这三个时间并不是没有任何联系;
1.8总是被执行
我们上面介绍的这个时间,实际上就是判断源文件和目标文件的生成时间判断这个make是否会被执行,如果我们想要这个make指令输入之后这个一定被执行,可以在这个第一行前面添加.PHONY:文件名字;
上面的就是这个文件makefile里面应该输入的内容,我们使用make之后,就会发现这个一定会被执行,但是我们一般不会这样搞,我们可以把这个总是被执行的设置放到clean那一行,这样的话我们的这个清除就可以总是被执行(默认实际上也是可以会被多次执行的),但是并不一定这个里面只有文件清理的其他的指令,这个并不是多此一举哈,书写格式如下所示:
1.9特殊符号介绍
我们在这个里面使用gcc进行编译的时候,这个$@可以表示这个依赖关系前面的文件,$^可以表示这个依赖关系后面的文件,我们可以使用这个符号代替里面涉及到的两个文件;
但是实际上在查看文件内容的时候这个特殊符号会以这个文件名字的形式回显出来的;
我们在这个指令前面添加上一个@符号,就可以让这个make之后的结果不会显示在屏幕上面,这个就是一个隐藏的功能;