使用最新的 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