Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I build in XCode 4, for an iOS 3.1 deployment target, using libSystem.B?

Tags:

ios

xcode4

linker

I've recently upgraded from XCode 3 to 4, and now I'm having build problems with my iPhone project. I need to support older versions of iOS back to 3.1. With XCode 3.2.5, I had no problem building with SDK 4.2, using an iOS deployment target of 3.1. I also included a weak link to the libSystem.B library, which is required for running the app on older iOS versions. Now when I build with XCode 4, I get the linker error below. The compilation step completes, but the link step fails. If I remove the weak link to the libSystem.B library, then the build completes, but the app crashes at startup when running on iOS 3.1.

Has anyone found a solution to this problem? How do you build with XCode 4, to run on an old version of iOS?

ld: library not found for -lSystem.B collect2: ld returned 1 exit status Command /Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin/llvm-gcc-4.2 failed with exit code 1

like image 621
gstroup Avatar asked Mar 17 '11 22:03

gstroup


3 Answers

In your project build settings under "Other Linker Flags" add the following:

-weak_library /usr/lib/libSystem.B.dylib

It should automatically be added to your Target build settings but if it isn't you should add it there as well.

like image 116
TrevorL Avatar answered Nov 15 '22 10:11

TrevorL


OK, the weak_library option is the right track...here are the issues:

The .B indicates a second version of the system library. I'm guessing some of the newer Obj-C features require this (like Blocks), and using libraries that give API support for blocks and such will indirectly reference the .B system library. This means the dynamic linker will try to pull in libSystem.B, but indirectly (if your code isn't using these features).

There are two competing problems: getting the app to work on older devices, and getting it to build for the simulator.

To get it to run on older phones, you'll have to specify a weak linkage for libSystem.B. Weak link basically makes it so older libraries that are missing bits don't cause problems. With normal linkage, the dynamic linker is required to find all of the symbols that could ever get used. With weak linkage, the linker allows for missing items. This is part of Apple's support for older phones...if it is missing a symbol in the library, don't worry about it.

Unfortunately, the 5.1 simulator SDK does NOT include a libSystem.B.dylib file, which is why several of the solutions above sort-of work...if you put a file in it can find, it at least won't die on build.

Make sure you understand what you are doing when you make this file, though. You are telling the linker to link in that library when running on the simulator...thus, it must have the correct arch, and must properly cross-link with other libraries in the frameworks.

Using /usr/lib/libSystem.B is a bad idea, as that is an OSX library, not an iOS one. Similarly, linking to a DEVICE library is going to get you a library with arm arch, which will not work in a sim running on intel hardware.

Using a libSystem.B from an older SDK is a better idea, and probably will work, but given that it looks like Apple is not following it's own advice with library versioning (it looks like with 5.1 they dropped the version again), I would guess that this is going to cause problems as well.

So, if you want to support older devices, and you want the sim to work properly, it seems like the best approach is as follows:

  1. Add libSystem.B.dylib to the Link With Libraries in Build Phases as OPTIONAL (this is equivalent to adding the other linker flag -weak_library, but finds the correct file for you).
  2. Create a sym link from libSystem.dylib in the iOS SIMULATOR framework to libSystem.B.

My reasoning is that since the .B indicates a bump in versioning, and since ios5.x will have all of the needed functionality in the stock library, it should be ok to pretend the .B version is identical to the non-versioned library. With XCode 4.4 (July 2012), this is done with:

cd /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator5.1.sdk/usr/lib
sudo ln -s libSystem.dylib libSystem.B.dylib

Really, it is probably safe to use anything that looks like a valid library simply because when actually running in ios 5.x it does not currently even look for the B version....the workaround is to get past the link phase for older devices...nevertheless, it seems like this fix is safer than the other alternatives listed above.

Some Cross-References of Interest:

Weak Linking in Frameworks

Developer Tools Weak Linking

like image 30
Tony K. Avatar answered Nov 15 '22 08:11

Tony K.


Here's my solution for Xcode 4.0.2 with SDK 4.3 environment, but I believe it should also work on other setups.

  1. libSystem.B.dylib is not present under /Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator4.3.sdk/usr/lib, however it is present for lower SDK versions (e.g. iPhoneOS4.2.sdk)
  2. most of the cases libSystem.B.dylib is just a symbolic link to libSystem.dylib
  3. so in iPhoneSimulator4.3.sdk/usr/lib I've applied following command sudo ln -s libSystem.dylib libSystem.B.dylib and my simulator builds started to work again :)

NOTE: libSystem.B.dylib is used by Flurry and Urban Airship so you better don't delete the reference in project file (of course Urban Airship does not work under Simulator, but I think Flurry does. libSystem.B.dylib may also be required by other libraries you included to your project.

like image 21
matm Avatar answered Nov 15 '22 08:11

matm