【问题标题】:XCode 4.2 static libraries linking issueXCode 4.2 静态库链接问题
【发布时间】:2012-01-28 05:49:30
【问题描述】:

我有 Core 静态库,几个 Component 静态库中继在 Core 上,然后还有一个 链接到 CoreComponent 库的应用。我的 App 可以链接到 CoreComponent 只要 Component 不使用来自 的类CoreApp 使用 Core 中的类)。

我在 armv6 和 armv7 版本中都收到以下错误。所以我的问题不是每个人都有的非常流行的链接问题。

ld: symbol(s) not found for architecture armv6
clang: error: linker command failed with exit code 1 (use -v to see invocation)

我在 Component 中添加了对 Core 的引用,甚至将它添加到静态库不需要的“Link Binary With Libraries”中。

自从我开始遇到这个问题后,我开始怀疑我的设计......它在动态链接环境中可能更有意义,但在静态环境中它仍然应该是可行的,特别是因为这已经在 Windows 下使用 MSVC 编译器工作。

编辑: 我取得了一些进展!虽然我仍然不知道该去哪里。

这是我的设置:

  • Core 有一个类 cResourceManager,它有一个模板化方法 GetResource(int id)

  • Core 也有类 cResource

  • Component 具有继承 cResource 的类 cMesh

这里有一些测试:

  • 如果我尝试从 App 调用 rm->GetResource(...) 我会收到链接错误

  • 如果我尝试从 App 构建 cMesh,则会出现链接错误

  • 如果我尝试从 App 调用将返回新 cMesh 实例的静态方法,则会收到链接错误

  • 如果我注释掉 cMesh 的构造,但保留其他成员 cMesh 函数调用 App 链接正常。我什至可以调用 删除网格

我从来没有见过这样的东西!

【问题讨论】:

  • 希望这会有所帮助...(目前为 100%)
  • 设计不错,我们对两个 iOS 应用使用了类似的方法;所以几乎可以肯定“只是”某种配置问题。
  • @rvalue 是的,我也针对 iOS。目前我唯一的想法是我可能正在使用模板工厂或其他东西进行一些循环依赖。我用模块引入了新的资源类型,但核心有模板资源工厂。

标签: c++ xcode linker llvm


【解决方案1】:

如果您删除 cMesh 构造函数,那么您将使用提供给您的默认(无参数,无主体)cMesh 构造函数。由于cMesh 构造函数中的某些代码,这几乎听起来像是构建错误或缺少代码,因此实际上并没有生成库,也许 Xcode 没有报告错误。 Xcode 不擅长报告链接器错误。

我建议查看链接器所说的缺少哪些符号,并仔细检查它们是否确实在您的代码中定义。我的猜测是您在 cMesh 构造函数中使用了这些符号之一。很多时候,使用虚拟基类,您可能会忘记在子类中定义实现一两个方法。可能是由于缺少基于您的模板的方法,或者您的模板不是正确的#included。这可以很好地编译,但会导致您看到的链接器错误。

如果 Xcode 没有向您显示完整的链接器错误,请显示 Log Navigator (Command ⌘+7),双击最后一个“Build”条目,选择错误,然后按选中时出现的行最右侧的按钮。符号应在此处列出。如果没有,是时候在终端中输入xcodebuild了。

如果不是不是这种情况,我很想看看是否正在为适当的架构构建库的结果,或者这可能会促进一些进展:

  1. 在 Xcode Organizer Shift ⇧+Command ⌘+2 中,单击 Projects 并为您的项目找到 DerivedData 的路径。
  2. 在终端中,导航到该目录 (cd ~/Library/Developer/Xcode/DerivedData/proj-<random value>/)
  3. 删除(或移到一边)构建目录 (rm -r Build)
  4. 在 Xcode 中,尝试使用 cMesh 构造函数进行构建。
  5. 查找库产品文件 (cd Build/Products/<scheme>-iphoneos)

您编译的静态库 (<libname>.a) 应该在此目录中。如果他们不在那里,他们就没有建造(除非你把你的产品放在别处)。如果您的库在那里,让我们确认它们实际上是为适当的架构构建的。运行otool -vh <library>.a。您应该会看到如下内容:

$ otool -vh libtesting.a 
Archive : libtesting.a
libtesting.a(testing.o):
Mach header
      magic cputype cpusubtype  caps    filetype ncmds sizeofcmds      flags
   MH_MAGIC     ARM         V7  0x00      OBJECT     3       1928 SUBSECTIONS_VIA_SYMBOLS

如您所见,我的测试库是为 ARMv7 构建的。

【讨论】:

  • 这个问题真的很奇怪...... XCode 没有报告这个符号,或者至少它看起来像是整个班级都不见了。我开始删除碎片,直到我设法缩小有问题的符号。它是 cResource 的析构函数。它没有什么特别之处,我设法将其设为空的公共虚拟析构函数。如果我将析构函数内联,我可以链接,如果它在 .cpp 中定义,那么它不会链接。我的构造函数也在同一个 .cpp 文件中,其他函数也很少,它们似乎不是问题。
  • 我的代码库是经过 3 年多的工作大量构建的。 cResource 在其中无处不在。而且由于我目前有不使用组件的活动项目,而且它们工作得很好,我的组件应用程序在 MSVS 下编译和链接......我认为这可能是一些编译器/链接器问题。我会再试一次,以找出有关此的更多信息。
  • 缺失的符号将出现在“ld: symbol(s) not found for architecture”之前。如果您在 .h 中的实现工作但在 .cpp 中找不到符号时遇到问题,您是否确定 .cpp 正在构建到库中?听起来它只是在构建,因为它被包含在另一个翻译单元中。这可能是您的库中的循环依赖的问题(听起来您有几个使用其他静态库的静态库)。
  • 您还可以使用nm 检查库中未定义的符号。当符号未定义时,第二列是“U”,所以nm <lib>.a | grep -E "^(\ *)U"。从您的项目中查找符号。
【解决方案2】:

确保您以正确的顺序链接它们。

如果 Component 依赖于 Core 中的符号,则 Component 需要在链接顺序中排在第一位,因此链接器知道要在 Core 中查找哪些符号。

在 MSVC 中顺序无关紧要,但在大多数其他编译器套件中它确实如此。

【讨论】:

  • 我的顺序错了,但结果还是一样。
【解决方案3】:

我认为 Clang 不会为 armv6 生成代码,如果您的目标是旧设备,您仍然需要使用 GCC。

【讨论】:

  • 我不认为我的问题是代码生成。我对 armv7 也有完全相同的错误。另外,即使我使用 LLVM GCC 4.2,我也会收到错误
  • 公平地说,我们在首次迁移到 Clang 时遇到了类似的问题。您可以直接(也)将 Component 目标与 Core 链接起来吗?
猜你喜欢
  • 1970-01-01
  • 2011-07-15
  • 1970-01-01
  • 1970-01-01
  • 2018-01-23
  • 2018-06-26
  • 1970-01-01
  • 1970-01-01
  • 2019-04-19
相关资源
最近更新 更多