Проблема со связыванием XCode при сборке с последним iOS SDK

Я использовал библиотеку Google LevelDB для своего приложения для iOS, и я был вполне ей доволен. В последнее время я перенес весь свой проект на последнюю версию Xcode 5, и, хотя целью развертывания по-прежнему является iOS 6.1, базовый SDK теперь является iOS 7.

Все строится нормально, пока не дойдет до фазы связывания, где не удается найти символы leveldb для требуемой архитектуры, даже если статическая библиотека leveldb была создана с -isysroot опция правильно указывающая на iOS 7 SDK. Это терпит неудачу как это:

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 и сохранить его где-нибудь на моей машине).

Итак, мой вопрос, это ожидаемое поведение? Если так, то почему? Возможно ли / что я должен изменить, чтобы не сохранять старую версию iOS SDK только для сборки этой библиотеки?

1 ответ

Решение

У вас несоответствие, в какой стандартной библиотеке C++ вы ссылаетесь. LLVM от Apple использует libC++, в то время как старые сборки используют libstdC++. Символы, которые вы показываете, являются символами libC++.

Если параметры сборки для компилятора, стиля кода и стандартной библиотеки сделаны одинаковыми между библиотекой и приложением, у вас должно быть все в порядке.

Другие вопросы по тегам