在构建我的 C++ 可执行文件 (gcc) 时,我可以获得所有链接库的报告吗? (包括静态链接)

Posted

技术标签:

【中文标题】在构建我的 C++ 可执行文件 (gcc) 时,我可以获得所有链接库的报告吗? (包括静态链接)【英文标题】:Can I get a report of ALL the libraries linked when building my C++ executable (gcc)? (including statically linked) 【发布时间】:2011-06-22 22:32:49 【问题描述】:

我有一个我继承的 C++ 应用程序,其中包括:

我的主应用 几个特定于应用程序的库(libapp1、libapp2 等...) 几个“第三方”库(大多数“第三方只是公司中的其他团队”)从主应用程序、应用程序特定的 libappX 库和其他第 3 部分库链接 - 例如。 libext1、libext2 等...

换句话说,我的代码如下所示:

// main.C
#include <app1/a1l1.H>
#include <app2/a2l1.H>
#include <ext1/e1l1.H>

// app1/a1l1.H
#include <app1/a1l2.H>
#include <ext2/e2l1.H>

// app2/a2l1.H
#include <ext2/e2l2.H>

// ext1/e1l1.H
#include <ext3/e3l1.H>

// ext3/e3l1.H
#include <ext4/e4l1.H>

问题:

1) 我如何知道哪些库已链接到最终的可执行文件中? 这必须包括静态链接的

也就是说,我想要“app1, app2, ext1, ext2, ext3, ext4”的答案

理想情况下,答案可以从可执行文件本身获得(我有一个内置的调试版本,以防它变得更有可能)。如果这是不可能的,我想知道是否有一个简单的代码分析工具(例如 gcc 本身的东西)来提供分析。

请注意,外部库的目标文件已经构建,因此查看构建日志以查看链接的内容,我担心“ext4”不会出现在日志中,因为我们不会构建已经预先构建的“ext3”库。

注意:在 DEPS 设置为 yes 的情况下运行“nmake”来重建所有这些不是一个选项。但我确实可以访问外部库的完整源代码。

2) 一个稍微独立且不太重要的问题,我如何才能列出我正在构建的整个源代码树中使用的所有 包含文件 的列表。同样,理想情况下是 frm 已经构建的可执行文件,我有一个调试版本。

==================

更新:澄清一下,我们的库是静态链接的,所以 ldd(列出同步依赖项)不起作用。

另外,答案可以是 Solaris 或 Linux - 没关系。

我尝试使用nm,但没有列出库

【问题讨论】:

@Tom - Solaris 或 Linux。我不在乎答案对两者都是通用的还是只适用于一个。 我会建议 ldd 然后你的第一个问题 【参考方案1】:

我遇到了类似的问题并找到了解决方案:链接时添加 -Wl,--verbose 选项。它会将链接器切换到详细模式:

gcc -o test main.o -ltest -L. -Wl,--verbose

这是示例输出:

GNU ld (GNU Binutils) 2.23.52.20130604
  Supported emulations:
   i386pep
   i386pe
using internal linker script:
==================================================
/* Default linker script, for normal executables */
[many lines here]
==================================================
attempt to open /usr/lib/gcc/x86_64-pc-cygwin/4.8.2/../../../../lib/crt0.o succeeded
/usr/lib/gcc/x86_64-pc-cygwin/4.8.2/../../../../lib/crt0.o
attempt to open /usr/lib/gcc/x86_64-pc-cygwin/4.8.2/crtbegin.o succeeded
/usr/lib/gcc/x86_64-pc-cygwin/4.8.2/crtbegin.o
attempt to open main.o succeeded
main.o
attempt to open ./libtest.dll.a failed
attempt to open ./test.dll.a failed
attempt to open ./libtest.a succeeded
(./libtest.a)test.o
[more lines here]
attempt to open /usr/lib/gcc/x86_64-pc-cygwin/4.8.2/crtend.o succeeded
/usr/lib/gcc/x86_64-pc-cygwin/4.8.2/crtend.o

更新:您还可以使用 -Wl,--trace 选项代替 -Wl,--verbose。它还会为您提供库列表,但不那么冗长。

更新 2: -Wl,--trace 不显示间接包含的库。示例:您与 libA 链接,而 libA 与 libB 链接。如果你想看到也需要 libB,你必须使用 -Wl,--verbose。

【讨论】:

作为关注者的说明,“.o”文件ld 列出了一个库(即那些在它说attempt to open libXX succeeded 之后列出的)不会是一个“所有”的.o 文件库,只有在那时满足依赖关系所需的库。其余的基本上都被丢弃了,即使存在于 .a 文件中。参考:***.com/q/14091669/32453 在 Visual Studio 2017 中有简单的方法吗? @YuriyF:我试着用谷歌搜索,发现 MSVC 有 /VERBOSE 选项:docs.microsoft.com/en-us/cpp/build/reference/…。请检查它是否适合你,我没有 MSVC 来测试它。 Visual Studio 是一个破碎的哔哔声。【参考方案2】:

对于直接依赖;

ldd <app>

间接/所有依赖;

ldd -r <app>

【讨论】:

很抱歉之前没有澄清这一点,这些库是静态链接的。 ldd 没有列出这些。 我通过您的回答找到了我想要的答案,谢谢!【参考方案3】:

据我所知,在链接时没有保留太多关于静态库的信息(因为链接器只是将该库视为 *.o 对象的集合)。

如果您找到链接最终可执行文件的 make 命令并添加 -v 标志,g++ 将准确显示它如何调用 ld 命令。这应该包括所有必要的静态库,包括其他库使用的库,否则链接步骤将失败。但它也可能包含实际未使用的额外库。

另一个可能有用的事情是,至少在 Linux 上,对象和可执行文件通常存储创建它们的源代码文件的名称。 (只有文件名,没有路径。)试试

objdump -t executable | grep '*ABS*'

【讨论】:

objdump 似乎产生的输出与nm 非常相似,并且实际上并没有产生库列表。我可以通过命令行开关将“-v”传递给nmake吗?谢谢 @DVK:AT&T nmake?微软nmake?无论如何,可能不会。您想找到 make 进程执行或将要调用的最后一个 g++ 命令,然后将 -v 添加到该命令。 明白了。我认为默认情况下它已经这样做了,因为我认为我在 g++ 命令行中看到了所有 .a 文件的列表【参考方案4】:

尝试使用ldd + 你的文件名,这将列出库。

【讨论】:

很抱歉之前没有澄清这一点,这些库是静态链接的。 ldd 没有列出这些。【参考方案5】:

我先回答你的第二个问题。您可以简单地使用-H-M 标志来查看编译中处理的所有(包括系统)头文件。 gcc -H main.c 应该可以解决问题。查看哪些标题 包括在内实际上会让您找到正确的路径来查找链接的静态库。

您可以在最终对象上使用objdump(或在最终二进制文件上使用readelf)来获取其中所有函数的名称。然后,您必须去查找从中提取函数的库,但这有点麻烦。你肯定必须编写一个脚本来尽量减少痛苦。

有人提到使用gcc &lt;stuff&gt; -Wl,-verbose,它只是将-verbose 标志传递给链接器。这是获取共享库(.so 文件)列表的完美方法,但您说您的库是静态的,因此在这种情况下不是这样。

祝你好运!

【讨论】:

【参考方案6】:

这是我用来生成链接时依赖项的内容:

-include .deps/TARGET.d

$(TARGET): $(OBJECTS)
    @echo " LINK $(TARGET)"
    @echo '$$(TARGET): \' > .deps/TARGET.d
    @$(CXX) -o $(TARGET) $(OBJECTS) $(LDLIBS) -Wl,--trace | sed -r -e "s#.*\(($(MY_LIB_DIR)).*)\).*#\t\\1 \\\\#p;d" | sort | uniq >> .deps/TARGET.d

它会生成一个如下所示的.deps/TARGET.d 文件:

$(TARGET): \
    /home/user/project/lib/lib1.a \
    /home/user/project/lib/lib2.a \
    /home/user/project2/bin/lib3.so \

【讨论】:

以上是关于在构建我的 C++ 可执行文件 (gcc) 时,我可以获得所有链接库的报告吗? (包括静态链接)的主要内容,如果未能解决你的问题,请参考以下文章

从 gcc 3.3.3 到 4.1.0 的移植,C++ 模板,未定义的引用

C++ linux在部署环境中安装可执行文件

由于 std::pair 导致的 GCC (MoSync) 中的 C++ 构建错误

autotools:C 编译器无法创建可执行文件

在 Visual Studio (TDD) 中构建和运行 C++ 单元测试

使用 GCC 创建静态链接的可执行文件