【Makefile文件的测试和调试】

本文介绍了Makefile的测试命令、变量展示、Gcc选项、依赖关系管理和shell实用技巧,有助于提升开发者对Makefile的运用效率。
摘要由CSDN通过智能技术生成

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 文件中了
  1. -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
在生成的依赖文件中,指定依赖规则中的目标

  • 25
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值