Jak skompilować bibliotekę statyczną z włączoną funkcją Bitcode?

88

Xcode 7 wprowadza Bitcode , który jest rodzajem pośredniego pliku binarnego LLVM, co oznacza, że ​​serwery Apple mogą przekompilować moją aplikację dla różnych architektur bez mojego udziału.

W Lookback rozpowszechniam statyczną strukturę archiwum wraz z naszą biblioteką. Wygląda na to, że kiedy budujesz za pomocą czegoś innego niż „Build & Archive”, kod bitcode nie jest w rzeczywistości emitowany do mojej biblioteki, a każdy, kto łączy się z moją biblioteką w swojej aplikacji i spróbuje utworzyć kompilację i archiwizację z włączonym Bitcode, otrzyma jeden z dwa ostrzeżenia:

  • 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. (jeśli biblioteka jest zbudowana z 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) (jeśli biblioteka jest zbudowana z Xcode 7 z normalnym xcodebuild)

Mam skrypt kompilacji, który buduje uniwersalny plik binarny urządzenie + symulator, więc nie mogę używać funkcji Build & Archive, ale raczej uruchamiam xcodebuildz wiersza polecenia z mojego skryptu. Jak mogę xcodebuildwygenerować odpowiednią bibliotekę obsługującą bitcode?

nevyn
źródło
HI @nevyn Próbuję zmusić SDK do kompilacji w aplikacji, która używa kodu bitowego. Czy istnieje sposób?
Stoff81
@ Stoff81 Przepraszamy, pracuję nad tym. Najpierw muszę sprawić, by wszystkie moje zależności działały z Bitcode, a to całkiem sporo pracy.
nevyn

Odpowiedzi:

137

Bitcode to funkcja czasu kompilacji (nie funkcja czasu łącza), co oznacza, że ​​każdy plik .o powinien zawierać dodatkową sekcję o nazwie __bitcode, gdy jest budowany za pomocą bitcode. Możesz sprawdzić, czy Twój plik binarny jest zgodny z kodem bitowym, uruchamiając otool -l (my .o or .a file) | grep __LLVM.

Kiedy budujesz normalnie, Xcode dodaje flagę kompilacji -fembed-bitcode-markerdo każdego wywołania clang. Wydaje się, że jest to coś w rodzaju `` to jest miejsce, w którym byłby kod bitowy, gdyby był włączony kod bitowy '' i tak naprawdę nie włącza kodu bitowego.

Kiedy tworzysz i archiwizujesz, ta flaga jest zastępowana przez -fembed-bitcode, co naprawdę buduje plik binarny obsługujący Bitcode.

Wydaje się, że istnieją dwa sposoby xcodebuildwykorzystania -fembed-bitcode:

  • Użyj akcji „archiwum”, jak w xcodebuild -target LookbackSDK archivezamiast xcodebuild -target LookbackSDK build. Ma to efekt uboczny umieszczania plików binarnych w organizatorze Xcode zamiast w build/folderze, ale możesz to obejść, używając -exportArchive -archivePath ./build(dzięki @JensAyton )
  • Wymuś użycie flagi, dodając inne flagi C za pomocą OTHER_CFLAGS="-fembed-bitcode". Twoje xcodebuildwezwanie wyglądałoby mniej więcej tak xcodebuild OTHER_CFLAGS="-fembed-bitcode" -target LookbackSDK build.

To drugie jest tym, co wybrałem, aby nie musieć zmieniać mojego systemu kompilacji, ale generuje ostrzeżenia dla każdego pliku, ponieważ teraz oba -fembed-bitcode-markeri -fembed-bitcodesą wysyłane do clang. Na szczęście ten ostatni wygrywa, generując bibliotekę obsługującą Bitcode!

Zasoby

nevyn
źródło
9
FWIW, możesz pozbyć się ostrzeżenia o -fembed-bitcode-markerignorowaniu, dodając -Qunused-argumentsrównież.
mstorsjo
którego exportFormat używa do xcodebuild frameworka? Wydaje się, że zdefiniowane są tylko „ipa”, „pkg” i „aplikacja” ( developer.apple.com/library/mac/documentation/Darwin/Reference/… ).
Fabian Köbel
@nevyn Nadal nie można zbudować mojej głównej aplikacji, która ma niestandardowy plik struktury, który z kolei zawiera skrypt kompilacji z wyżej wymienioną flagą.
ravoorinandan
otool -l (mój plik .o lub .a). Czy masz na myśli otool -l (mój plik .o lub .a) | grep __bitcode?
Mike M
1
@MikeM nie otool -l myfile.o | grep __LLVM, ponieważ będzie segment __bitcode, nawet jeśli będzie tam tylko znacznik kodu bitowego zamiast prawdziwego kodu bitowego.
nevyn
40

Z Xcode 8 nie mogłem zabrać się OTHER_CFLAGS="-fembed-bitcode"do pracy. Ciągle wpadałem na coś podobnego do tego, was built without full bitcode. All frameworks and dylibs for bitcode must be generated from Xcode Archive or Install buildkiedy próbowałem stworzyć wersję Archive aplikacji zawierającą mój statyczny framework.

To, czego naprawdę szukałem, to:

BITCODE_GENERATION_MODE=bitcode

Właściwie używam skryptu uruchamiania wewnątrz zagregowanego celu, pełna linia xcodebuild wygląda następująco (tylko w celach informacyjnych):

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

Aaron Ash
źródło
2
+1, BITCODE_GENERATION_MODE=bitcodemetoda wydaje się być preferowana, jak zasugerowano również w tej odpowiedzi .
William Denniss,
To również rozwiązało mój problem, podczas gdy domyślna odpowiedź już nie.
Kamczatka
Oszczędza życie! Dziękuję Ci!
vidalbenjoe
17

Po dodaniu obsługi kodu bitowego dla biblioteki statycznej nie będzie ona zgodna z Xcode 6. Aplikacja nie zostanie zarchiwizowana.

Chciałbym wyraźnie wspomnieć o ustawieniu bitcode, ponieważ odpowiedź @ nevyn trochę mnie zdezorientowała.

Przejdź do ustawień kompilacji i wyszukaj „niestandardowe flagi kompilatora”. Dodaj -fembed-bitcode. Spowoduje to zbudowanie biblioteki z bitcode.

Gautam Jain
źródło
6

Wybierz projekt w ustawieniach kompilacji -> Inne flagi C, ustaw debugowanie na -fembed-bitcode-marker i Release na -fembed-bitcode

W ustawieniach kompilacji kliknij znak + u góry, aby dodać ustawienie kompilacji zdefiniowane przez użytkownika o nazwie BITCODE_GENERATION_MODE i ustaw opcję Debuguj na znacznik, Zwolnij na kod bitowy

Edytuj schemat jako Release Następnie kliknij żądaną bibliotekę. Plik i uzyskaj ścieżkę kompilacji. Pobierz bibliotekę z folderu Release.

Oshitha Wimalasuriya
źródło