我有一个我继承的C ++应用程序,它包含:
换句话说,我的代码如下所示:
// 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”库。
注意:运行“nmake”并将DEPS设置为yes以重建所有不是一个选项。但我可以访问外部库的完整源代码。
2)一个稍微独立且不那么重要的问题,如何判断我正在构建的整个源代码树中使用的所有包含文件的列表。再次,理想情况下frm已经构建的可执行文件,我有一个调试版本。
=================
更新:为了澄清,我们的库是静态链接的,因此ldd
(列出动态依赖关系)不起作用。
此外,答案可以是Solaris或Linux - 无所谓。
我尝试使用nm
,但没有列出库
答案 0 :(得分:29)
我有类似的问题并找到了解决方案:链接时添加-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。
答案 1 :(得分:9)
对于直接依赖;
ldd <app>
间接/所有依赖;
ldd -r <app>
答案 2 :(得分:4)
据我所知,链接时保留的静态库信息不多(因为链接器只是将该库视为* .o对象的集合)。
如果找到链接最终可执行文件的make命令并添加-v
标志,g++
将准确显示它如何调用ld
命令。这应包括所有必需的静态库,包括其他库使用的库,否则链接步骤将失败。但它可能还包括未实际使用的额外库。
另一个可能有用的事情是,至少在Linux上,对象和可执行文件通常存储创建它们的源代码文件的名称。 (仅限文件名,无路径。)尝试
objdump -t executable | grep '*ABS*'
答案 3 :(得分:1)
尝试使用ldd
+您的文件名,这将列出库。
答案 4 :(得分:0)
我先回答你的第二个问题。您只需使用-H
或-M
标志即可查看编译中处理的所有(包括系统)标头。 gcc -H main.c
应该做到这一点。看看哪个标题
包括在内,实际上可以帮助您找到链接的静态库。
您可以在最终对象(或最终二进制文件的objdump
)上使用readelf
来获取其中所有函数的名称。然后你必须找到函数被引入的库,但这有点麻烦。你必须制作一个脚本来减少痛苦。
其他人提到使用gcc <stuff> -Wl,-verbose
只是将-verbose
标志传递给链接器。这是获取共享库列表(.so文件)的完美方式,但是你说你的是静态的,所以在这种情况下不是这样的。
答案 5 :(得分:0)
这是我用来生成链接时依赖项的内容:
-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 \