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源文件中)

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

2.2 makefile如何制作

在工程中,最重要的就是通过源文件通过某种方式来形成可执行文件,以及项目资源的清理。现在的问题是如何通过makefile来达到上述目的呢? 我们只需要在Makefile文件中输入以下程序即可:(后续还会在修改)

bash 复制代码
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目标文件,所以代码为:

bash 复制代码
mybin:main.c code.c test.c 
	gcc main.c code.c test.c -o mybin

bash 复制代码
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 版本一

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

bash 复制代码
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中,我们可以在指令前加上@符号,可以不在显示屏上回显文件执行的指令。同时$@表示冒号左边的目标文件,$^来表示冒号右边的所有源文件。 所以上述代码可修改如下:

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

4,3 版本三

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

bash 复制代码
cc=gcc
target=mybin.exe
src=main.c code.c test.c
#使用上述变量时,我们仅需通过$(变量)即可使用

$(target):$(src)  
	$(cc) &^ -o $@ #前面的空格只能按Tab键,不能输入4个空格(语法)
.PHONY:clean #伪目标                                                                                                                                                                   
clean:                         
   rm -f target
相关推荐
fufu031112 分钟前
Linux环境下的C语言编程(四十二)
linux·c语言·算法
Trouvaille ~15 分钟前
【Linux】进程调度与环境变量:Linux内核的智慧
linux·运维·服务器·操作系统·进程·环境变量·调度算法
HalvmånEver16 分钟前
Linux : 基础IO(三)
linux·运维·算法
oushaojun218 分钟前
linux中backtrace实战
linux·运维·算法·backtrace
soft200152522 分钟前
MySQL 8.0.39 Rocky Linux 一键安装脚本(完整可直接运行)
linux·mysql·adb
Nerd Nirvana24 分钟前
WSL——Windows Subsystem for Linux流程一览
linux·运维·服务器·windows·嵌入式·wsl·wsl2
CS创新实验室1 小时前
计算机考研408【操作系统】核心知识点总结
java·linux·考研·计算机·操作系统·408
bulucc1 小时前
vim 快捷操作
linux·编辑器·vim
我是koten1 小时前
用Ansible查找文件并记录文件名的playbook
linux·运维·centos·ssh·ansible·find·playbook
云qq2 小时前
x86操作系统19——键盘驱动
linux·c语言·汇编