Question

I've been using Google's LevelDB library for my iOS app and I've been quite happy with it. Lately I migrated my whole project to the latest Xcode 5 and, while the deployment target is still iOS 6.1, the base SDK is now iOS 7.

Everything builds fine, until it gets to the linking phase, where it fails to find leveldb's symbols for the required architecture, even though the leveldb's static library was built with the -isysroot option properly pointing to the iOS 7 SDK. It fails like this:

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)

Surprisingly, linking works fine if I rebuild leveldb's static library by pointing it to an old iOS 6.1 SDK (for which I have to download Xcode 4.6, hunt for the SDK and store it somewhere on my machine).

So, my question is, is that expected behavior? If so, why? Is it possible / what would I have to change in order to not have to keep an older version of the iOS SDK just to build this library?

Was it helpful?

Solution

You have a mismatch in which standard C++ library you're linking to. Apple's LLVM uses libc++ while older builds use libstdc++. The symbols you show are libc++ ones.

If the build settings for compiler, code style, and standard library are made the same between the library and the app, you should be OK.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top