Makefile项目管理-----在Linux下编译c/c++程序

起因

自己半个月之前学习了makefile编译c/c++程序方便很多

而最近又正好使用到了Linux系统,Linux系统不像Windows系统一样,基本上都是命令行编程

一个文件还好说,可是多个文件一起编译,就会很麻烦,甚至浪费时间

这个时候makefile管理项目就很方便了,明白其原理后,一旦需要使用,写好模板后,可以直接移植,而且我发现,这个适合于Linux平台,也适合于Windows平台

而且只要你把规则写好一个make命令就直接编译完成自己只需要查看可执行文件就可以了

那就结合之前看过的视频对学习过的知识进行一个总结吧!!!

放出视频链接:

视频链接

今天复习了一遍,收获良多

makefile项目管理

一、用途:

项目代码编译管理 节省编译项目时间

二、 makefile的基础规则

1 个规则:

目标:依赖条件
(一个TAB缩进)命令

使用命令借助依赖条件去生成目标
目标的生成时间应该比依赖条件的生成目标晚

Makefile文件
image.png

出现错误原因及解决方式
image.png
运行hello,成功运行!
image.png


注意

  1. 目标的时间必须晚于依赖条件的时间,否则,更新目标
  2. 依赖条件如果不存在,找寻新的规则去产生依赖条件。

image.png
依赖规则:如下 Makefile文件
image.png

执行make命令 成功生成hello.o hello
image.png
运行成功,木有问题
image.png

1.多文件联合编译

makefiletest目录下有以下文件
image.png
hello.c修改如下
image.png
此时编译,则需要多文件联合编译
image.png

对于当前文件,Makefile文件修改如下
image.png
执行make命令,成功生成a.out
image.png
执行a.out
image.png


修改add.c
image.png
再次make运行a.out
image.png
可以看到,只修改add.c,但是编译的时候,其他.c文件也重新编译了
明明只改了一个,全部都重新编译了

解决方法

  1. 使用命令的方式进行编译

image.png

  1. 修改Makefile文件

image.png
执行make,成功生成a.out文件
image.png


2. makefile检测原理

修改div.c后,再次执行make
可以看到只重新编译了修改后的文件,而其他文件并没有编译
image.png
再次修改add.c,再次执行make
除法的结果没有改变,表明只编译了add.c,而div.c和其他文件并没有编译
image.png

Makefile文件中
使用命令借助依赖条件去生成目标
目标的生成时间应该比依赖条件的生成目标晚

当依赖条件比目标时间晚,目标就要被更新

makefile检测原理

  • 修改文件后,文件的修改时间发生变化,会出现目标文件的时间早于作为依赖的时间,出现这种情况的文件会重新编译。
  • 修改div.c后,div.o的时间就早于div.c ,a.out的时间也早于div.o的时间了,于是重新编译这俩文件了

3. ALL来指定终极目标

ALL来指定终极目标

  • makefile的依赖是从上至下的,换句话说就是目标文件是第一句里的目标,如果不满足执行依赖,就会继续向下执行。如果满足了生成目标的依赖,就不会再继续向下执行了。
  • make会自动寻找规则里需要的材料文件,执行规则下面的行为生成规则中的目标。

修改Makefile文件,把生成a.out放在其他下面
image.png
执行make,可以看到只生成了hello.o,其他文件的.o并没有生成
image.png
同样,修改Makefile文件后,再次执行make,只执行了
image.png

这就说明了make命令会检查所写的Makefile文件,把它碰到的第一组规则中的目标,作为终极任务

解决方法

ALL : 终极目标

ALL存在的意义就是用来告诉make命令,当前Makefile文件中,不管碰到的第一组规则的目标是谁,最终要生成的目标一定是a.out
image.png
这样再执行make命令,文件都编译成功!
image.png
:::

三、 makefile的两个函数和clean

makefile文件的变量类型只有一种,字符串类型
wildcard函数和patsubst函数

  1. src = $(wildscard *.c)

匹配当前工作用户下的所有.c文件。将文件名组成列表,赋值给变量src。

找到当前目录下所有后缀为.c的文件,赋值给src
eg: src = add.c sub.c div.c hello.c
匹配当前目录下所有后缀为.c的文件,赋值给src

$(wildcard arguments)函数 arguments表示函数的参数

  1. obj=$(patsubst %.c , %.o , $(src))

将参数3中,包含参数1的部分,替换成参数2

把src变量里所有后缀为.c的文件替换成.o
eg:obj = add.o sub.o div.o hello.o

把src变量里所有后缀名为.c的文件替换成.o

这样Makefile文件就可以更新了
image.png
执行make命令 运行结果
image.png
image.png

  1. clean:(没有依赖)

clean:
(TAB缩进) rm -rf $(obj) a.out
循环删除所有.o和a.out文件

在执行make clean命令时,一定要加-n 去模拟执行

make clean -n
image.png
自己在查看-n命令后,认为无问题了,再执行,所有的.o文件和a.out文件都被删除了
image.png

Makefile文件里clean中的命令

clean:
-rm -rf $(obj) a.out

这里rm前面的”-“表示出错依然执行,作用是删除不存在文件时,不报错,顺序执行结束

四、 makefile中的三个自动变量

3个自动变量
$@:在规则命令中,表示规则中的目标
$<:在规则命令中,表示规则中的第一个依赖条件
如果将该变量用在模式规则中,它可以将依赖条件列表中的依赖依次取出,套用模式规则

%.o:%.c
(tab)gcc -c $< -o $@

$^:在规则命令中,表示规则中的所有依赖条件组成一个列表,以空格隔开,如果这个列表中有重复项,则去重

由此,更新makefile文件
image.png
执行make命令,运行成功
image.png

五、模式规则

上面的Makefile可扩展型不强
比如,要添加一个乘法函数,就需要在Makefile里添加乘法的规则
解决方法:模式规则

%.o:%.c
	gcc -c $< -o $@

更新Makefile文件
image.png
执行make命令,运行成功
image.png

这样可移植性可扩展性就很强,比如再来一个mul乘法函数,下图可见成功make,成功运行
image.png
image.png

继续优化Makefile,静态模式规则

六、 静态模式规则

使用静态模式规则,就是指定模式规则给谁用,这里指定模式规则给obj用
以后文件多了,文件集合会有很多个,就需要指定哪个文件集合用什么规则

$(obj):%.o:%.c
	gcc -c $< -o $@

Makefile文件优化如下
image.png
make成功,又一次优化
image.png

七、 扩展

1. 扩展1 伪目标

当文件夹下有ALL文件或者clean文件时,会导致makefile瘫痪,如下所示,make clean没有工作
用伪目标来解决,添加一行
伪目标的目的 不管条件满足与否,这个目标都要被执行

.PHONY: clean ALL

image.png
Makefile文件优化如下:
image.png
成功删除
image.png

2. 扩展2 可添加常用的参数

编译时的参数,-g,-Wall, ... 这些,可以放在makefile里面
再次优化Makefile
image.png

八、makefile最终形态

m1和Makefile最终形态

左边是第一版Makefile

右边是终极版本
image.png

九、练习

  • 源码add.c,sub.c这些在src目录下,.o文件要放在obj目录下,头文件mymath.h在inc目录下。
  • 将hello.c中的头文件单独拿出来

image.png
image.png

inc/mymath.h
image.png
src/hello.c

这里一定要添加头文件噢,千万不要忘了,我就是在复习一遍的时候,将这里遗忘了,导致错误。
image.png

1. 修改Makefile文件

%的匹配理解,只匹配文件名
注意这里,也有错误噢,小坑,大家注意!!!!!
image.png
image.png

这样才是正确的Makefile,注意%的含义

% 只匹配文件名 而目录位置参数要自己主动设置

image.png

2. 执行make命令

成功运行,生成了a.out和其他.o文件
image.png
image.png

3. 使用make clean

删除.o文件和a.out文件
image.png

4. 注意

  • 如果makefile的名字变化一下,比如,叫m6

用m6执行makefile, make -f m6
用m6执行clean make -f m6 clean

5.我的项目结构

在这里插入图片描述

总结

大前提命名:makefile Makefile — make 命令(只有这两个命名才能使用make命令)
记住1个规则2个函数3个自动变量

1个规则

目标:依赖
(tab)命令

  1. 如果想生成目标,检查规则中的依赖条件是否存在,不存在,则寻找是否有规则用来生成该依赖文件(创造依赖条件) ----- 依赖条件如果不存在,则找寻新的规则去产生依赖条件
  2. 目标的时间必须晚于依赖条件的时间,否则更新目标
  3. ALL指定makefile的终极目标

2个函数

  1. src = $(wildcard *.c) 匹配当前工作目录中所有的.c文件
  2. obj = $(patsubst %.c,%.o,$(src)) 将参数3中,包含参数1的部分,替换成参数2 把src中的所有的.c文件替换成.o文件
  3. clean:(无依赖) (tab) -rm -rf $(obj) a.out #强制删除所有的.o文件和a.out文件

3个自动变量

  1. $@:表示规则中的目标
  2. $<:表示规则中的第一个依赖条件,如果将该变量用在模式规则中,它可以将依赖条件列表中的依赖依次取出,套用模式规则
  3. $^:表示规则中所有的依赖条件

小tips

大家学习完makefile后,可以做出自己的一个模板,下次在Linux系统中编写程序时可以直接复制这个模板,就不用去写重复的Makefile了。

然后编译c++程序也是一样的,只不过gcc编译变成了g++编译

一样的是

.c文件/.cpp文件 ---> .o 文件 ---> 可执行文件

噢,关于c和c++不同的地方就是,要添加指定c++的标准(是c++11还是c++14标准),其他大体不差,还有对应的规则要修改一下makefile也适用于c++

大家只需要换相应的参数就可以啦!!!!

猜你喜欢

转载自blog.csdn.net/cyaya6/article/details/129771224