.o文件中的导出符号未在.dylib中导出

时间:2014-07-28 18:58:00

标签: c++ osx-mavericks xcode5.1 crtp

我最近遇到了在Mavericks(OS X 10.9.4,Xcode 5.1)上从已编译的C ++代码(.o文件)构建共享库(.dylib文件)时出现的错误。来自一个特定实现类的键符号似乎是在.o文件中导出的,而不是从包含.o的.dylib文件中导出的。

我们的代码库分解为模块。我们大量使用奇怪的重复模板模式(CRTP)。代码草图如下所示:

#include <string>
class ExprVec;

class Operator
{
 public:
  virtual bool operator()(bool &result, ExprVec const &args) const = 0;
  virtual bool operator()(int32_t &result, ExprVec const &args) const = 0;
  virtual bool operator()(double &result, ExprVec const &args) const = 0;
  virtual bool operator()(std::string &result, ExprVec const &args) const = 0;
};

template <class IMPL>
class OperatorShim : public Operator
{
 public:
  bool operator()(bool &result, ExprVec const &args) const
  {
    return static_cast<IMPL const *>(this)->calc(result, args);
  }
  bool operator()(int32_t &result, ExprVec const &args) const
  {
    return static_cast<IMPL const *>(this)->calc(result, args);
  }
  bool operator()(double &result, ExprVec const &args) const
  {
    return static_cast<IMPL const *>(this)->calc(result, args);
  }
  bool operator()(std::string &result, ExprVec const &args) const
  {
    return static_cast<IMPL const *>(this)->calc(result, args);
  }
};

template <typename T>
class OperatorImpl : public OperatorShim<OperatorImpl<T> >
{
 public:
  // implemented by derived classes
  virtual bool calc(T &result, ExprVec const &args) const = 0;

  // default methods
  template <typename U>
  bool calc <U &result, ExprVec const &args) const
  {
    // throw wrong-type exception
    return false;
  }
};

template class OperatorImpl<bool>;
template class OperatorImpl<int32_t>;
template class OperatorImpl<double>;
template class OperatorImpl<std::string>;

在我们的实际代码库中,声明位于.hh文件中,而.cc文件中的定义位于.hh文件中。来自.cc的.o文件导出所有模板化的calc()默认方法 - 但.dylib不会。这些符号位于.dylib中,但仅作为调试符号。我已经通过使用nm和c ++ filt来检查文件来验证这一点。

这导致链接使用此库的任何应用程序时出错,因为OperatorShim方法调用未导出的OperatorImpl方法。

仅在使用Xcode 5.1.x命令行工具在Mac OS X 10.9.x上构建时才会发生这种情况。 10.8.x和Xcode 5.0.x链接这个库没有问题,Linux上的GNU工具也没有问题。

作为一种解决方法,我已将方法实现移回到.hh文件中。因为它们需要其他几个包含文件,所以我更愿意将这些实现与声明分开。

您可以按如下方式重现OS X 10.9.x上的实际问题:

export PLEXIL_HOME=$PWD
svn checkout -r3785 svn+ssh://svn.code.sf.net/p/plexil/code/branches/plexil-3-new-exp/src
cd src
./configure --disable-static --enable-module-tests --prefix=$PLEXIL_HOME
make

有问题的文件是...... / src / expr / OperatorImpl。{hh,cc,o}和... / src / expr / .libs / libPlexilExpr.0.dylib。构建dylib文件的命令是:

libtool: link: g++ -dynamiclib -Wl,-undefined -Wl,dynamic_lookup -o .libs/libPlexilExpr.0.dylib  .libs/libPlexilExpr_la-Alias.o .libs/libPlexilExpr_la-Array.o .libs/libPlexilExpr_la-ArrayImpl.o .libs/libPlexilExpr_la-ArithmeticFunctionFactory.o .libs/libPlexilExpr_la-ArithmeticOperators.o .libs/libPlexilExpr_la-ArrayOperators.o .libs/libPlexilExpr_la-ArrayReference.o .libs/libPlexilExpr_la-ArrayVariable.o .libs/libPlexilExpr_la-Assignable.o .libs/libPlexilExpr_la-AssignableImpl.o .libs/libPlexilExpr_la-BooleanOperators.o .libs/libPlexilExpr_la-CommandHandle.o .libs/libPlexilExpr_la-Comparisons.o .libs/libPlexilExpr_la-ConcreteExpressionFactory.o .libs/libPlexilExpr_la-Constant.o .libs/libPlexilExpr_la-Expression.o .libs/libPlexilExpr_la-ExpressionConstants.o .libs/libPlexilExpr_la-ExpressionFactories.o .libs/libPlexilExpr_la-ExpressionFactory.o .libs/libPlexilExpr_la-ExpressionImpl.o .libs/libPlexilExpr_la-ExpressionListener.o .libs/libPlexilExpr_la-ExprVec.o .libs/libPlexilExpr_la-Function.o .libs/libPlexilExpr_la-FunctionFactory.o .libs/libPlexilExpr_la-NodeConstants.o .libs/libPlexilExpr_la-NodeConstantExpressions.o .libs/libPlexilExpr_la-NotifierImpl.o .libs/libPlexilExpr_la-OperatorImpl.o .libs/libPlexilExpr_la-PlexilExpr.o .libs/libPlexilExpr_la-StringOperators.o .libs/libPlexilExpr_la-UserVariable.o .libs/libPlexilExpr_la-Value.o .libs/libPlexilExpr_la-ValueType.o   -lm -lpthread -ldl  -O2   -install_name  /Users/chucko/src/plexil-3-new-exp/lib/libPlexilExpr.0.dylib -compatibility_version 1 -current_version 1.0 -Wl,-single_module

这是我的编码错误的结果吗?我尝试了许多不同的方法,但无法解决问题。

0 个答案:

没有答案