如何在启用 Bitcode 的情况下创建静态库?

Xcode 7引入了 比特码,这是某种 LLVM 中间二进制代码,这意味着苹果的服务器可以在没有我参与的情况下为不同的架构重新编译我的应用程序。

在回顾中,我使用我们的库发布了一个静态归档框架。似乎当你使用“ Build & Archive”以外的任何东西构建时,比特码实际上并没有发送到我的库中,任何人在他们的应用程序中链接到我的库,并且试图在启用了比特码的情况下进行构建和存档,都会得到以下两个警告之一:

  • ld: 'Lookback(Lookback.o)' does not contain bitcode. You must rebuild it with bitcode enabled (Xcode setting ENABLE_BITCODE), obtain an updated library from the vendor, or disable bitcode for this target.(如果 lib 是用 Xcode 6构建的)
  • ld: warning: full bitcode bundle could not be generated because 'Lookback(Lookback.o)' was built only with bitcode marker. The library must be generated from Xcode archive build with bitcode enabled (Xcode setting ENABLE_BITCODE)(如果 lib 使用 Xcode 7构建,并使用普通的 xcodebuild)

我有一个构建脚本,它构建了一个设备 + 模拟器通用二进制,所以我不能使用 Build & Archive,但是,我从我的脚本命令行运行 xcodebuild。我怎样才能使 xcodebuild生成一个适当的位码启用库?

52322 次浏览

Bitcode is a compile-time feature (not a link-time feature) which means that every .o file should contain an extra section called __bitcode when built with bitcode. You can confirm whether your binary is bitcode-compatible by running otool -l (my .o or .a file) | grep __LLVM.

When you build normally, Xcode adds the build flag -fembed-bitcode-marker to any clang invocation. This seems to be some sort of 'this is where bitcode would go, if bitcode was enabled' thing, and doesn't actually enable bitcode.

When you "Build & Archive", this flag is replaced by -fembed-bitcode, which really does build a Bitcode-enabled binary.

There seems to be two ways to make xcodebuild use -fembed-bitcode:

  • Use the 'archive' action, as in xcodebuild -target LookbackSDK archive instead of xcodebuild -target LookbackSDK build. This has the side-effect of putting binaries in your Xcode Organizer instead of the build/ folder, though you can work around that by using -exportArchive -archivePath ./build (thanks @JensAyton)
  • Force usage of the flag by adding Other C Flags with OTHER_CFLAGS="-fembed-bitcode". Your xcodebuild invocation would look something like xcodebuild OTHER_CFLAGS="-fembed-bitcode" -target LookbackSDK build.

The latter is what I chose so that I don't have to change my build system, but it will generate warnings for every file, since now both -fembed-bitcode-marker and -fembed-bitcode are sent to clang. Luckilly the latter wins, generating a Bitcode-enabled library!

Resources

Once you add bitcode support for the static lib, it won't be compatible with Xcode 6. The app won't archive.

I would like to clearly mention the setting for bitcode as @nevyn's answer confused me a little.

Go to Build settings, search for "custom compiler flags". Add -fembed-bitcode. This will build your lib with bitcode.

With Xcode 8, I couldn't get OTHER_CFLAGS="-fembed-bitcode" to work. I kept running into something along the lines of was built without full bitcode. All frameworks and dylibs for bitcode must be generated from Xcode Archive or Install build when I tried to create an Archive build of an app containing my static framework.

What I was really looking for was this:

BITCODE_GENERATION_MODE=bitcode

I'm actually using a Run Script inside of an aggregate target, the full xcodebuild line looks like this (just for reference):

xcodebuild BITCODE_GENERATION_MODE=bitcode OTHER_CFLAGS="-fembed-bitcode" -target "${PROJECT_NAME}" ONLY_ACTIVE_ARCH=NO -configuration ${CONFIGURATION} -sdk iphoneos BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" clean build

Select project On Build Settings -> Other C flags, set Debug to -fembed-bitcode-marker and Release to -fembed-bitcode

On Build Settings, click on the + sign at the top to add a user-defined build setting with the name BITCODE_GENERATION_MODE, and set Debug to marker, Release to bitcode

Edit schema as Release Then click the desired library. A file and get the build path. Get the library form Release folder.