在构建我的 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 <stuff> -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++ 模板,未定义的引用
由于 std::pair 导致的 GCC (MoSync) 中的 C++ 构建错误