架构i386找不到符号 - 但适用于iOS设备

Raj*_*dal 5 c++ cocoa-touch cross-compiling ios ios6

我在这里面临一个奇怪的问题,我正在尝试将libkml C++项目源集成到我的iOS项目中.项目独立编译很好,但是当涉及通过这行代码链接时:

kmldom::PointPtr appPoint = kmlconvenience::CreatePointLatLon(appLocation.coordinate.latitude, appLocation.coordinate.longitude);
Run Code Online (Sandbox Code Playgroud)

我得到链接器错误只有当我为模拟器构建它时.当我为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)
Run Code Online (Sandbox Code Playgroud)

只有当我尝试构建模拟器时才会出现这些错误

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

  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__
Run Code Online (Sandbox Code Playgroud)

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

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

kml_factory.cc文件包含在编译阶段

期待提出建议和帮助.谢谢.

Raj*_*dal 3

这么说让我觉得很愚蠢,但是,我不知道 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);
};
Run Code Online (Sandbox Code Playgroud)

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

冷静思考可以为我节省 100 个赏金点,但我有一个教训!

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

对于那些花时间解决我这个愚蠢问题的人表示歉意,谢谢大家。