使用最新的 iOS SDK 构建时的 Xcode 链接问题

Posted

技术标签:

【中文标题】使用最新的 iOS SDK 构建时的 Xcode 链接问题【英文标题】:Xcode linking issue when building with latest iOS SDK 【发布时间】:2013-09-14 23:18:02 【问题描述】:

我一直在为我的 ios 应用程序使用 Google's LevelDB 库,我对此非常满意。最近我将整个项目迁移到了最新的 Xcode 5,虽然部署目标仍然是 iOS 6.1,但基础 SDK 现在是 iOS 7。

一切都构建得很好,直到它进入链接阶段,在该阶段它无法找到所需架构的 leveldb 符号,即使 leveldb 的静态库是使用正确指向 iOS 7 SDK 的-isysroot 选项构建的。它像这样失败:

Ld /Users/mathieudamours/Development/storm/iOS/Uptime/Build/Intermediates/Uptime.build/Release-iphoneos/Uptime.build/Objects-normal/armv7/Uptime normal armv7
    cd /Users/mathieudamours/Development/storm/iOS/Uptime/Uptime
    setenv IPHONEOS_DEPLOYMENT_TARGET 6.1
    setenv PATH "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin:/Applications/Xcode.app/Contents/Developer/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin"
    /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang -arch armv7 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS7.0.sdk -L/Users/mathieudamours/Development/storm/iOS/Uptime/Build/Products/Release-iphoneos -L/Users/mathieudamours/Development/storm/iOS/Uptime/Uptime/../Pods/Objective-LevelDB/leveldb-library -F/Users/mathieudamours/Development/storm/iOS/Uptime/Build/Products/Release-iphoneos -F/Users/mathieudamours/Development/storm/iOS/Common/HockeySDK.embeddedframework -filelist /Users/mathieudamours/Development/storm/iOS/Uptime/Build/Intermediates/Uptime.build/Release-iphoneos/Uptime.build/Objects-normal/armv7/Uptime.LinkFileList -dead_strip -ObjC -fobjc-arc -Wl,-no_compact_unwind -licucore -lleveldb -lstdc++ -framework Accelerate -framework CFNetwork -framework CoreGraphics -framework MessageUI -framework MobileCoreServices -framework QuartzCore -framework Security -framework SystemConfiguration -fobjc-arc -fobjc-link-runtime -miphoneos-version-min=6.1 -framework SystemConfiguration -framework QuartzCore -framework CoreText -framework EventKit -framework UIKit -framework HockeySDK -framework Foundation -framework CoreGraphics -lPods -Xlinker -dependency_info -Xlinker /Users/mathieudamours/Development/storm/iOS/Uptime/Build/Intermediates/Uptime.build/Release-iphoneos/Uptime.build/Objects-normal/armv7/Uptime_dependency_info.dat -o /Users/mathieudamours/Development/storm/iOS/Uptime/Build/Intermediates/Uptime.build/Release-iphoneos/Uptime.build/Objects-normal/armv7/Uptime

Undefined symbols for architecture armv7:
  "std::__1::__vector_base_common<true>::__throw_length_error() const", referenced from:
      void std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >::__push_back_slow_path<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) in libleveldb.a(env_posix.o)
  "std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::operator=(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)", referenced from:
      leveldb::(anonymous namespace)::PosixEnv::LockFile(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, leveldb::FileLock**) in libleveldb.a(env_posix.o)
  "std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::__init(char const*, unsigned long)", referenced from:
      leveldb::Status::ToString() const in libleveldb.a(status.o)
      leveldb::(anonymous namespace)::PosixEnv::GetChildren(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >*) in libleveldb.a(env_posix.o)
      leveldb::(anonymous namespace)::PosixEnv::UnlockFile(leveldb::FileLock*) in libleveldb.a(env_posix.o)
  "std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::append(char const*, unsigned long)", referenced from:
      leveldb::Status::ToString() const in libleveldb.a(status.o)
      leveldb::PutLengthPrefixedSlice(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >*, leveldb::Slice const&) in libleveldb.a(coding.o)
      leveldb::(anonymous namespace)::PosixEnv::LockFile(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, leveldb::FileLock**) in libleveldb.a(env_posix.o)
  "std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::push_back(char)", referenced from:
      leveldb::WriteBatch::Put(leveldb::Slice const&, leveldb::Slice const&) in libleveldb.a(write_batch.o)
      leveldb::WriteBatch::Delete(leveldb::Slice const&) in libleveldb.a(write_batch.o)
      leveldb::(anonymous namespace)::BloomFilterPolicy::CreateFilter(leveldb::Slice const*, int, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >*) const in libleveldb.a(bloom.o)
  "std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::assign(char const*)", referenced from:
      leveldb::(anonymous namespace)::PosixEnv::GetTestDirectory(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >*) in libleveldb.a(env_posix.o)
  "std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::~basic_string()", referenced from:
      leveldb::WriteBatch::WriteBatch() in libleveldb.a(write_batch.o)
      leveldb::WriteBatch::~WriteBatch() in libleveldb.a(write_batch.o)
      leveldb::Status::ToString() const in libleveldb.a(status.o)
      leveldb::(anonymous namespace)::PosixEnv::GetChildren(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >*) in libleveldb.a(env_posix.o)
      leveldb::(anonymous namespace)::PosixEnv::LockFile(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, leveldb::FileLock**) in libleveldb.a(env_posix.o)
      leveldb::(anonymous namespace)::PosixEnv::UnlockFile(leveldb::FileLock*) in libleveldb.a(env_posix.o)
      leveldb::(anonymous namespace)::PosixFileLock::~PosixFileLock() in libleveldb.a(env_posix.o)
      ...
  "std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::basic_string(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)", referenced from:
      leveldb::Status::ToString() const in libleveldb.a(status.o)
      leveldb::(anonymous namespace)::PosixEnv::NewSequentialFile(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, leveldb::SequentialFile**) in libleveldb.a(env_posix.o)
      leveldb::(anonymous namespace)::PosixEnv::NewRandomAccessFile(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, leveldb::RandomAccessFile**) in libleveldb.a(env_posix.o)
      leveldb::(anonymous namespace)::PosixEnv::NewWritableFile(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, leveldb::WritableFile**) in libleveldb.a(env_posix.o)
      leveldb::(anonymous namespace)::PosixEnv::GetChildren(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >*) in libleveldb.a(env_posix.o)
      std::__1::__tree<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::less<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >::__insert_unique(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) in libleveldb.a(env_posix.o)
      void std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >::__push_back_slow_path<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) in libleveldb.a(env_posix.o)
      ...
  "std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::resize(unsigned long, char)", referenced from:
      leveldb::WriteBatch::WriteBatch() in libleveldb.a(write_batch.o)
      leveldb::(anonymous namespace)::BloomFilterPolicy::CreateFilter(leveldb::Slice const*, int, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >*) const in libleveldb.a(bloom.o)
      leveldb::(anonymous namespace)::BytewiseComparatorImpl::FindShortestSeparator(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >*, leveldb::Slice const&) const in libleveldb.a(comparator.o)
      leveldb::(anonymous namespace)::BytewiseComparatorImpl::FindShortSuccessor(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >*) const in libleveldb.a(comparator.o)
  "std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::__init(char const*, unsigned long, unsigned long)", referenced from:
      leveldb::(anonymous namespace)::PosixEnv::LockFile(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, leveldb::FileLock**) in libleveldb.a(env_posix.o)
  "leveldb::DB::Open(leveldb::Options const&, std::string const&, leveldb::DB**)", referenced from:
      -[LevelDB initWithPath:name:andOptions:] in libPods.a(LevelDB.o)
ld: symbol(s) not found for architecture armv7
clang: error: linker command failed with exit code 1 (use -v to see invocation)

令人惊讶的是,如果我通过将 leveldb 的静态库指向旧的 iOS 6.1 SDK(为此我必须下载 Xcode 4.6、寻找 SDK 并将其存储在我机器上的某个位置)来重建 leveldb 的静态库,链接工作正常。

所以,我的问题是,这是预期的行为吗?如果是这样,为什么?是否有可能/我必须改变什么才能不必保留旧版本的 iOS SDK 来构建这个库?

【问题讨论】:

你能用它抱怨的符号名称显示几个链接器行吗? 【参考方案1】:

您链接到的标准 C++ 库不匹配。 Apple 的 LLVM 使用 libc++,而旧版本使用 libstdc++。您显示的符号是 libc++ 的。

如果编译器、代码样式和标准库的构建设置在库和应用程序之间保持相同,则应该没问题。

【讨论】:

就是这样,非常感谢!作为记录,在我的特殊情况下,将 leveldb 和 iOS 目标与 libc++ 匹配并没有解决它,但使用 libstdc++ 可以解决。 你是怎么解决的。能详细点吗?

以上是关于使用最新的 iOS SDK 构建时的 Xcode 链接问题的主要内容,如果未能解决你的问题,请参考以下文章

使用适用于 ARC 和多个开发人员的最新 iOS SDK 构建 Facebook

尽管 Xcode 是最新的,但无法将 iOS 应用程序部署到 App Store

如何在 Xcode 4.0.2 中使用 iOS SDK 4.2

IOS7.1 SDK可以用XCode6.3吗

Xamarin iOS构建错误-本地链接失败(仅链接框架SDK)

使用 xcode 5 (iOS 7 sdk) 构建 iOS 7 UI