Makefile文件的测试和调试
本文是对网上的相关文件进行的测试和汇总
文章目录
命令行选项
1. -n --just-print
不执行真实的动作,但会显示每条命令。
2. -p --print-database
输出内部数据库。
Variables / Dirctories / implicity Rules /pattern /files / vpath
3.–debug {=basic,verbose,implicit,jobs,all, makefile}
–debug=verbose 比较有用
4. -s 沉默模式,在执行之前不输出相应的命令行信息。
-i 忽略命令执行返回的出错信息。
-r 禁止使用build-in规则
-t 更新目标文件。
-q make操作将根据目标文件是否已经更新返回"0"或非"0"的状态信息
在Makefile中输出变量的内容
1.在Makefile中加入${info(warning ,error} ${var}}
info 输出在stdout
warning,error的输出在stderr.
2. 编写vars.mk文件
%:
@echo '$*=$($*)/'
d-%:
@echo ' $*=$($*)'
@echo ' origin=$(origin *)'
@echo ' value =$(value *)'
@echo ' flavor=$(flavor *)'
获取变量ROOT,则如下所示
make -f makefile ROOT -f vars.mk
若想获取ROOT详细内容,则如下所示
make -f makefile d-ROOT -f vars.mk
输出如下:
ROOT=.
origin=automatic
value =ROOT
flavor=simple
其中
- origin:表示变量的来源,有如下几种可能:
file,enviroment,envirmonent override,command line,override,automatic - value: 表示变量没有展开的样子
- flavor: simple/recursive
Makefile中常用符号
- PHONY 表明target不是文件
- ?= 如果没有被赋值过就赋予等号后面的值
- := 覆盖之前的值
- 依赖中带有管道符号: |
依赖的类型
在 GNU make 的规则中可以使用两种不同类型的依赖:
1. 以前章节所提到的规则中使用的是常规依赖,这是书写 Makefile 规则时最常用的一种。
2. 另外一种在我们书写 Makefile 时不会经常使用,它比较特殊、称之为“ order-only”依赖。
一个规则的常规依赖(通常是多个依赖文件)表明了两件事:
首先,它决定了重建此规则目标所要执行规则(确切的说是执行命令)的顺序;表明在更新这个规则的目标(执行此规则的命令行)之前需要按照什么样的顺序、执行那些规则(命令)来重建这些依赖文件(对所有依赖文件的重建,使用明确或者隐含规则。就是说对于这样的规则: A:B C,那么在重建目标 A 之前,首先需要完成对它的依赖文件 B 和 C 的重建。重建 B 和 C 的过程就是执行 Makefile 中以文件 B 和 C 为目标的规则)。
其次,它确定了一个依存关系;规则中如果依赖文件的任何一个比目标文件新,则认为规则的目标已经过期而需要重建目标文件。
有时,需要定义一个这样的规则,在更新目标( 目标文件已经存在)时只需要根据依赖文件中的部分来决定目标是否需要被重建,而不是在依赖文件的任何一个被修改后都重建目标。为了实现这一目的,相应的就需要对规则的依赖进行分类,一类是在这些依赖文件被更新后,需要更新规则的目标;另一类是更新这些依赖的,可不需要更新规则的目标。我们把第二类称为:“ order-only”依赖。书写规则时,“ order-only”依赖使用管道符号“ |”开始,作为目标的一个依赖文件。规则依赖列表中管道符号“ |”左边的是常规依赖,管道符号右边的就是“ order-only”依赖。这样的规则书写格式如下:
TARGETS : NORMAL-PREREQUISITES | ORDER-ONLY-PREREQUISITES
NORMAL-PREREQUISITES:改变后需要更新target
ORDER-ONLY-PREREQUISITES: 第一次构造targets时才会使用
Gcc中常用的一些选项
- lnosys 提供空的底层系统函数以便程序通过编译。
- lc lm libc是标准C库,libm是标准数学库
- –w 关闭警告
- -W 只显示必要的警告
- -Wall 显示所有警告
- -ffunction-sections和 -fdata-sections 将每个函数或符号创建为一个sections,
- -Wl,–gc-sections 指示链接器去掉不用的section
- -specs=nano.specs 将 -lc 替换成 -lc_nano,使有精简版的C库替代标准C库,可以减少最终程序映像的大小
- -Wl 将后面的参数传给ld,链接器
Makefile中常用变量和函数
- MAKEFILE_LIST include时会自动追加此变量中
- lastword 最后一个字段
- $(dir ) 函数的功能是从文件名序列 names 中取出目录部分,如果names 中没有 / ,取出的值为 ./ 。返回值为目录部分,指的是最后一个反斜杠之前的部分。如果没有反斜杠将返回 ./。
- $(notdir ) 函数的功能是从文件名序列 names 中取出非目录的部分。非目录的部分是最后一个反斜杠之后的部分。返回值为文件非目录的部分。
- $(suffix ) 函数的功能是从文件名序列中 names 中取出各个文件的后缀名。返回值为文件名序列 names 中的后缀序列,如果文件没有后缀名,则返回空字符串。
- $(basename ) 函数的功能是从文件名序列 names 中取出各个文件名的前缀部分。返回值为被取出来的文件的前缀名,如果文件没有前缀名则返回空的字符串。
- $(addsuffix ,) 函数的功能是把后缀 suffix 加到 names 中的每个单词后面。返回值为添加上后缀的文件名序列。
- $(addperfix ,) 函数的功能是把前缀 prefix 加到 names 中的每个单词的前面。返回值为添加上前缀的文件名序列。
- $(join ,) 函数功能是把 list2 中的单词对应的拼接到 list1 的后面。
如果 list1 的单词要比 list2 的多,那么,list1 中多出来的单词将保持原样,如果 list1 中的单词要比 list2 中的单词少,那么 list2 中多出来的单词将保持原样。返回值为拼接好的字符串。
OBJ=$(join aa bb, cc dd ee)
all:
echo $(OBJ)
-wohu@ubuntu:~/cpp/func$ make
echo aacc bbdd ee
aacc bbdd ee
wohu@ubuntu:~/cpp/func$
-
$(wildcard PATTERN) 函数的功能是列出当前目录下所有符合模式的 PATTERN 格式的文件名。返回值为空格分隔并且存在当前目录下的所有符合模式 PATTERN 的文件名。
-
$(patsubst ,,
) -
可以包括通配符“%”,表示任意长度的字串。如果中也包含“%”,那么,中的这个“%”将是中的那个“%”所代表的字串。
-
$(filter PATTERN…,TEXT) 过滤掉字串“TEXT”中所有不符合模式“PATTERN”的单词,保留所有符合此模式的单词。可以使用多个模式。模式中一般需要包含模式字符“%”。存在多个模式时,模式表达式之间使用空格分割。
-
ifneq (,$(filter $(ARCH), x86_64 amd64)) 如果filter不为空,则执行
-
$(findstring FIND,IN) 如果在“IN”之中存在“FIND” ,则返回“FIND”,否则返回空。
-
@这个符串通常用在“规则”行中,表示不显示命令本身,而只显示它的结果,
-
$@ --代表目标文件(target)
-
$^ --代表所有的依赖文件(components)
-
$< --代表第一个依赖文件(components中最左边的那个)。
-
$? --代表示比目标还要新的依赖文件列表。以空格分隔。
-
% --仅当目标是函数库文件中,表示规则中的目标成员名。例如,如果一个目标是"foo.a(bar.o)",那么," %“就是"bar.o”,"$@“就是"foo.a”。如果目标不是函数库文件(Unix下是[.a],Windows下是[.lib]),那么,其值为空。
-
通常删除,创建文件如果碰到文件不存在或者已经创建,那么希望忽略掉这个错误,继续执行,就可以在命令前面添加 -,
-
-rm dir;
-
’ $ '符号的使用
美元符号$,主要扩展打开makefile中定义的变量 -
’ ′ 符号的使用 '符号的使用 ′符号的使用 符号主要扩展打开makefile中定义的shell变量
-
$(@D) $@的目录部分
-
$(@F) $@的文件部分
-
$(@:.elf=.d) 目标文件,但.elf替换成.d
常用shell命令
- grep “xxx” file : 输出当前行,每一个字段为$1,$2,$3…
- awk ‘print $$3’
- uname linux
- uname -m x86_64
- gcc 可以使用 C/C++ 编译器的 “-M” 系列选项,即自动获取源文件中包含的头文件,并生成一个依赖关系。
1.生成文件的依赖关系,同时也把一些标准库的头文件包含了进来。本质是告诉预处理器输出一个适合 make 的规则,用于描述各目标文件的依赖关系。对于每个源文件,预处理器输出 一个 make 规则,该规则的目标项 (target) 是源文件对应的目标文件名,依赖项 (dependency) 是源文件中 “#include” 引用的所有文件,生成的规则可以是单行,但如果太长,就用’'换行符续成多行。规则显示在标准输出,不产生预处理过的 C 程序。
2.-MM
生成文件的依赖关系,和 -M 类似,但不包含标准库的头文件
3.-MG
要求把缺失的头文件按存在对待,并且假定他们和源文件在同一目录下,必须和 ‘-M’ 选项一起用。
4.-MF File
当使用了 “-M” 或者 “-MM” 选项时,则把依赖关系写入名为 “File” 的文件中。若同时也使用了 “-MD” 或 “-MMD”,“-MF” 将覆写输出的依赖文件的名称 。
gcc -M -MF main.d main.c
则 “-M” 输出的内容就保存在 main.d 文件中了
- -MD
等同于 -M -MF File,但是默认关闭了 -E 选项。其输出的文件名是基于 -o 选项,若给定了 -o 选项,则输出的文件名是 -o 指定的文件名,并添加 .d 后缀,若没有给定,则输入的文件名作为输出的文件名,并添加 .d 后缀,同时继续指定的编译工作。
注意:-MD 不会像 -M 那样阻止正常的编译任务,因为它默认关闭了 -E 选项,比如命令中仅使用了 -c 选项而没有指定 -o 选项时,若同时使用了 -M 选项,则不会生成 .o 文件,若使用的是 -MD 选项,则会生成 .o 文件
6. -MMD
类似于 “-MD”,但是输出的依赖文件中,不包含标准头文件
7. -MP
生成的依赖文件里面,依赖规则中的所有 .h 依赖项都会在该文件中生成一个伪目标,其不依赖任何其他依赖项。该伪规则将避免删除了对应的头文件而没有更新 “Makefile” 去匹配新的依赖关系而导致 make 出错的情况出现。
8. -MT Target
在生成的依赖文件中,指定依赖规则中的目标