《跟我一起学makefile》学习笔记(六)

学习记录(对应文档的p51-p78)

六、call函数
    用途:写一个非常复杂的表达式。定义许多参数,用call函数向表达式传递参数
$(call <expression>, <parm1>, <parm2>, <parm3>...)
    执行时,expression参数中的变量,如$(1),会被参数parm1取代
七、origin函数
    告知变量的来源
$(origin <variable>)
    为什么要判断变量是哪来的?原因:
假设 Makefile 包了一个定义文件 Make.def,在Make.def 中定义了一个变量“bletch”,
有一个环境变量“bletch”。此时,我们想判断一下,如果变量来源于环境,那么我们就把
之重定义了,如果来源于 Make.def 或是命令行等非环境的,那么我们就不重新定义它。
ifdef bletch  
ifeq "$(origin bletch)" "environment"  
bletch = barf, gag, etc.  
endif
八、shell函数
    可以用操作系统命令以及字符串处理命令 awk,sed 等等命令来生成
一个变量,如:  
contents := $(shell cat foo)  
files := $(shell echo *.c)  
九、控制make的函数
1、error
$(error <text ...>)  
产生一个致命的错误,<text ...>是错误信息。注意,error函数不会在一被使用就会
产生错误信息,所以如果你把其定义在某个变量中,并在后续的脚本中使用这个变量,那么
也是可以的。例如:  
示例一:  
ifdef ERROR_001  
$(error error is $(ERROR_001))  
endif  
 
示例二:  
ERR = $(error found an error!)  
.PHONY: err  
err: ; $(ERR)  
 
示例一会在变量 ERROR_001 定义了后执行时产生 error 调用,而示例二则在目录 err
被执行时才发生 error调用。  
2、warning
$(warning <text ...>)

第十部分 make的运行
一、make的退出码
0 成功
1 出现任何错误
2 使用了make的-q选项,且make使得一些目标不需要更新
二、指定Makefile
    有个Makefile文件hchen.mk,需要执行
make -f hchen.mk
三、指定目标
    make的环境变量MAKECMDGOALS,存放指定的终极目标
    例子:
sources = foo.c bar.c  
ifneq ( $(MAKECMDGOALS),clean)  
include $(sources:.c=.d)  
endif  
  输入的命令不是“make clean”,那么 makefile 会自
动包含“foo.d”和“bar.d”这两个makefile。  
    GNU这种开源软件发布时,makefile都包含了编译、安装、打包等功能
    使用通用伪目标名称的好处:规范(不用解释,大家都懂)、实用、专业(不是初学者)
四、规则检查
    不想让Makefile执行,只是检查一下命令,使用make的参数:
“-n”  
“--just-print”  
“--dry-run”  
“--recon”
    上面这几个参数只打印命令,可用来调试Makefile
“-t”  
“--touch”  
    上面这个参数的意思就是把目标文件的时间更新,但不更改目标文件。也就是说,make 假
装编译目标,但不是真正的编译目标,只是把目标变成已编译过的状态。
“-q”  
“--question”  
这个参数的行为是找目标的意思,也就是说,如果目标存在,那么其什么也不会输出,
当然也不会执行编译,如果目标不存在,其会打印出一条出错信息
“-W <file>”  
“--what-if=<file>”  
“--assume-new=<file>”  
“--new-file=<file>”  
这个参数需要指定一个文件。一般是是源文件(或依赖文件),Make 会根据规则推导来
运行依赖于这个文件的命令,一般来说,可以和“-n”参数一同使用,来查看这个依赖文件
所发生的规则命令。  
 
另外一个很有意思的用法是结合“-p”和“-v”来输出 makefile 被执行时的信息(这
个将在后面讲述)
五、make的参数
    GNU make 3.80版参数
“-b”  
“-m”  
这两个参数的作用是忽略和其它版本 make 的兼容性。
“-B”  
“--always-make”  
认为所有的目标都需要更新(重编译) 。  
 
“-C <dir>”  
“--directory=<dir>”  
指定读取 makefile 的目录。如果有多个“-C”参数,make 的解释是后面的路径以前面
的作为相对路径,并以最后的目录作为被指定目录。如: “make –C  ~hchen/test –C  prog”
等价于“make –C ~hchen/test/prog”。  
 
“—debug[=<options>]”  
输出 make 的调试信息。它有几种不同的级别可供选择,如果没有参数,那就是输出最简单
的调试信息。下面是<options>的取值:  
a ——  all,输出所有的调试信息。(会非常的多)  
b ——  basic,只输出简单的调试信息。即输出不需要重编译的目标。  
v ——  verbose,在 b 选项的级别之上。输出的信息包括哪个 makefile 被解析,不
需要被重编译的依赖文件(或是依赖目标)等。  
i ——  implicit,输出所以的隐含规则。  
j ——  jobs,输出执行规则中命令的详细信息,如命令的 PID、返回码等。   
m ——  makefile,输出 make 读取 makefile,更新 makefile,执行 makefile 的信
息。
第十一部分 隐含规则
    “隐含规则”会使用系统变量,如系统变量“CFLAGS”可以控制编译时的编译器参数。  
一、使用隐含规则
foo : foo.o bar.o
cc -o foo foo.o bar.o $(CFLAGS) $(LDFLAGS)
    make会自动推导如何生成foo.o和bar.o
二、隐含规则一览
    取消预设值的隐含规则,make的参数-r或--no-builtin-rules
1、编译C程序的隐含规则
    .o的目标自动找对应的.c文件,生成命令$(CC) -c $(CPPFLAGS) $(CFLAGS)
2、编译C++程序的隐含规则
    .o的目标自动找对应的.cc文件,生成命令$(CXX) -c $(CPPFLAGS) $(CFLAGS)
3、Pascal
    .o的目标自动找对应的.p文件,生成命令$(PC) -c $(PFLAGS)
4、编译Fortran/Ratfor
5、预处理Fortran/Ratfor
6、Modulate-2
7、汇编和汇编预处理的规则
    .o的目标自动找对应的.s文件,默认使用编译器as,生成命令$(AS) $(ASFLAGS)
    .s的目标自动找对应的.S文件,默认使用C预编译器cpp,生成命令$(AS) $(ASFLAGS)
8、链接Object
    “<n>”目标依赖于“<n>.o”,通过运行 C 的编译器来运行链接程序生成(一般是
“ld”) ,生成命令“$(CC) $(LDFLAGS) <n>.o $(LOADLIBES) $(LDLIBS)”。这个规
则对于只有一个源文件的工程有效,同时也对多个 Object 文件(由不同的源文件生成)的
也有效。
9、Yacc C
10、Lex C
11、Lex Ratfor
12、从 C 程序、Yacc文件或 Lex 文件创建Lint 库的隐含规则
三、隐含规则使用的变量
1、关于命令的变量
AR 函数库打包程序,默认命令是ar
AS 汇编语言编译程序,as
CC C语言编译程序,cc
CXX C++语言编译程序,gcc
CO 从RCS文件中扩展文件程序,co
CPP C程序的预处理器,$(CC) -E
FC Fortran 和 Ratfor 的编译器和预处理程序。f77。  
GET 从 SCCS 文件中扩展文件的程序。默认命令是“get”。  
LEX Lex 方法分析器程序(针对于 C 或Ratfor)。默认命令是“lex”。  
PC  Pascal 语言编译程序。默认命令是“pc”。  
YACC Yacc 文法分析器(针对于 C 程序) 。默认命令是“yacc”。  
YACCR Yacc 文法分析器(针对于 Ratfor 程序) 。默认命令是“yacc –r”。  
MAKEINFO  转换 Texinfo 源文件(.texi)到 Info 文件程序。默认命令是“makeinfo”。
TEX  从 TeX 源文件创建 TeX DVI 文件的程序。默认命令是“tex”。  
TEXI2DVI 从 Texinfo源文件创建军 TeX DVI 文件的程序。默认命令是“texi2dvi”。  
WEAVE  转换 Web 到TeX 的程序。默认命令是“weave”。  
CWEAVE 转换 C Web 到 TeX 的程序。默认命令是“cweave”。  
TANGLE 转换 Web 到Pascal 语言的程序。默认命令是“tangle”。  
CTANGLE 转换 C Web 到 C。默认命令是“ctangle”。  
RM  删除文件命令。默认命令是“rm –f”。
2、关于命令参数的变量
四、隐含规则链
    如果文件[.c]存在,直接调用 C的编译器的隐含规则
    如果没有[.c]文件,但有一个[.y]文件,那么 Yacc 的隐含规则会被调用,生成[.c]文件,
    然后,再调用 C 编译的隐含规则最终由[.c]生成[.o]文件,达到目标
 
    通常,一个被 makefile 指定成目标或是依赖目标的文件不能被当作中介。但可
以明显地说明一个文件或是目标是中介目标,使用伪目标“.INTERMEDIATE”来强制声明。
(如:.INTERMEDIATE : mid )
五、定义模式规则
1、模式规则介绍
    至少在规则的目标定义中要包含"%",否则,就是一般的规则。
2、模式规则示例
    下面这个例子表示了,把所有的[.c]文件都编译成[.o]文件.  
%.o : %.c  
$(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@  
其中,"$@"表示所有的目标的挨个值,"$<"表示了所有依赖目标的挨个值。
3、自动化变量
    目的:从不同的依赖文件生成相应的目标
$@ 目标文件集
$% 仅当目标是函数库文件中,表示规则中的目标成员名
    例子:目标是"foo.a (bar.o)",那么,"$%"就是"bar.o","$@"就是"foo.a"。
    如果目标不是函数库文件,其值为空。
$<  依赖目标中的第一个目标名字。如果依赖目标是以模式(即"%")定义的,那么"$<"将
是符合模式的一系列的文件集。注意,其是一个一个取出来的。  
$?  所有比目标新的依赖目标的集合。以空格分隔。  
$^  所有的依赖目标的集合。以空格分隔。如果在依赖目标中有多个重复的,只保留一份。  
$+  这个变量很像"$^",也是所有依赖目标的集合。只是它不去除重复的依赖目标。  
$*  这个变量表示目标模式中"%"及其之前的部分。如果目标是"dir/a.foo.b",并且目标的
模式是"a.%.b",那么,"$*"的值就是"dir/a.foo"。
如果目标中没有模式的定义,那么"$*"也就不能被推导出,但是,如果目标文件的
后缀是 make所识别的,那么"$*"就是除了后缀的那一部分。例如:如果目标是"foo.c",因
为".c"是 make 所能识别的后缀名,所以,"$*"的值就是"foo"。这个特性是 GNU make 的
4、模式的匹配
  % 茎
5、重载内建隐含规则
六、老式风格的“后缀规则”
七、隐含规则搜索算法
    后缀规则在 Makefile 被载入内存时,会被转换成模式规则
    目标T 搜索分7步
第十二部分 使用make更新函数库文件
    函数库文件也就是对 Object 文件(程序编译的中间文件)的打包文件。在 Unix 下,一
般是由命令"ar"来完成打包工作。  
一、函数库文件的成员
    一个函数库文件由多个文件组成,指定函数库文件及其组成:
archive(member)定义一个目标和依赖,为ar服务,如:
foolib(hack.o) : hack.o
ar cr foolib hack.o
二、函数库成员的隐含规则
    make执行的命令大致如下:
cc -c bar.c -o bar.o
ar r foo.a bar.o
rm -f bar.o
三、函数库文件的后缀规则
    使用后缀规则和隐含规则,生成函数库打包文件
.c.a:
$(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $*.o
$(AR) r $@ $*.o
$(RM) $*.o
四、注意
    在进行函数库打包文件生成时,小心使用 make 的并行机制("-j"参数)
    如果多个ar 命令在同一时间运行在同一个函数库打包文件上,就很有可以损坏这个函数库文件。
    在 make未来的版本中,应该提供一种机制来避免并行操作发生在函数打包文件上。  
第十三部分 后序
    make 以文件的依赖性为基础
    make 不仅可以编译程序,也可以完成其他工作,因为规则中的命令可以是shell下的任何命令
    可以在Makefile中写其他命令:tar、awk、mail、sed、cvs、compress、ls、rm、yacc、rpm、ftp
    可以实现的功能:程序打包、备份、制作程序安装包、提交代码、使用程序模板、合并文件

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值