【问题标题】:Symbols not found for architecture i386 - But works for iOS device未找到架构 i386 的符号 - 但适用于 iOS 设备
【发布时间】:2013-05-19 17:34:23
【问题描述】:

我在这里遇到了一个奇怪的问题,我正在尝试将 libkml C++ project sources 集成到我的 iOS 项目中。该项目可以独立编译,但是通过这行代码进行链接时:

kmldom::PointPtr appPoint = kmlconvenience::CreatePointLatLon(appLocation.coordinate.latitude, appLocation.coordinate.longitude);

我得到链接器错误只有当我为模拟器构建它时。当我为 iOS 设备构建它时它工作正常,但对于模拟器我得到以下 3 个链接器错误:

(null): "kmldom::GxTimeSpan::GxTimeSpan()", referenced from:

(null): Kmldom::KmlFactory::CreateGxTimeSpan() const in libLibKML.a(kml_factory.o)

(null): "kmldom::GxTimeStamp::GxTimeStamp()", referenced from:

(null): Kmldom::KmlFactory::CreateGxTimeStamp() const in libLibKML.a(kml_factory.o)

(null): Symbol(s) not found for architecture i386

(null): Linker command failed with exit code 1 (use -v to see invocation)

我可以单独为设备开发,但我希望解决这个问题有两个原因:

  1. 团队有时很容易将模拟器用于开发目的。
  2. 我真的很想深入了解它并了解为什么会在第一种情况下发生这种情况。为什么它为设备构建而在模拟器中失败虽然目标相同并且目标中包含的源文件在模拟器和设备中都是相同的?。

GXTimeStamp 和 GXTimeSpan 类的定义在头文件 gx_timeprimitive.h 中,内容如下:

#ifndef KML_DOM_GX_TIMEPRIMITIVE_H__
#define KML_DOM_GX_TIMEPRIMITIVE_H__

#include <string>
#include "kml/base/xml_namespaces.h"
#include "kml/dom/kml22.h"
#include "kml/dom/object.h"
#include "kml/dom/timeprimitive.h"

namespace kmldom {

class Serializer;
class Visitor;

// <gx:TimeSpan>
class GxTimeSpan : public TimeSpan {
 public:
  virtual ~GxTimeSpan();
  static KmlDomType ElementType() {
    return Type_GxTimeSpan;
  }
  virtual KmlDomType Type() const { return Type_GxTimeSpan; }
  virtual bool IsA(KmlDomType type) const {
    return type == Type_GxTimeSpan || TimeSpan::IsA(type);
  }

  // Visitor API methods, see visitor.h.
  virtual void Accept(Visitor* visitor);

 private:
  friend class KmlFactory;
  GxTimeSpan();
  LIBKML_DISALLOW_EVIL_CONSTRUCTORS(GxTimeSpan);
};

// <gx:TimeStamp>
class GxTimeStamp : public TimeStamp {
 public:
  virtual ~GxTimeStamp();
  static KmlDomType ElementType() {
    return Type_GxTimeStamp;
  }
  virtual KmlDomType Type() const { return Type_GxTimeStamp; }
  virtual bool IsA(KmlDomType type) const {
    return type == Type_GxTimeStamp || TimeStamp::IsA(type);
  }

  // Visitor API methods, see visitor.h.
  virtual void Accept(Visitor* visitor);

 private:
  friend class KmlFactory;
  GxTimeStamp();
  LIBKML_DISALLOW_EVIL_CONSTRUCTORS(GxTimeStamp);
};

}  // end namespace kmldom

#endif  // KML_DOM_GX_TIMEPRIMITIVE_H__

我读过很多帖子,因为源文件没有编译,所以会发生链接器错误。我也在考虑同样的问题来解决这个问题,但是我不能将此头文件包含到编译源中,因为它是一个 .h 文件。

另外,我仔细检查了 - kml_factory.cc 文件包含在内部项目的编译源中:

期待您的建议和帮助。谢谢。

【问题讨论】:

  • 你使用的是什么版本的 XCode?​​span>

标签: c++ ios cocoa-touch ios6 cross-compiling


【解决方案1】:

这样说让我觉得很愚蠢,但是,我不知道 gx_timeprimitive.cc 文件是如何丢失的。我的印象是 gx_timeprimitive.h 文件本身是完整的,因为它具有虚拟类,我尝试通过在 Private 范围内提供构造函数的空实现来定义 GXTimeSpan 和 GXTimeStamp 类,如下所示:

class GxTimeSpan : public TimeSpan {
 public:
  virtual ~GxTimeSpan();
  static KmlDomType ElementType() {
    return Type_GxTimeSpan;
  }
  virtual KmlDomType Type() const { return Type_GxTimeSpan; }
  virtual bool IsA(KmlDomType type) const {
    return type == Type_GxTimeSpan || TimeSpan::IsA(type);
  }

  // Visitor API methods, see visitor.h.
  virtual void Accept(Visitor* visitor);

 private:
  friend class KmlFactory;
  GxTimeSpan()
  {

  }
  LIBKML_DISALLOW_EVIL_CONSTRUCTORS(GxTimeSpan);
};

但是,编译器仍然不会从接口文件中创建目标文件(.h 文件被排除在编译源之外,它们只包含所有声明),因此链接器无法找到所需的构造函数。这让我在互联网上搜索 gx_timeprimitive.cc 文件,它确实可用。

冷静地思考本来可以为我节省 100 点赏金,但我有一个教训要学习!

另外,要回答为什么仅在模拟器模式下会出错: 实际上我上面提到的那条线 - kmldom::PointPtr appPoint = kmlconvenience::CreatePointLatLon(appLocation.coordinate.latitude, appLocation.coordinate.longitude); 我认为,当为 ARMv7 构建时,除非变量 appPoint 在代码中的其他位置使用,否则链接器会跳过将其与 libkml 目标文件的源链接。然而,无论变量是否在代码中使用,i386 都会执行链接。我想这是某种编译器优化,因此在各自的体系结构中行为不同。正是这个谜题让我错过了寻找丢失文件的关键线索!

向那些花时间解决我这个愚蠢问题的人道歉,谢谢大家。

【讨论】:

    【解决方案2】:

    这可能类似于iOS symbols not found for architecture i386

    以下是最相关的几点:

    在为 iOS 构建库、框架或应用程序时,XCode 只会为目标的构建设置中指定的体系结构编译目标代码。 XCode 也将仅链接到具有内置指定架构的二进制文件。

    在 iOS 模拟器中运行代码时,您是在 i386 架构的桌面上运行代码。

    如果您在模拟器中运行 iOS 应用程序时遇到缺少 i386 架构的错误,您需要确保您的应用程序及其所有依赖库都是针对 i386 架构构建的。

    【讨论】:

    • 我的代码中包含了 libkml 源代码,这意味着将为构建主项目之前选择的架构构建 libkml 库。此外,libkml 仅依赖于一个外部库——我在外部编译的 Expat 库,并创建了一个可以跨 i386 和 ARMv7 链接的胖库。此外,正如我的问题所示,Expat 库在这里没有给出问题,问题出在 libkml 源代码的某个地方。仍在尝试找出问题所在,感谢您的建议。
    【解决方案3】:
    猜你喜欢
    • 2012-10-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-13
    相关资源
    最近更新 更多