我该如何强制让make/GCC显示命令?

393

我正在尝试调试一个编译问题,但是我似乎无法让GCC(或者可能是make??)显示它实际执行的编译器和链接器命令。

这是我看到的输出:

  CCLD   libvirt_parthelper
libvirt_parthelper-parthelper.o: In function `main':
/root/qemu-build/libvirt-0.9.0/src/storage/parthelper.c:102: undefined reference to `ped_device_get'
/root/qemu-build/libvirt-0.9.0/src/storage/parthelper.c:116: undefined reference to `ped_disk_new'
/root/qemu-build/libvirt-0.9.0/src/storage/parthelper.c:122: undefined reference to `ped_disk_next_partition'
/root/qemu-build/libvirt-0.9.0/src/storage/parthelper.c:172: undefined reference to `ped_disk_next_partition'
/root/qemu-build/libvirt-0.9.0/src/storage/parthelper.c:172: undefined reference to `ped_disk_next_partition'
collect2: ld returned 1 exit status
make[3]: *** [libvirt_parthelper] Error 1

我想看到的应该类似于这样:

$ make
gcc -Wall   -c -o main.o main.c
gcc -Wall   -c -o hello_fn.o hello_fn.c
gcc   main.o hello_fn.o   -o main

注意这个例子完整地显示了gcc命令。而上面的例子只显示类似于"CCLD libvirt_parthelper"这样的东西。我不确定如何控制这种行为。


你是在运行一个Makefile文件还是只是使用gcc命令? - Blender
30
这看起来像是Kbuild或者Autotools的输出。尝试使用***make V=1***命令。 - jww
8个回答

377

要执行模拟运行,请执行以下操作:

make -n

这将展示make试图做什么。


39
找到了 :)将 "make V=1" 输入命令行。虽然上述建议中的 "make -n" 也可以起作用。 :)感谢大家的回复。 - hernejj
93
区别在于 make -n 不会执行命令,因此正确答案是 make V=1 - m-ric
26
只有支持"make V=1"的Makefile才能使用该命令。Automake的Makefile可以支持,但许多其他Makefile则不行。 - larsr
81
对于CMake,请使用 make VERBOSE=1;对于GNU autotools,请使用 make V=1 - Ruslan
17
如果你想要真正运行命令,请考虑使用make SHELL='sh -x':https://dev59.com/dG025IYBdhLWcg3wvIu2#32010960 - Ciro Santilli OurBigBook.com
显示剩余2条评论

247

构建系统无关的方法

make SHELL='sh -x'

还有另一个选项。示例Makefile

a:
    @echo a

输出:

+ echo a
a

这将为make设置特殊的SHELL变量,而-x告诉sh在执行之前打印扩展后的行。

-n相比,一个优点是它实际运行命令。我发现对于某些项目(例如Linux内核),-n可能会比通常停止运行得早得多,可能是因为依赖问题。

这种方法的一个缺点是您必须确保将使用的 shell 是 sh,这是 Make 使用的默认 shell,因为它们是 POSIX,但可以使用 SHELL make 变量更改。

也可以尝试执行 sh -v,但是 Dash 0.5.7(Ubuntu 14.04 sh)会忽略 -c 命令(似乎是 make 的使用方式),因此它不起作用。

make -p 也很有趣,它会打印设置变量的值。

CMake 生成的 Makefile 始终支持 VERBOSE=1

例如:

mkdir build
cd build
cmake ..
make VERBOSE=1

问题链接:使用CMake和GNU Make:如何查看确切的命令?


18
绝对是最佳答案,不受原始Makefile的编写/生成质量影响。 - nodakai
2
如果有人能解释一下为什么要点踩,请告诉我,这样我就可以学习并改进信息了;-) - Ciro Santilli OurBigBook.com
1
使用SHELL='$$SHELL -x'会使$SHELL成为字面量而不被评估。使用make SHELL="$SHELL -x"将起作用。 - Rick van der Zwet
2
使用 SHELL='sh -x' 真是太棒了! - Jackie Yeh
1
SHELL += -x 可能是更好的方法。 - artless noise
显示剩余3条评论

215

库文件的makefile是由autotools生成的(您必须发出./configure命令),通常具有详细选项,因此基本上使用make VERBOSE=1make V=1应该会给您完整的命令。

但这取决于makefile的生成方式。

-d选项可能有帮助,但它将提供非常长的输出。


71
注意:通过CMake生成的Makefile仅支持VERBOSE=1,不支持V=1 - blinry
4
V=1 对我很有用,在使用 mips-linux-gnu-gcc 编译 NuttX 时,谢谢。 - jcomeau_ictx

38
自从GNU Make 4.0版本以来,--trace参数成为查看makefile执行何事以及原因的好方法,输出如下行:
makefile:8: target 'foo.o' does not exist

或者
makefile:12: update target 'foo' due to: bar

2
这个参数打印的信息比干运行更详细。对于理解像dpdk这样具有复杂构建过程的make系统非常有帮助。 - makerj
@makerj:也许是这样,但它确实执行命令,不像 make -n - einpoklum

31

使用make V=1

其他建议如下:

  • make VERBOSE=1 - 从我的测试中至少不能工作。
  • make -n - 仅显示逻辑操作,而不是正在执行的命令行。例如:CC source.cpp

  • make --debug=j - 同样有效,但可能也会启用多线程构建,导致额外的输出。


9
make VERBOSE=1 是用于 CMake 的。你之前尝试的项目很可能是基于 GNU autotools 的。 - Ruslan

18

我喜欢使用:

make --debug=j

https://linux.die.net/man/1/make

--debug[=FLAGS]

打印调试信息以及正常处理的输出。如果省略了 FLAGS,则行为与指定了 -d 时相同。FLAGS 可以为 a(表示输出所有调试信息,等同于使用 -d)、b(表示基本调试)、v(表示更详细的基本调试)、i(表示显示隐含规则)、j(表示显示命令的详细信息)和 m(表示在重新生成 makefile 时进行调试)。


2
它不一定显示它执行的命令。你可能只会得到 Reaping winning child xyzJobserver client (fds 3,4)Need a job token; we don't have children 等等。 - einpoklum
同意,@einpoklum。 - Santiago Villafuerte

14

根据你的automake版本,你也可以使用以下内容:

make AM_DEFAULT_VERBOSITY=1

参考: AM_DEFAULT_VERBOSITY

注意: 我添加了这个答案因为V=1对我没有起作用。


1
这仅适用于使用GNU autotools / automake的情况。 - einpoklum
@einpoklum 这个答案说... - AStopher

2
  • 如果您想查看默认目标运行的所有命令(包括已编译的命令):
make --always-make --dry-run
make -Bn
  • 显示下一次运行make时执行的命令:
make --dry-run
make -n

在这个例子中,您可以自由选择目标。


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