Linux中项目自动化构建工具-make/Makefile

前言

前面我们学习了vim的使用,直到vim是一个文本编辑器,那么要形成可执行程序还需要我们手动编译,这是一个相当繁琐的步骤。因此需要一些工具来简化这个步骤。

简单使用示范

首先我们需要清楚,make是一个命令而Makefile是一个文件。

构建

首先我们先编写一个code.c文件:

然后创建一个makefile(或Makefile)文件,在里面写入如下内容:

注意此时我们的文件仅有:

shell 复制代码
[zhangwho@VM-0-2-centos code]$ ll
total 8
-rw-rw-r-- 1 zhangwho zhangwho 463 Dec  4 18:17 code.c
-rw-rw-r-- 1 zhangwho zhangwho  36 Dec  4 18:21 makefile

运行make之后:

shell 复制代码
[zhangwho@VM-0-2-centos code]$ make
gcc -o myexe code.c	
[zhangwho@VM-0-2-centos code]$ ll
total 20
-rw-rw-r-- 1 zhangwho zhangwho  463 Dec  4 18:17 code.c
-rw-rw-r-- 1 zhangwho zhangwho   36 Dec  4 18:21 makefile
-rwxrwxr-x 1 zhangwho zhangwho 8360 Dec  4 18:24 myexe

可以看到自动生成了myexe的可执行程序.

尝试运行:

shell 复制代码
[zhangwho@VM-0-2-centos code]$ ./myexe 
hello Linux! M=100
hello Linux! M=100
hello Linux! M=100

非常完美!

清理

我们现在还可以给makefile附上一些清理临时文件的功能:

尝试运行make clean:

shell 复制代码
[zhangwho@VM-0-2-centos code]$ make clean
rm -f myexe
[zhangwho@VM-0-2-centos code]$ ll
total 8
-rw-rw-r-- 1 zhangwho zhangwho 463 Dec  4 18:17 code.c
-rw-rw-r-- 1 zhangwho zhangwho  68 Dec  4 18:27 makefile

直接将myexe删除了!

运行原理

makefile

学习了如何使用make之后,我们来看看makefile的构成。

首先我们将第一行称为依赖关系,第二行称为依赖方法。

其中第一行':'后的部分称为依赖文件列表,可以有多个文件,按照空格分割,如:code.c test.c love.c

':'前的称为目标文件

从语法上来讲,第二行的依赖方法必须以Tab开头而非Space。

make运行过程

  1. 首先我们输入make命令
  2. make会在当前目录下找名字叫"Makefile"或"makefile"的文件。
  3. 然后make根据makefile的内容完成编译或清理工作。

make clean

前面我们已经了解make会默认生成myexe的目标文件,那么clean和PHONY又是什么呢?

首先我们需要明确一个概念:clean也是目标文件,虽然说运行这个命令没有形成什么文件就是了/

并且clean他是不依赖于任何文件的!

那么我们很容易想到,make命令会默认生成第一个目标文件。

因此呢,我们的make还可以像这样调用:

shell 复制代码
[zhangwho@VM-0-2-centos code]$ make myexe
gcc -o myexe code.c	

.PHONY

那么.PHONY又是什么呢?

别急我们再执行一次make看看:

shell 复制代码
[zhangwho@VM-0-2-centos code]$ make
make: `myexe' is up to date.

holy shit!我们的make文件被拦截了。因为此时目标文件已经是最新的了,主要是上次make之后,依赖文件没有更新。如果此时我们修改一下依赖文件:

shell 复制代码
[zhangwho@VM-0-2-centos code]$ ll code.c 
-rw-rw-r-- 1 zhangwho zhangwho 463 Dec  4 18:17 code.c
[zhangwho@VM-0-2-centos code]$ touch code.c
[zhangwho@VM-0-2-centos code]$ ll code.c
-rw-rw-r-- 1 zhangwho zhangwho 463 Dec  4 18:48 code.c

我们用touch命令修改了依赖文件的acm时间,然后看看能不能make吧:

shell 复制代码
[zhangwho@VM-0-2-centos code]$ make
gcc -o myexe code.c	

可以看到此时就可以make了。

也就是make指令会自动检索依赖文件是否更改,如果没有就不给你执行.

像clean都没有依赖文件,那就从头到尾只能执行一次咯!

因此为了让目标文件能一直生成而不依赖于依赖文件是否改变,仅需在前面加上 .PHONY 列表就可以了。

当然我们也可以让myexe一直生成,就是没什么意义罢了

为什么makefile对最新形成的目标文件,默认不重新形成?

简单来说就是为了提高编译效率。

当写的项目非常大的时候,一个目标文件想要重新编译就会带动其他所有目标文件编译。这是非常消耗资源的,因此默认最新形成的不重新编译。

那么这是怎么做到的?

上面已经提到了,就是看依赖文件和目标文件的acm时间。

如果目标文件的生成时间晚于依赖文件的修改时间,自然说明目标文件是最新的。

$ @ ^在makefile 的含义

首先@可以代表目标文件,^代表所有依赖文件,$的含义就是提取内容。因此我们上面的makefile符号还可以这样写:

实则是一样的效果哦!

makefile完整写法

前面我们不是定义了一个make clean来清理myexe吗,有没有读者觉得这多少有点多余了,毕竟只需要rm myexe即可,还比make clean方便。

实际上是我们的makefile没写全,完整的写法如下:

简单使用下:

shell 复制代码
[zhangwho@VM-0-2-centos code]$ ls
code.c  makefile
[zhangwho@VM-0-2-centos code]$ make
gcc -E -o code.i code.c
gcc -S -o code.s code.i
gcc -c -o code.o code.s
gcc -o code.exe code.o
[zhangwho@VM-0-2-centos code]$ ls
code.c  code.exe  code.i  code.o  code.s  makefile
[zhangwho@VM-0-2-centos code]$ make clean
rm -f code.i code.o code.s code.exe
[zhangwho@VM-0-2-centos code]$ ls
code.c  makefile

可以看到我们的make执行逻辑是在找到依赖关系链中的已存在的依赖文件,然后一次性执行这些依赖关系。类似于递归的实现。

makefile的变量

每次写makefile都要写一堆重复的简单的工作是不是很无趣,有没有办法实现一个模板,然后简单套一下目标文件名和依赖文件名呢?

有的兄弟,有的!

这时候先看用法:

非常直观的用法吧,这时候我们只要将dest和src指向的名称改为目标文件和依赖文件就完成makefile的编写咯。

不显示执行的依赖方法

我们没make一下就会显示执行了什么依赖方法。像这样:

shell 复制代码
[zhangwho@VM-0-2-centos code]$ make
gcc -o code.exe code.c

多少有点缺少逼格。

为了去掉这些提示,我们只需在每个依赖方法前加上@符号即可:

shell 复制代码
[zhangwho@VM-0-2-centos code]$ make clean
[zhangwho@VM-0-2-centos code]$ ls
code.c  makefile
[zhangwho@VM-0-2-centos code]$ make
[zhangwho@VM-0-2-centos code]$ ls
code.c  code.exe  makefile

是不是一下就逼格上来了。

多行依赖方法

前面我们的makefile里面的每个依赖关系都只对应一个依赖方法,但这不是必要的。

实际上我们可以写多个依赖方法:

shell 复制代码
[zhangwho@VM-0-2-centos code]$ make
echo "compiler code.c to code.exe"
compiler code.c to code.exe

可以看到,一下子执行了多个命令哦。

相关推荐
senijusene几秒前
Linux软件编程:IO编程,标准IO(1)
linux·运维·服务器
忧郁的橙子.8 分钟前
02-本地部署Ollama、Python
linux·运维·服务器
醇氧17 分钟前
【linux】查看发行版信息
linux·运维·服务器
No8g攻城狮1 小时前
【Linux】Windows11 安装 WSL2 并运行 Ubuntu 22.04 详细操作步骤
linux·运维·ubuntu
XiaoFan0121 小时前
免密批量抓取日志并集中输出
java·linux·服务器
souyuanzhanvip1 小时前
ServerBox v1.0.1316 跨平台 Linux 服务器管理工具
linux·运维·服务器
HalvmånEver3 小时前
Linux:线程互斥
java·linux·运维
番茄灭世神3 小时前
Linux应用编程介绍
linux·嵌入式
wdfk_prog3 小时前
[Linux]学习笔记系列 -- [drivers][mmc][mmc_sdio]
linux·笔记·学习
Forsete3 小时前
LINUX驱动开发#9——定时器
linux·驱动开发·单片机