如何确定库间依赖?

时间:2011-01-24 07:54:35

标签: c++ gcc ld undefined-symbol nm

我的项目由几个静态库组成,这些库在最后一步中链接在一起。现在我遇到问题,link order of the library is important(否则我得到一个未定义的符号链接器错误)。有时我遇到问题,我必须重新排序链接库(-lcommon -lsetup -lcontrol等)。目前这是一个愚蠢的试验和错误:重新排序,编译,检查错误,重新排序,编译等等。

所以我编写了一个小程序来向我展示库间依赖关系,并生成链接库的顺序。它从nm读取定义的('T','B'等)和未定义的符号('U')并删除weak symbols('w','W','v'和'未定义的符号列表'中的'V')。现在它为每个未定义的符号确定解析它的库。

但是我的程序向我展示了循环依赖...我的错误是什么?

如果它们真的存在,我根本无法链接......所以在分析nm输出时我错过了什么?或者正在分析nm输出,而不是获取这些依赖关系?

libcommon.a:
         U _ZN15HardwareUnit23GetHardwareSerialNumberEv
libhardware.a:
00000484 T _ZN15HardwareUnit23GetHardwareSerialNumberEv
libsecurityaccess.a:
         U _ZN15HardwareUnit23GetHardwareSerialNumberEv
---
libhardware.a:
         U _ZN21ApplicationProfile26GetApplicationSettingsPathERK7QString
libsecurityaccess.a:
00004020 T _ZN21ApplicationProfile26GetApplicationSettingsPathERK7QString
         U _ZN21ApplicationProfile26GetApplicationSettingsPathERK7QString

2 个答案:

答案 0 :(得分:6)

使用循环依赖关系链接库的另一个选项是使用特殊的链接器选项。男子ld:

   -( archives -)
   --start-group archives --end-group
       The archives should be a list of archive files.  They may be either
       explicit file names, or -l options.

       The specified archives are searched repeatedly until no new
       undefined references are created.  Normally, an archive is searched
       only once in the order that it is specified on the command line.
       If a symbol in that archive is needed to resolve an undefined
       symbol referred to by an object in an archive that appears later on
       the command line, the linker would not be able to resolve that
       reference.  By grouping the archives, they all be searched
       repeatedly until all possible references are resolved.

       Using this option has a significant performance cost.  It is best
       to use it only when there are unavoidable circular references
       between two or more archives.

尽管消除循环依赖关系总是更清晰。

答案 1 :(得分:2)

如果你真的有一个静态库的循环依赖链(从你的粘贴中看不清楚;你只显示非循环依赖),有两个选项:

  1. 以某种方式删除循环依赖;例如,您可以确保libcommon不引用libpthardware中的符号。
  2. 从.a库中提取单个.o文件,并直接链接它们。然后链接顺序不再重要。
  3. 对于2.,您可能会发现使用部分链接而不是创建静态库很有帮助。在使用GNU bintools的系统上,可以通过调用类似的东西来完成:

    ld -r -o libfoo.o foo.o bar.o
    

    这样做的效果是将foo.o和bar.o组合成一个.o文件。订单无关紧要。然后,您可以在最后的链接步骤中将libfoo.o简单地引用为普通目标文件。

    请注意,执行此操作可能interfere with the linker's ability to discard unreferenced portions of the static library(通常这是在.a中的.o文件级别完成的,我相信)。如果您正在使用所有或大多数这些库,这可能不是问题。但是,如果代码内存存在问题,您可能需要查看automatically discarding unused code at the function level。如果您这样做,请仅在最终链接阶段传递--gc-sections-s(如果您需要调试,请避免这样做!)。此外,现代gcc似乎不需要使用系统库进行静态链接。