GNU make调试

85

make中,有没有一种命令行方式可以找出目标的先决条件中哪些没有更新?


有没有类似详细模式的选项?你不能在每个目标处输入一些“echo”调试来找出问题吗? - Earlz
7个回答

123
make -d

这应该为您提供足够的信息来调试您的Makefile。

请注意:分析输出需要一些时间和精力,但将输出加载到您喜欢的编辑器中并进行搜索会有很大帮助。

如果您指定您感兴趣的特定目标,可以大大减少调试输出的数量。因此,如果您只对'dodgy'目标感兴趣,而不是仅使用make -d(可能有100个不同的东西),请尝试:

make clean
make -d dodgy

(假设当然你已经有了一个干净的目标clean)。

make --debugmake -d是相同的,但您还可以指定:

make --debug=FLAGS

其中flags可以是:

  • a表示所有调试信息(与make -dmake --debug相同)。
  • b表示基本调试信息。
  • v表示稍微详细的基本调试信息。
  • i表示隐含规则。
  • j表示调用信息。
  • m表示在重新生成makefile期间显示的信息。

从下面的记录中可以看出,make --debug=b是你需要的最佳选择:

pax@paxbox> cat makefile
c:a b
    touch c

pax@paxbox> touch a b ; make
touch c

pax@paxbox> make
make: 'c' is up to date.

pax@paxbox> touch a ; make --debug=b
GNU Make 3.81
Copyright (C) 2006  Free Software Foundation, Inc. Blah, blah, blah.
Reading makefiles...
Updating goal targets....
 Prerequisite 'a' is newer than target 'c'.
Must remake target 'c'.
touch c
Successfully remade target file 'c'.

7
另一个建议是,如果你想要摆脱内置的隐式规则,可以在-d之后加上-r标志。 - P Shved

29

您是否正在寻找Make的“试运行”功能?它将打印出make正在执行的内容,而不实际执行,使您可以看到发生了什么。

标志是-n,使用方法如下:make -n


这是我最喜欢的,-d 太啰嗦了(甚至 --debug=b 也是)。特别是当你卡在递归 make 上时(呃!)。 - Adam Lindberg

8
我通常不使用-d选项,就像之前的回答者所说。
我要么:
  1. 使用-p打印数据库,以查看已创建的规则。如果您有第二次扩展规则并且正在动态创建规则,特别是递归make,则这非常方便。
  2. 大量使用$(info)函数。
  3. 使用DrDobbs文章Debugging Makefiles中描述的提示和技巧。
下面是一些我用于打印值的代码:
define pv
$(info $(1) [$(origin $(1))] : >|$($(1))|<)
endef

define pva
$(foreach t,$(1),$(call pv,$(t)))
endef

define itemizer
$(foreach t,$($(1)),$(info $(t)))
endef

8

似乎在Windows上不存在。 - Radzor

7

你的问题有点不太清楚。如果您想查看哪些先决条件文件最近没有被修改,请使用ls -l查看它们的修改时间。如果您想查看make正在做什么,请尝试以下操作:

# Make会在制作此目标及其原因时进行公告。
sometarget: preq1 preq2 preq3
    @echo making $@
    @echo 以下先决条件比目标新:$?
    do_things

我也打算建议使用$?。 - just somebody
虽然不是一个命令行解决方案,但仍然很有用。您可以通过仅在设置了环境变量时执行回显来使其基于命令行。 - paxdiablo

1
我偶尔也会使用由John Graham-Cumming开发的交互式制作调试器this(虽然有点老但仍可用)。

0
我正在使用GNU Make模板来为每个目标定义Make规则;
模板类似于编写规则的宏,这里有更详细的解释 https://www.gnu.org/software/make/manual/html_node/Eval-Function.html 当您拥有一个Make系统来生成所有项目类型的规则时,这个功能非常有用;如果它指示要进行共享库,则编写编译共享库的规则;等待其他类型的目标。
在这个例子中:如果您在make命令行中添加SHOW_RULES=1,它还会显示由PROGRAM_target_setup_template生成的规则文本;以及使用eval生成规则本身。
 # this one defines the target for real
 $(foreach prog, $(TARGETS), $(eval $(call PROGRAM_target_setup_template,$(prog))))

 ifneq "$(SHOW_RULES)" ""
 $(foreach prog, $(TARGETS), $(info $(call PROGRAM_target_setup_template,$(prog))))
 endif
  • $(call ...) 调用模板
  • $(info ...) 打印模板替换的结果; (eval 会调用输出解析和添加到当前 make 文件)

关于我的 make 文件的更多信息,请参见这里:http://mosermichael.github.io/cstuff/all/projects/2011/06/17/make-system.html


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接