Как мне создать xcodebuild статическую библиотеку с включенным битовым кодом?

Xcode 7 представляет биткод, который является своего рода промежуточным двоичным кодом LLVM, что означает, что серверы Apple могут перекомпилировать мое приложение для разных архитектур без моего участия.

В Lookback я распространяю статическую структуру архива с нашей библиотекой. Похоже, что когда вы строите что-либо, кроме "Build and 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)

У меня есть сборка script, которая строит универсальный двоичный файл device + simulator, поэтому я не могу использовать Build и Archive, но вместо этого я запускаю xcodebuild из командной строки из моего script. Как я могу сделать xcodebuild создать надлежащую библиотеку с поддержкой битового кода?

Ответ 1

Биткод - это функция времени компиляции (а не функция времени соединения), что означает, что каждый файл .o должен содержать дополнительный раздел, называемый __bitcode, когда он построен с помощью битового кода. Вы можете подтвердить, совместим ли ваш бинард с совместимостью с битами, запустив otool -l (my .o or .a file) | grep __LLVM.

Когда вы строите нормально, Xcode добавляет флаг сборки -fembed-bitcode-marker к любому вызову clang. Кажется, что это какой-то "это то, где биткод будет идти, если биткод был включен", и на самом деле не разрешает биткод.

Когда вы создаете и архивируете, этот флаг заменяется на -fembed-bitcode, который действительно создает двоичный код с поддержкой Bitcode.

Кажется, есть два способа сделать xcodebuild использование -fembed-bitcode:

  • Используйте действие "archive", как в xcodebuild -target LookbackSDK archive вместо xcodebuild -target LookbackSDK build. Это имеет побочный эффект по созданию двоичных файлов в вашем Xcode Organizer вместо папки build/, хотя вы можете обойти это с помощью -exportArchive -archivePath ./build (спасибо @JensAyton)
  • Принудительное использование флага путем добавления других флагов C с OTHER_CFLAGS="-fembed-bitcode". Ваш вызов xcodebuild будет выглядеть примерно как xcodebuild OTHER_CFLAGS="-fembed-bitcode" -target LookbackSDK build.

Последний - это то, что я выбрал так, что мне не нужно менять мою систему сборки, но она будет генерировать предупреждения для каждого файла, так как теперь оба -fembed-bitcode-marker и -fembed-bitcode отправляются в clang. Luckilly последний выигрывает, создавая библиотеку с поддержкой Bitcode!

Ресурсы

Ответ 2

После добавления поддержки bitcode для статического lib он не будет совместим с Xcode 6. Приложение не будет архивироваться.

Я хотел бы четко указать настройку для битового кода, так как ответ @nevyn немного смутил меня.

Перейдите к настройкам сборки, найдите "настраиваемые флаги компилятора". Добавьте -fembed-bitcode. Это создаст ваш lib с помощью битового кода.

Ответ 3

С Xcode 8 я не смог заставить OTHER_CFLAGS="-fembed-bitcode" работать. Я продолжал сталкиваться с чем-то вроде was built without full bitcode. All frameworks and dylibs for bitcode must be generated from Xcode Archive or Install build, когда пытался создать сборку архива приложения, содержащего мою статическую фреймворк.

Я действительно искал это:

BITCODE_GENERATION_MODE=bitcode

Я использую Run Script внутри агрегатной цели, полная строка xcodebuild выглядит так (только для справки):

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