【Linux系统编程】第十三弹---项目自动化构建工具-make/Makefile

本文详细介绍了makefile的基本概念、编写步骤、工作原理,以及如何通过自动化变量和自定义变量进行优化,强调了makefile在大型工程中的重要性和效率提升。
摘要由CSDN通过智能技术生成

个人主页: 熬夜学编程的小林

💗系列专栏: 【C语言详解】 【数据结构详解】【C++详解】【Linux系统编程】

目录

1、背景

2、编写makefile

2、make原理

3、理解makefile

 4、优化makefile

总结


1、背景

★ 会不会写makefile,从一个侧面说明了一个人是否具备完成大型工程的能力。
★ 一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作。
★ makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。
★ make是一个命令工具,是一个解释makefile中指令的命令工具,一般来说,大多数的IDE都有这个命令,比如:Delphi的make,Visual C++的nmake,Linux下GNU的make。可见,makefile都成为了一种在工程方面的编译方法。

总结:

★ make是一条命令,makefile是一个文件,两个搭配使用,完成项目自动化构建。

2、编写makefile

第一步,先创建两个文件,一个用于编写源代码(test.c),一个用于自动编译源代码(makefile/Makefile)。

[jkl@VMCentos7 lesson4]$ touch test.c makefile # 创建两个文件
[jkl@VMCentos7 lesson4]$ ls
makefile  test.c

第二步,编写makefile文件。

test.exe:test.c
	gcc test.c -o test.exe
.PHONY:clean
clean:
	rm -f test.exe

注意:

  • makefile 的文件名必须是 makefile/Makefile,不能是其他名称,否则 make 识别不了。
  • 依赖文件可以有多个,也可以没有。
  • 依赖方法必须以 [Tab] 键开头,特别注意不能是四个空格。

第三步,编写test.c文件。

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

第四步,通过命令看效果。

[jkl@VMCentos7 lesson4]$ make
gcc test.c -o test.exe
[jkl@VMCentos7 lesson4]$ ls
makefile  test.c  test.exe
[jkl@VMCentos7 lesson4]$ ./test.exe
hello linux

2、make原理

在Linux中,输入make命令后,make会在当前目录下找文件名为 "makefile或者Makefile"的文件,1. 如果找到,则会把文件中的第一个目标文件作为最终的目标文件

[jkl@VMCentos7 lesson4]$ ls # 查看当前目录的文件,有一个makefile一个Makefile文件
makefile  Makefile  test.c
[jkl@VMCentos7 lesson4]$ make  # 把第一个文件作为目标文件
gcc test.c -o test.exe    # 执行makefile
[jkl@VMCentos7 lesson4]$ cat makefile
test.exe:test.c
	gcc test.c -o test.exe
.PHONY:clean
clean:
	rm -f test.exe
[jkl@VMCentos7 lesson4]$ cat Makefile
mytest:test.c
	gcc -o mytest test.c

 2. 如果没有找到,则打印提示信息。

[jkl@VMCentos7 ~]$ make
make: *** No targets specified and no makefile found.  Stop. # 没有找到目标文件

3、理解makefile

首先我们需要知道makefile文件中代码所代表的意思,通过下图进行一一解释:

注意:上面我们说了输入make指令出现两种可能,此处只讲解找到最终文件的情况。

当我们在命令行中输入make命令,会默认生成第一个目标文件,即执行第一个依赖方法。

[jkl@VMCentos7 lesson4]$ make # 默认执行第一个依赖方法,并打印出来
gcc test.c -o test.exe
[jkl@VMCentos7 lesson4]$ ls  # 查看当前目录文件,确实生成了可执行程序(目标文件)test.exe
makefile  Makefile  test.c  test.exe

当我们再次输入make命令,会出现以下提示:

[jkl@VMCentos7 lesson4]$ make
make: 'test.exe' is up to date.  # 可执行程序(目标文件)是最新生成的了

1. 为什么再次输入make命令会不让我们继续生成目标文件呢???

因为当有大量的文件的时候,编译执行会消耗大量的时间,为了达到更高的效率,因此源代码没有改变,makefile就会知道只生成一份可执行程序就可以了。

但是此时就有另外的两个问题了,编译器怎么知道哪个文件是没有改变的源代码???如果我们的目的就是想要输入命令则生成目标文件该怎么办???

2. 编译器怎么知道哪个文件是没有改变的源代码???

对比可执行程序最近修改时间与源文件最近修改时间,谁更新?

编写代码和代码生成的可执行程序的修改时间是不一样的,先写的源代码,后才有的代码生成的可执行程序。因此makefile会通过谁的时间更新,来确定到底要不要重新生成可执行程序。通过stat命令可以看到文件的三个时间。

3. 想要输入make命令则生成目标文件该怎么办???

此处可以在每个方法之前输入 .PHONY:xxx,xxx对应的方法总是要执行。xxx可以是目标文件也可以是依赖方法。

举例:想要make总是执行,可以将makefile改成如下内容:

.PHONY:test.exe
test.exe:test.c
    gcc test.c -o test.exe

此时输入make则会生成可执行程序。

4. 我们像VS编译一个程序可以生成解决方案,还可以清理解决方案,我们makefile如何清理解决方案呢???

 清理解决方案的实质是删除可执行程序,那么我们在makefile中提供一个删除文件的依赖方法即可,而且我们可能总是想要删除可执行程序,因此可以加上.PHONY:xxx。

test.exe:test.c
    gcc test.c -o test.exe
.PHONY:clean # 总是执行该依赖关系中的方法
clean:       # 删除可执行程序
    rm -f test.exe

5. 从上面我们可以看到,删除可执行程序是第二个依赖方法,我们前面知道make默认执行第一个依赖方法,那我们想要执行第二个依赖方法应该怎么办呢??

此处需要使用make命令+目标文件,即make clean。 只要不是第一个依赖方法,都是这样执行依赖方法!!!

[jkl@VMCentos7 lesson4]$ ls
makefile  Makefile  test.c  test.exe
[jkl@VMCentos7 lesson4]$ make clean  # 删除可执行程序
rm -f test.exe
[jkl@VMCentos7 lesson4]$ ls  # 确实删除了
makefile  Makefile  test.c

6. 虽然知道了如何执行其他时候的依赖方法,但是此时又有一个问题,如果我执行依赖方法之后不想看到执行的是什么,怎么解决呢???

解决办法是在依赖方法前面加一个@符号,则不会看到执行的内容了。

[jkl@VMCentos7 lesson4]$ cat makefile # 查看文件内容
.PHONY:test.exe
test.exe:test.c
	@gcc test.c -o test.exe  # 依赖方法中有@
.PHONY:clean
clean:
	rm -f test.exe           # 依赖方法中没有@
[jkl@VMCentos7 lesson4]$ make  # 不显示执行的是什么
[jkl@VMCentos7 lesson4]$ ls
makefile  Makefile  test.c  test.exe # 生成了可执行程序
[jkl@VMCentos7 lesson4]$ make clean  # 显示执行的是什么
rm -f test.exe
[jkl@VMCentos7 lesson4]$ ls  # 删除了可执行程序
makefile  Makefile  test.c

 4、优化makefile

前面我们理解了makefile中内容的意义,但是在依赖关系和依赖方法之间的文件名基本是重复的,有没有一种方法让它更简便一些呢???

答案是可以的,此处我们需要介绍几个makefile中一些自动化变量。

$@ : 规则的目标 ,即上面的test.exe

$<   : 规则的第一个依赖,即test.c

$?   : 所有比目标新的依赖的列表

$^   : 所有的依赖的列表,会自动去重  ,即目标后面的多个依赖列表

下面我们则对上面写的makefile文件进行优化:

1.如下为单个依赖关系的举例:

test.exe:test.c
	gcc -o $@ $< # 自动化变量需要在最后面 $@代表test.exe $<表示test.c
.PHONY:clean
clean:
	rm -f test.exe

 2.如下为多个依赖关系的举例:

test.exe:test.c test.h
	gcc -o $@ $^ # 自动化变量需要在最后面 $@代表test.exe $^表示test.c 和 test.h
.PHONY:clean
clean:
	rm -f test.exe

注意:依赖关系以空格间隔!!! 

除了makefile中的自动化变量以外,其实我们还可以自己创建变量

[jkl@VMCentos7 lesson5]$ cat makefile
bin=test.exe # 创建目标文件变量
src=test.c   # 创建被编译文件变量 
 
$(bin):$(src)  # 使用需要加$符号
	gcc -o $@ $^
.PHONY:clean
clean:
	rm -f $(bin)

注意:创建变量跟C语言相似,但是不用加类型。 

总结


本篇博客就结束啦,谢谢大家的观看,如果公主少年们有好的建议可以留言喔,谢谢大家啦!

  • 149
    点赞
  • 128
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 134
    评论
评论 134
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小林熬夜学编程

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值