调试 GNU make

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

100938 次浏览
make -d

应该给你的 更多比足够的信息来调试你的 makefile。

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

如果指定感兴趣的特定目标,则可以大大减少调试输出的数量。因此,如果你只对 dodgy目标感兴趣,而不是仅仅对 make -d目标感兴趣,它可能会产生上百种不同的东西,试试:

make clean
make -d dodgy

(当然,假设您有一个 clean目标)。

make --debugmake -d完全相同,但你也可以指定:

make --debug=FLAGS

旗帜的位置:

  • 所有调试的 a(与 make -dmake --debug相同)。
  • b进行基本调试。
  • v用于稍微详细一些的基本调试。
  • 隐式规则的 i
  • 调用信息的 j
  • 在 makefile 重制期间获取信息的 m

看起来 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'.

你在找马克的“演习”吗?它会打印出 make 正在做什么,而不用真的这么做,这样你就可以看到发生了什么。

标志是 -n,像 make -n一样使用它。

你的问题有点含糊。如果希望查看哪些必备条件文件最近没有被修改,请使用 ls-l 查看它们的修改时间。如果你想知道 make 在做什么,试试这个:

# Make will announce when it is making this target, and why.
sometarget: preq1 preq2 preq3
@echo making $@
@echo The following preqs are newer than the target: $?
do_things

还有带有调试器和更好的跟踪/错误输出的 GNU make: 重拍

尽管这两者仍然相关,但都有点过时了。

有几次我也使用了 John Graham-Cumming 交互式 make debug

我通常不会像前面的答案那样使用 -d。

我要么:

  1. 使用-p 打印数据库,查看创建了哪些规则。如果您有第二个展开规则并且正在动态创建规则,特别是递归 make,那么这很方便。
  2. 大量使用 $(info)函数。
  3. 使用 DrDobbs 文章 调试 Makefile中描述的提示和技巧

下面是我用来打印值的一些代码:

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

我使用 make gnu make 模板来定义每个目标的 make 规则;

模板就像编写规则的宏,这里解释 https://www.gnu.org/software/make/manual/html_node/Eval-Function.html

当你有一个 make 系统,其中包含一个核心 makefile 来生成每个项目类型的所有规则时,这个特性是非常有用的; 如果它说要做一个共享库,那么它就编写规则来编译一个共享库; 等等,用于其他类型的目标。

在这个例子中: 如果将 SHOW _ RULES = 1添加到 make 命令行,它还会显示由 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