[首页]
[文章]
[教程]
首页
Web开发
Windows开发
编程语言
数据库技术
移动平台
系统服务
微信
设计
布布扣
其他
数据分析
首页
>
其他
> 详细
2.26-GNU Make Tutorial
时间:
2019-07-01 22:49:21
阅读:
104
评论:
0
收藏:
0
[点我收藏+]
以下为《跟我一起学写Makefile》的笔记
学习目标:能够写小型工程的Makefile,能够看懂CMake自动生成的Makefile
Make 工具是一个自动化编译工具,写一个脚本文件便可决定整个工程的编译规则,比如哪一个文件先编译,哪些文件后编译,编译好的文件放在什么目录中,等等。
书上的版本为3.80,本机版本为3.81,可见make工具这么多年来都没有更新
关于编译知识,还得系统学习龙书《编译原理》
示例工程里有3个头文件和8个C文件,由于没有下载,只好推测之
command.c display.c insert.c search.c files.c utils.c main.c kbd.c
defs.h command.h buffer.h
第一行为依赖关系,第二行为命令,第二行需要以Tab键开头
我们还可以定义“clean”等与编译无关的动作
GNU Make 可以自动推倒文件以及文件依赖关系后面的命令
“.PHONY”显式地表示此目标是一个伪文件,用以避免与文件重名
命令前面添加“-”的作用是:如果此命令执行错误,则忽略此错误,继续执行其他命令
不要设置${MAKEFILES}环境变量
分号“;”用来分隔多个命令
如果命令过长,使用反斜杠“\”分行
伪目标的特点是,永远是最新的,后面如果有依赖文件则永远要更新
“$?” 表示:
"$@" 表示:一个数组存放目标集合,其中顺次存放着所有的目标
“$<”表示:所有的依赖目标集
gcc命令:gcc -MM main.c 自动生成文件依赖关系,则不需要在Makefile中写明依赖关系(-M 将把标准库的头文件也包含进来)
如果你希望上一条命令的结果应用到下一条命令时,用分号分隔这两条命令
传统的Makefile变量名是大写的,但是现在推荐大小写搭配的变量名,这样可以避免和系统的变量冲突,发生意外。
一般来讲,使用变量名应该这样:${},加上括号完全是为了更加安全。
变量名的本质是宏,在运行时会先扩展,本质就是“扩展”
“=”和“:=”的不同在于:前者可以引用后面的变量,后者只能引用前面的变量
目标型变量:为某个目标设置局部变量,它的作用范围只在这条规则以及连带规则中,所以其值只在作用范围内有效,而不会影响规则链之外的全局变量的值
模式变量:我们可以把变量定义在符合一种模式的所有目标上,这样的变量同样是局部变量
条件表达式:Make是在读取Makefile时就计算条件表达式的值,相当于C语言的预编译,所以在条件表达式中最好不要放置自动化变量(如“$@”),因为自动化变量是在运行时才有的,而且不允许把整个条件语句分成两部分放在不同的文件中。
函数包括:字符串操作函数;文件名操作函数;foreach 函数;if, call, origin, shell函数,控制Make 的 error, warning函数
Make的运行:制定Makefile,制定目标,等
Make的参数:路径参数若有多个,则后面的路径以前面的路径作为相对路径,并以最后的目录作为被制定目录。
-j --jobs:同时运行命令的个数
Make隐含规则:如果要使用隐含规则生成你需要的目标,你所需要做的就是不要写出这个目标的规则
隐含规则是有顺序的,越靠前的规则越是被经常使用的,如果你显式制定了规则,但是这个规则前面还有“隐含规则”,那么隐含规则一样会生效。
隐含规则有两种,“模式规则”和“后缀规则”
后缀规则:只要有文件的后缀包含在“后缀列表”中,那么这些隐含规则就会生效。
隐含规则的变量,分关于命令的变量和关于参数的变量。
CPP为C的预处理器
C++源程序后缀为*.cc
函数库文件其实是对*.obj或*.o中间文件的打包文件,在UNIX中,静态库为*.a,动态库为*.so。
重点——模式规则
使用模式规则来定义一个隐含规则
“%”的意思是表示一个或多个任意字符。在依赖项目中同样可以使用“%”,只是依赖项目的取值,取决于其目标。这就是说,目标中的“%”值决定了依赖目标中的值
%.o : %.c ; <command ......>
一旦依赖目标中的"%"模式被确定,那么,make 会被要求去匹配当前目录下所有的文件名
重点——自动化变量!
自动化变量
"$@"表示所有的目标的挨个值,"$<"表示了所有依赖目标的挨个值。
$@
表示规则中的目标文件集。
$@
表示规则中的目标文件集。在模式规则中,如果有多个目标,那么,"$@"就是匹配于
目标中模式定义的集合。
$%
仅当目标是函数库文件中,表示规则中的目标成员名。例如,如果一个目标是"foo.a
(bar.o)",那么,"$%"就是"bar.o","$@"就是"foo.a"。如果目标不是函数库文件(Unix
下是[.a],Windows 下是[.lib]),那么,其值为空。
$<
依赖目标中的第一个目标名字。如果依赖目标是以模式( 即"%")定义的,那么"$<"将
是符合模式的一系列的文件集。注意,其是一个一个取出来的。
$?
所有比目标新的依赖目标的集合。以空格分隔。
$^
所有的依赖目标的集合。以空格分隔。如果在依赖目标中有多个重复的,那个这个变量
会去除重复的依赖目标,只保留一份。
$+
这个变量很像"$^",也是所有依赖目标的集合。只是它不去除重复的依赖目标。
$*
这个变量表示目标模式中"%"及其之前的部分。如果目标是"dir/a.foo.b",并且目标的
模式是"a.%.b",那么,"$*"的值就是"dir/a.foo"。这个变量对于构造有关联的文件名是比
较有较。如果目标中没有模式的定义,那么"$*"也就不能被推导出,但是,如果目标文件的
后缀是 make 所识别的,那么"$*"就是除了后缀的那一部分。例如:如果目标是"foo.c",因
为".c"是 make 所能识别的后缀名,所以,"$*"的值就是"foo"。这个特性是 GNU make 的,
很有可能不兼容于其它版本的 make,所以,你应该尽量避免使用"$*",除非是在隐含规则
或是静态模式中。如果目标中的后缀是 make 所不能识别的,那么"$*"就是空值。
当你希望只对更新过的依赖文件进行操作时,"$?"在显式规则中很有用,例如,假设有
一个函数库文件叫"lib",其由其它几个 object 文件更新。那么把 object 文件打包的比较
有效率的 Makefile 规则是:
lib : foo.o bar.o lose.o win.o
ar r lib $?
在上述所列出来的自动量变量中。四个变量($@、$<、$%、$*)在扩展时只会有一个文
件,而另三个的值是一个文件列表。这七个自动化变量还可以取得文件的目录名或是在当前
目录下的符合模式的文件名,只需要搭配上"D"或"F"字样。这是 GNU make 中老版本的特性,
在新版本中,我们使用函数"dir"或"notdir"就可以做到了。"D"的含义就是 Directory,就
是目录,"F"的含义就是 File,就是文件。
下面是对于上面的七个变量分别加上"D"或是"F"的含义:
$(@D)
表示"$@"的目录部分(不以斜杠作为结尾),如果"$@"值是"dir/foo.o",那么"$(@D)"
就是"dir",而如果"$@"中没有包含斜杠的话,其值就是"."(当前目录)。
$(@F)
表示"$@"的文件部分,如果"$@"值是"dir/foo.o", 那么"$(@F)"就是"foo.o","$(@F)"
相当于函数"$(notdir $@)"。
"$(*D)"
"$(*F)"
和上面所述的同理,也是取文件的目录部分和文件部分。对于上面的那个例子, "$(*D)"
返回"dir",而"$(*F)"返回"foo"
"$(%D)"
"$(%F)"
分别表示了函数包文件成员的目录部分和文件部分。这对于形同"archive(member)"形
式的目标中的"member"中包含了不同的目录很有用。
"$(<D)"
"$(<F)"
分别表示依赖文件的目录部分和文件部分。
"$(^D)"
"$(^F)"
分别表示所有依赖文件的目录部分和文件部分。(无相同的)
"$(+D)"
"$(+F)"
分别表示所有依赖文件的目录部分和文件部分。(可以有相同的)
"$(?D)"
"$(?F)"
分别表示被更新的依赖文件的目录部分和文件部分。
最后想提醒一下的是,对于"$<",为了避免产生不必要的麻烦,我们最好给$后面的那
个特定字符都加上圆括号,比如,"$(<)"就要比"$<"要好一些。
还得要注意的是,这些变量只使用在规则的命令中,而且一般都是"显式规则"和"静态
模式规则"(参见前面"书写规则"一章)。其在隐含规则中并没有意义。
2.26-GNU Make Tutorial
原文:https://www.cnblogs.com/lizhensheng/p/11117200.html
踩
(
0
)
赞
(
0
)
举报
评论
一句话评论(
0
)
登录后才能评论!
分享档案
更多>
2021年09月23日 (328)
2021年09月24日 (313)
2021年09月17日 (191)
2021年09月15日 (369)
2021年09月16日 (411)
2021年09月13日 (439)
2021年09月11日 (398)
2021年09月12日 (393)
2021年09月10日 (160)
2021年09月08日 (222)
最新文章
更多>
2021/09/28 scripts
2022-05-27
vue自定义全局指令v-emoji限制input输入表情和特殊字符
2022-05-27
9.26学习总结
2022-05-27
vim操作
2022-05-27
深入理解计算机基础 第三章
2022-05-27
C++ string 作为形参与引用传递(转)
2022-05-27
python 加解密
2022-05-27
JavaScript-对象数组里根据id获取name,对象可能有children属性
2022-05-27
SQL语句——保持现有内容在后面增加内容
2022-05-27
virsh命令文档
2022-05-27
教程昨日排行
更多>
1.
list.reverse()
2.
Django Admin 管理工具
3.
AppML 案例模型
4.
HTML 标签列表(功能排序)
5.
HTML 颜色名
6.
HTML 语言代码
7.
jQuery 事件
8.
jEasyUI 创建分割按钮
9.
jEasyUI 创建复杂布局
10.
jEasyUI 创建简单窗口
友情链接
汇智网
PHP教程
插件网
关于我们
-
联系我们
-
留言反馈
- 联系我们:wmxa8@hotmail.com
© 2014
bubuko.com
版权所有
打开技术之扣,分享程序人生!
↑
↓