Linxu自动化构建工具make/Makefile究竟时什么?

简介: Linxu自动化构建工具make/Makefile究竟时什么?

一、简介

 在一个大型工程中,源文件不计其数。按照文件类型、功能、模块不同,放在不同的目录下。但哪些文件先编译,哪些文件后编译,哪些文件需冲重新编译,甚至更为复杂的功能操作,如果依靠程序员自身来控制,不仅效率低下,而且极其容易出错!为此,自动化构建工具诞生 —— make/Makefile

 Makefile(或makefile)是一个脚本文件;而make是一个命令工具,用于解释Makefile中的指令,一般来说,大多数的IDE都有这个命令,比如:Delphi的make,Visual C++的nmake,Linux下GNU的make。当我们在Makefile中一旦写好了编译方式,只需要一个make命令就可完成整个工程的自动化编译。

二、makefile文件制作(简洁版)

2.1 源文件

这里我们给出一段各位都记忆深刻的代码:(存在于code.c源文件中)

#include <stdio.h>  
  
int main()  
{  
    printf("hello world\n");
    printf("hello world\n");
    printf("hello world\n");
    return 0;                                                                                                                                                                          
}

2.2 makefile如何制作

在工程中,最重要的就是通过源文件通过某种方式来形成可执行文件,以及项目资源的清理。现在的问题是如何通过makefile来达到上述目的呢?

我们只需要在Makefile文件中输入以下程序即可:(后续还会在修改)

mybin:code.c  #如果有多个源文件,code.c后可继续田间源文件 
  gcc code.c -o mybin #前面的空格只能按Tab键,不能输入4个空格(语法)
.PHONY:clean #伪目标                                                                                                                                                                   
clean:                         
  rm -f mybin

接下来我们来一一分析每段代码是什么意思,以及如何编写!

2.2.1 依赖关系、依赖方法

 第一行mybin:code.c 称为依赖关系冒号左边为目标文件;冒号左边为源文件(可以是多个)。

 第二行gcc code.c -o mybin称为依赖关系,及源文件通过何种方式来形成目标文件。需要特别注意的是:依赖关系前的空格只能通过Tab键实现,不可以是4空格或其他!!!

 比如假设我们需要通过main.c、code.c、test.c三个源文件通过gcc来编译形成mybin目标文件,所以代码为:

mybin:main.c code.c test.c 
  gcc main.c code.c test.c -o mybin

mybin:main.c code.c test.c 
  gcc -o mybin main.c code.c test.c  //(只需保证-o后紧跟的是目标文件即可)

2.2.3 伪目标(清理文件资源)

在上述代码中.PHONY:xxx文件名表示该目标文件为伪目标,表示该文件不需要依赖关系,并且总是被执行

现在我们分别运行伪目标文件和普通文件看看会发生什么?

【普通目标文件】:

【伪目标文件】:

 我们发现对于普通目标文件,一旦我们编译后就不能重复编译,否则会报make: ‘mybin' is up to date.;但对于伪目标文件来说可以重复执行。

 为什么会这样呢?

三、make/Makefile自动化原理

3.1 伪目标为什么可以重复执行?

在解决这个问题之前,我们需要先了解为什么普通目标文件不可以重复执行!

 在实际工程中,一个大型项目存在众多的源文件,我们需要对这些源文件进行编译形成可执行文件。但一旦编译好后,在下一次执行该文件时,我们只需要重新编译某些内容被修改过的源文件即可。如果每次执行都需要重新编译所有的源文件,不仅意义不大,还会导致效率大大降低!

那程序如何发现代码别修改过,需要重新编译了?

在Linux中,每个文件有3种时间:Access、Modify、change三种时间,分别代表文件被打开的时间、文件内容内修改的时间、文件属性被修改的时间。我们可以通过stat 文件名来查看文件的3种时间。

 其中,Access时间比较特殊。一般而言,一个文件被访问是非常频繁的。由于文件存在磁盘中,如果每次进入文件都修改文件的Access时间,这也意味着存在大量的访问磁盘的IO操作,变形的降低了操作系统的效率。为此,当代计算机一般都对更改Access时间做了次数限制,不同机器平台存在差异。只有达到一定次数时,才会修改Access时间

 由于我们最终目的是得到相应的可执行程序,所以我们可以通过对比源文件和可执行文件的Modify来判断哪些文件被修改过,需要重新编译。即源文件第一次形成可执行文件时,可执行文件的Modify > 源文件的Modify。一旦源文件内容被修改后,此时源文件Modify被修改为最新时间,此时源文件Modify > 可执行文件的Modify。而make如果识别到源文件Modify > 可执行文件的Modify,便会对源文件进行重新编译。

伪目标为什么可以重复执行?

 前面博主替代过,一旦文件通过.PHONY:文件名成为伪目标,此时该文件不在需要依赖关系。这也意味这该文件不需要对比任何时间,直接执行。即可以重复执行。

3.2 make如何工作?

 在默认情况下,只要我们输入make命令,此时make会在当前目录下查找名为Makefile或makefile的文件。如果找到,则它会将第一个目标文件作为最终的目标文件。

 如果第一个目标文件文件不存在,或是第一个目标文件所依赖的后面的 .o 文件的文件修改时间要比第一个目标文件新,那么,他就会执行后面所定义的命令来生成这个文件。如果第一个目标文件所依赖的.o文件也不存在,那么make会在当前文件中找目标为.o文件的依赖性,如果找到则再根据那一个规则生成.o文件。

 这就是整个make的依赖性,make会一层又一层地去找文件的依赖关系,直到最终编译出第一个目标文件。在找寻的过程中,如果出现错误,比如最后被依赖的文件找不到,那么make就会直接退出,并报错,而对于所定义的命令的错误,或是编译不成功,make根本不理。make只管文件的依赖性,即,如果在找了依赖关系之后,冒号后面的文件还是不在,那么就不工作了。

四、Makefile简介版本

比如假设我们需要通过main.c、code.c、test.c三个源文件通过gcc来编译形成mybin目标文件,这里有3个版本。各位自行选择。

4.1 版本一

这个就是最简单版本,就不多说了。

mybin:code.c  
  gcc main.c、code.c、test.c -o mybin #前面的空格只能按Tab键,不能输入4个空格(语法)
.PHONY:clean #伪目标                                                                                                                                                                   
clean:                         
   rm -f main.c、code.c、test.c

4.2 版本二

在Makefile中,我们可以在指令前加上@符号,可以不在显示屏上回显文件执行的指令。同时$@表示冒号左边的目标文件,$^来表示冒号右边的所有源文件。

所以上述代码可修改如下:

mybin:main.c、code.c、test.c 
  gcc $^ -o $@ #前面的空格只能按Tab键,不能输入4个空格(语法)
.PHONY:clean #伪目标                                                                                                                                                                   
clean:                         
   rm -f target

4,3 版本三

在make/Makefile中,支持变量化处理。有点类似于宏替换,具体如下:

cc=gcc
target=mybin.exe
src=main.c code.c test.c
#使用上述变量时,我们仅需通过$(变量)即可使用
$(target):$(src)  
  $(cc) $^ -o $@ #前面的空格只能按Tab键,不能输入4个空格(语法)
.PHONY:clean #伪目标                                                                                                                                                                   
clean:                         
   rm -f target


相关文章
|
30天前
|
Linux C++
Linux自动化构建工具——make和Makefile使用详解
Linux自动化构建工具——make和Makefile使用详解
|
1月前
|
IDE Linux 编译器
【Linux】项目自动化构建工具 —— make/Makefile
【Linux】项目自动化构建工具 —— make/Makefile
|
4月前
|
IDE 开发工具
Linux---(六)自动化构建工具 make/Makefile
Linux---(六)自动化构建工具 make/Makefile
73 6
|
7月前
|
Linux 编译器 C语言
【Linux】自动化构建工具:make/Makefile
【Linux】自动化构建工具:make/Makefile
84 0
|
1月前
|
IDE Linux 编译器
Linux项目自动化构建工具-make/Makefile
Linux项目自动化构建工具-make/Makefile
22 0
|
2月前
|
IDE Linux 开发工具
【Linux工具篇】Linux项目自动化构建工具make/Makefile
【Linux工具篇】Linux项目自动化构建工具make/Makefile
26 1
|
3月前
|
Linux C语言
【Linux系统编程】项目自动化构建工具make/Makefile--2
【Linux系统编程】项目自动化构建工具make/Makefile--2
|
3月前
|
Linux 开发工具 C语言
【Linux系统编程】项目自动化构建工具make/Makefile--1
【Linux系统编程】项目自动化构建工具make/Makefile--1
|
4月前
|
Linux 编译器 C语言
3.3、Linux项目自动化构建工具make/makefile
3.3、Linux项目自动化构建工具make/makefile
32 0
|
4月前
|
IDE Linux 编译器
Linux项目自动化构建工具:make与Makefile的基本用法
Linux项目自动化构建工具:make与Makefile的基本用法