目录
前言
1.make/makefile
1.1 依赖关系/依赖方法
2.原理
3.项目清理
4.make的执行问题
5.相关简单的符号介绍
总结
前言
之前给大家介绍了我们在开发过程中所需要使用到的编辑器vim,以及编译器gcc/g++的使用,但是我相信大家在使用过程会发现我们在每次编写好一份代码时总是需要每次去调用gcc/g++的相关指令去编译,那么如果我们具有了多份代码时,我们还需要一个一个去编写就显得非常的麻烦,那么我们今天要学的相关工具就会免去我们在这个方面的很多工作。
1.make/makefile
学习我们的自动项目构建工具学习的就是我们对make以及makefile这个工具的使用,而会不会写makefile,从一个侧面说明了一个人是否具备完成大型工程的能力。
一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作。
makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。
make是一个命令工具,是一个解释makefile中指令的命令工具,一般来说,大多数的IDE都有这个命令,比如:Delphi的make,Visual C++的nmake,Linux下GNU的make。可见,makefile都成为了一种在工程方面的编译方法。
从本质来讲我们的make是一条命令,makefile是一个文件,两个搭配使用,完成项目自动化构建。
那么我们如何去使用我们这个工具呢?那么首先就需要我们自己去创建一个makefile文件。
那么创建好这个文件后,我们后续需要做什么操作呢?为了让大家更好的理解
1.1 依赖关系/依赖方法
这里我们如何去理解这个依赖关系和依赖方法呢?这里我就简单的给大家举一个例子:
首先我们先创建一个文件写一份代码:
这里我们对makefile进行配置:
这里我们可以看到我们对我们hello.c到hello运行程序进行了编写,那么这里我们的依赖关系就是:
那么我们的依赖方法对应的就是每行依赖关系对应得下一行:
也就是: gcc -option hello.* -option hello.*
rm - fr hello.i hello.s hello.o hello
那么我们编写好得makefile文件该如何使用呢?这里我们使用make指令看看效果:
这里我们使用make指令可以发现我们这里产生了我们编译的各个过程所对应的文件,那么这里我们调用我们的可执行程序看看运行结果如何:
这里我们可以发现我们的程序执行无误,那么我们此处的原理又是什么呢?
2.原理
1.首先make会在当前目录下找名字叫“Makefile”或“makefile”的文件。
2. 如果找到,它会找文件中的第一个目标文件(target),在上面的例子中,他会找到“hello”这个文件,并把这个文件作为最终的目标文件3. 如果hello文件不存在,或是hello所依赖的后面的hello.o文件的文件修改时间要比hello这个文件新,那么,他就会执行后面所定义的命令来生成hello这个文件。
4.如果hello所依赖的hello.o文件不存在那么make会在当前文件中找目标为hello.o文件的依赖性,如果找到则再根据那一个规则生成hello.o文件。(这有点像一个堆栈的过程)
5. 当然,你的C文件和H文件是存在的啦,于是make会生成 hello.o 文件,然后再用 hello.o 文件声明make的终极任务,也就是执行文件hello了。
6. 这就是整个make的依赖性,make会一层又一层地去找文件的依赖关系,直到最终编译出第一个目标文件。
7. 在找寻的过程中,如果出现错误,比如最后被依赖的文件找不到,那么make就会直接退出,并报错,而对于所定义的命令的错误,或是编译不成功,make根本不理。
8. make只管文件的依赖性,即,如果在我找了依赖关系之后,冒号后面的文件还是不在,那么对不起,我就不工作啦。
那么总结的来说就是我们在调用make指令该会自动推导makefile中的依赖关系,去产生我们的目标文件。
3.项目清理
这里我们产生了一堆文件,但是我们的工作也是需要被清理的,这个清理过程就需要我们调用我们先前就编写好的clean
也就是
这里我们发现我们的清除程序调用方式是make +clean ,那么这里的原因是什么呢?这里有个小知识需要我们去了解一下:
make从顶向下扫描,默认将第一个作为make指令,后续的就需要我们使用make+文件名,就如我们需要使用make clean达到清理效果
但是一般我们的clean目标文件我们一般将其设置为伪目标,也就需要使用.PHONY关键字去修饰。
这里我们为什么需要使用.PHONY关键字去修饰clean呢?首先我们需要知道的就是我们的.PHONY关键字的作用就是让我们无论在什么情况下都能被执行,那么也就是说我们的依赖关系并不是在什么情况下都能执行的,而是需要一定条件的,所以我们不建议把形成可执行逻辑用伪目标修饰,但是就是我们的清理程序是我们要求每次都要被执行的,所以我们一般用伪目标关键字去修饰clean。
所以我们简单的修改一下我们的makefile文件:
4.make的执行问题
我们之前说我们的make并不是在任何情况下都能执行的,这里我给大家实验一下:
这里我们在第一次执行过make后发现我们第二次并不能执行了,而且上面提示我们hello是更新了的,那么原因是什么呢?首先我们需要知道我们make在执行所对应的依赖关系是需要我们操作系统付出代价的,在我们源文件没有改变的情况下,我们再次编译得到可执行程序也是不变的,那么我们再次make得到的可执行程序是没有意义的,我们的操作系统也不允许这样的事情发生。
那么如果要在是make有效就需要我们修改我们的源文件内容,而这个过程实际上就是修改了我们源文件的相关时间,从而我们的源文件时间就比我们的可执行程序文件更新,这样子我们就可以产生新的可执行程序,所以我们可以说我们的make指令是否有效实际上就是我们的源文件时间是否比我们的可执行程序文件更新。
而我们的文件又分为三个时间,分别是:
access指的是我们的访问时间
modify指的是我们对文件内容进行修改的时间
change指的是我们对文件属性进行修改的时间
我们可以使用stat指令去查看相关时间信息:
这里需要给大家简单的说明一下这里我们由于访问我们文件的是非常频繁的所以修改access时间会影响我们的整机效率,所以在我们现在的操作系统中access的修改并不是每次都需要修改而是要达到一定的条件(每个操作系统的不一样)。
那么我们对我们的源文件进行修改实际上就会更改我们的Modify时间,但是在修改源文件的过程中一般我们文件属性相关的内存也会发生相关变化所以我们的Change的时间也会发生变化。
那么我们就简单的给大家演示一下,这里我们对我们的源文件内容进行修改:
这里我们发现我们的时间发生了改变,那么我们调用我们的make指令看看效果:
可以发现我们的make成功了。
此外为了验证我们的程序编译成功和我们内容变化没有关系我们可以使用我们的touch指令去修改相关时间:
这里我们看到我们的时间发生了变化,那么调用我们的make指令看看效果:
可以发现我们的make指令也成功了,此外我们可以使用touch+对应的选项去修改我们的对应的时间,也就是:
-a更新访问时间,-m更新修改内容时间(这里我们的change时间也会随着改变)
5.相关简单的符号介绍
总体来讲我们的make小编已经给大家讲解的大差不差了,但是这里还有几个符号需要大家去使用理解一下:
$@:表示的是我们依赖关系左边的简写
$^:表示的是我们依赖关系右边的简写
@:如果我们不想让我们使用make时我们的依赖方法显示到屏幕上,只需要我们在我们的依赖方法的第一行加上@即可
#:mikefile中的注释
总结
对于内容呢,小编就给大家介绍到这里了关键是需要大家平时多使用加深影响并且学习,才能掌握我们的LInux操作系统的相关内容。|