OriginBot
OriginCar
智能车竞赛
ROS探索总结
ROS2探索总结
ROS入门教程
ROS
建图导航
运动控制
自动驾驶
机器视觉
机器学习
建模仿真
机器人学
ROS2入门教程
硬件电路
创客DIY教程
智能机器人创意大赛
ROS史话36篇
学习笔记
ROS2
技术前沿
行业资讯
古月居社区公告
RDK开发套件
机械臂控制
嵌入式开发
Linux
自己半个月之前学习了makefile,编译c/c++程序方便很多
而最近又正好使用到了Linux系统,Linux系统不像Windows系统一样,基本上都是命令行编程
一个文件还好说,可是
多个文件一起编译,就会很麻烦,甚至浪费时间
这个时候makefile管理项目就很方便了,明白其原理后,一旦需要使用,写好模板后,可以直接移植,而且我发现,这个适合于Linux平台,也适合于Windows平台。
而且只要你
把规则写好,一个make命令就直接编译完成,自己只需要查看可执行文件就可以了
那就结合之前看过的视频对学习过的知识进行一个总结吧!!!
放出视频链接:
视频链接
makefile项目管理
一、用途:
项目代码编译管理 节省编译项目时间
二、 makefile的基础规则
1 个规则:
目标:依赖条件
(一个TAB缩进)命令
使用命令借助依赖条件去生成目标
目标的生成时间应该比依赖条件的生成目标晚
Makefile文件
出现错误原因及解决方式
运行hello,成功运行!
注意:
1.目标的时间必须晚于依赖条件的时间,否则,更新目标
2.依赖条件如果不存在,找寻新的规则去产生依赖条件。
依赖规则:如下 Makefile文件
执行make命令 成功生成hello.o hello
运行成功,木有问题
1.多文件联合编译
makefiletest目录下有以下文件
hello.c修改如下
此时编译,则需要多文件联合编译
对于当前文件,Makefile文件修改如下
执行make命令,成功生成a.out
执行a.out
修改add.c
再次make运行a.out
可以看到,只修改add.c,但是编译的时候,其他.c文件也重新编译了
明明只改了一个,全部都重新编译了
解决方法:
1.使用命令的方式进行编译
2.修改Makefile文件
执行make,成功生成a.out文件
2. makefile检测原理
修改div.c后,再次执行make
可以看到只重新编译了修改后的文件,而其他文件并没有编译
再次修改add.c,再次执行make
除法的结果没有改变,表明只编译了add.c,而div.c和其他文件并没有编译
Makefile文件中
使用命令借助依赖条件去生成目标
目标的生成时间应该比依赖条件的生成目标晚
当依赖条件比目标时间晚,目标就要被更新
makefile检测原理:
修改文件后,文件的修改时间发生变化,会
出现目标文件的时间早于作为依赖的时间,出现这种情况的文件会重新编译。
修改div.c后,div.o的时间就早于div.c ,a.out的时间也早于div.o的时间了,于是重新编译这俩文件了。
3. ALL来指定终极目标
ALL来指定终极目标
makefile的依赖是从上至下的,换句话说就是目标文件是第一句里的目标,如果不满足执行依赖,就会继续向下执行。如果满足了生成目标的依赖,就不会再继续向下执行了。
make会自动寻找规则里需要的材料文件,执行规则下面的行为生成规则中的目标。
修改Makefile文件,把生成a.out放在其他下面
执行make,可以看到只生成了hello.o,其他文件的.o并没有生成
同样,修改Makefile文件后,再次执行make,只执行了
这就说明了make命令会检查所写的Makefile文件,把它碰到的第一组规则中的目标,作为终极任务
解决方法:
ALL:终极目标
ALL存在的意义就是用来告诉make命令,当前Makefile文件中,不管碰到的第一组规则的目标是谁,最终要生成的目标一定是a.out
这样再执行make命令,文件都编译成功!
三、 makefile的两个函数和clean
makefile文件的变量类型只有一种,字符串类型
wildcard函数和patsubst函数
src = $(wildscard _.c)
匹配当前工作用户下的所有.c文件。
将文件名组成列表
,赋值给变量src。
找到当前目录下所有后缀为.c的文件,赋值给src
eg: _*src = add.c sub.c div.c hello.c__
匹配当前目录下所有后缀为.c的文件,赋值给src
$(wildcard arguments)函数 arguments表示函数的参数
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文件就可以更新了
执行make命令 运行结果
clean:(没有依赖)
clean:
(TAB缩进) rm -rf $(obj) a.out
循环删除所有.o和a.out文件
在执行make clean命令时,一定要加-n 去模拟执行
make clean -n
自己在查看-n命令后,认为无问题了,再执行,所有的.o文件和a.out文件都被删除了
Makefile文件里clean中的命令
clean:
-rm -rf $(obj) a.out
这里
rm前面的”-“表示出错依然执行,作用是删除不存在文件时,不报错,顺序执行结束。
四、 makefile中的三个自动变量
3个自动变量
$@:在规则命令中,
表示规则中的目标
$<:在规则命令中,
表示规则中的第一个依赖条件
如果将该变量用在模式规则中,它可以将依赖条件列表中的依赖依次取出,套用模式规则
%.o:%.c
(tab)
gcc -c $< -o $@
$^:在规则命令中,
表示规则中的所有依赖条件,组成一个列表,以空格隔开,如果这个列表中有重复项,则去重
由此,更新makefile文件
执行make命令,运行成功
五、模式规则
上面的Makefile可扩展型不强
比如,要添加一个乘法函数,就需要在Makefile里添加乘法的规则
解决方法:
模式规则
```
%.o:%.c
gcc -c $< -o $@
更新Makefile文件
![](https://guyueju.oss-cn-beijing.aliyuncs.com/Uploads/Editor/202308/20230809_52686.jpg)
执行make命令,运行成功
![](https://guyueju.oss-cn-beijing.aliyuncs.com/Uploads/Editor/202308/20230809_47255.jpg)
这样可移植性可扩展性就很强,比如再来一个mul乘法函数,下图可见成功make,成功运行
![](https://guyueju.oss-cn-beijing.aliyuncs.com/Uploads/Editor/202308/20230809_15753.jpg)
![](https://guyueju.oss-cn-beijing.aliyuncs.com/Uploads/Editor/202308/20230809_34156.jpg)
**六、 静态模式规则**
使用静态模式规则,就是指定模式规则给谁用,这里指定模式规则给obj用
以后文件多了,文件集合会有很多个,就需要指定哪个文件集合用什么规则
$(obj):%.o:%.c
gcc -c $< -o $@
Makefile文件优化如下
![](https://guyueju.oss-cn-beijing.aliyuncs.com/Uploads/Editor/202308/20230809_25926.jpg)
make成功,又一次优化
![](https://guyueju.oss-cn-beijing.aliyuncs.com/Uploads/Editor/202308/20230809_24225.jpg)
**七、 扩展
1. 扩展1 伪目标**
当文件夹下有ALL文件或者clean文件时,会导致makefile瘫痪,如下所示,make clean没有工作
用伪目标来解决,添加一行
伪目标的目的 不管条件满足与否,这个目标都要被执行
.PHONY: clean ALL
Makefile文件优化如下:
2. 扩展2 可添加常用的参数
编译时的参数,-g,-Wall, … 这些,可以放在makefile里面
再次优化Makefile
八、makefile最终形态
m1和Makefile最终形态
左边是第一版Makefile
右边是终极版本
源码add.c,sub.c这些在src目录下,.o文件要放在obj目录下,头文件mymath.h在inc目录下。
将hello.c中的头文件单独拿出来
inc/mymath.h
src/hello.c
这里一定要添加头文件噢,千万不要忘了,我就是在复习一遍的时候,将这里遗忘了,导致错误。
1. 修改Makefile文件
%的匹配理解,只匹配文件名
注意这里,也有错误噢,小坑,大家注意!!!!!
这样才是正确的Makefile,注意%的含义
% 只匹配文件名 而目录位置参数要自己主动设置
2. 执行make命令
成功运行,生成了a.out和其他.o文件
3. 使用make clean
删除.o文件和a.out文件
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++
大家只需要换相应的参数就可以啦!!!!
原文作者:藕粉-
原文链接:https://blog.csdn.net/cyaya6/article/details/129771224?spm=1001.2014.3001.5502
linuxC++CMakefile编译链接
转载原出处:https://blog.csdn.net/cyaya6/article/details/129771224?spm=1001.2014.3001.5502