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
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.
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:
- 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).
- 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
Here's my solution for Xcode 4.0.2 with SDK 4.3 environment, but I believe it should also work on other setups.
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
)
- most of the cases
libSystem.B.dylib
is just a
symbolic link to libSystem.dylib
- 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.
Here is my step-by-step solution:
- I've copied libSystem.B.dylib file from my friend's MAC (/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS4.2.sdk/usr/lib/libSystem.B.dylib). !!! xCode 3.2.5 was installed on his MAC with 4.0 and 4.2 SDKs. !!!
- Go to: ProjectSettings > Targets > BuildPhases > Link Binary With Libraries > '+'.
- 'Add other'. Select the copied libSystem.B.dylib file (you can locate it in your project bundle)
- Build...
After this I did not get 'library not found for -lSystem.B' error.
Also the app runs file on devices with iOS < 4.
It's very odd, but it seems that the problem is inside the native libSystem.B.dylib file.
Native - I mean xCode's 4.0.2.
Good luck.