it-swarm.com.de

Was macht ENABLE_BITCODE in xcode 7?

Ich habe ein Problem mit dem eingebetteten Bitcode-Begriff.
Was ist eingebetteter Bitcode?
Wann muss ENABLE_BITCODE in neuem Xcode aktiviert werden?
Was passiert mit der Binärdatei, wenn diese aktiviert ist, ENABLE_BITCODE in Xcode 7?

257
damithH

Bitcode bezieht sich auf die Art des Codes: "LLVM-Bitcode", der an iTunes Connect gesendet wird. Dies ermöglicht es Apple, bestimmte Berechnungen zu verwenden, um Apps weiter zu optimieren (z. B. die ausführbaren Größen möglicherweise zu verkleinern). Wenn Apple Ihre ausführbare Datei ändern muss, können sie dies tun, ohne dass ein neuer Build hochgeladen wird.

Dies unterscheidet sich von: Slicing , bei dem Apple Ihre App für das Gerät eines Benutzers basierend auf der Auflösung und Architektur des Geräts optimiert wird. Das Schneiden erfordert keinen Bitcode. (Bsp .: nur mit @ 2x Bildern auf einer 5s)

App-Ausdünnung ist die Kombination aus Slicing-, Bitcode- und On-Demand-Ressourcen

Bitcode ist eine Zwischendarstellung eines kompilierten Programms. Apps, die Sie zu iTunes Connect hochladen und die Bitcode enthalten, werden im App Store kompiliert und verlinkt. Durch das Einfügen von Bitcode kann Apple Ihre App-Binärdatei in Zukunft erneut optimieren, ohne dass eine neue Version Ihrer App an den Store gesendet werden muss.

Apple-Dokumentation zur App-Ausdünnung

301
keji

Was ist eingebetteter Bitcode?

Nach docs :

Bitcode ist eine Zwischendarstellung eines kompilierten Programms. Apps, die Sie zu iTunes Connect hochladen und die Bitcode enthalten, werden im App Store kompiliert und verlinkt. Durch das Einfügen von Bitcode kann Apple Ihre App-Binärdatei in Zukunft erneut optimieren, ohne dass eine neue Version Ihrer App an den Store gesendet werden muss.

Update: Dieser Satz in "Neue Funktionen in Xcode 7" ließ mich lange darüber nachdenken, dass Bitcode wird für Slicing benötigt, um die App-Größe zu reduzieren:

Wenn Sie zum Einreichen im App Store archivieren, kompiliert Xcode Ihre App in eine Zwischendarstellung. Der App Store kompiliert dann den Bitcode nach Bedarf in die ausführbaren 64- oder 32-Bit-Dateien.

Das ist jedoch nicht wahr, Bitcode und Slicing arbeiten unabhängig voneinander: Slicing ist ungefähr Reduzieren der App-Größe und Generieren von App-Bundle-Varianten. Bei Bitcode handelt es sich um bestimmte binäre Optimierungen. Ich habe dies überprüft, indem ich die enthaltenen Architekturen in ausführbaren Dateien von Nicht-Bitcode-Apps überprüft habe und festgestellt habe, dass sie nur die erforderlichen enthalten.

Mit Bitcode können andere App-Ausdünnungs- Komponenten mit dem Namen Slicing App-Bundle-Varianten mit erzeugen bestimmte ausführbare Dateien für bestimmte Architekturen, z Die iPhone 5S-Variante wird nur die ausführbare Version von arm64, das iPad Mini armv7 usw. enthalten.

Wann soll ENABLE_BITCODE in neuem Xcode aktiviert werden?

Bei iOS-Apps ist Bitcode die Standardeinstellung, jedoch optional. Wenn Sie Bitcode bereitstellen, müssen alle Apps und Frameworks im App-Bundle Bitcode enthalten. Für watchOS- und tvOS-Apps ist ein Bitcode erforderlich.

Was passiert mit der Binärdatei, wenn ENABLE_BITCODE im neuen Xcode aktiviert ist?

Aus der Xcode 7-Referenz:

Das Aktivieren dieser Einstellung gibt an, dass das Ziel oder Projekt während der Kompilierung für Plattformen und Architekturen, die dies unterstützen, Bitcode generieren soll. Bei Archiv-Builds wird der Bitcode in der verknüpften Binärdatei zur Übermittlung an den App Store generiert. Bei anderen Builds prüfen der Compiler und der Linker, ob der Code den Anforderungen für die Bitcode-Generierung entspricht, generieren jedoch keinen tatsächlichen Bitcode.

Hier sind ein paar Links, die zum besseren Verständnis von Bitcode beitragen:

80
Maxim Pavlov

Da die genaue Frage lautet "Was ermöglicht Bitcode?", Möchte ich einige technische Details nennen, die ich bisher herausgefunden habe. Das meiste davon ist praktisch unmöglich mit 100% iger Sicherheit herauszufinden, bis Apple den Quellcode für diesen Compiler veröffentlicht

Erstens scheint der Apple-Bitcode nicht mit dem LLVM-Bytecode identisch zu sein . Zumindest konnte ich keine Ähnlichkeit zwischen ihnen feststellen. Es scheint einen proprietären Header zu haben (der immer mit "xar!" Beginnt) und wahrscheinlich eine Art Referenzmagie für die Verbindungszeit, die Datenduplikationen verhindert. Wenn Sie eine fest codierte Zeichenfolge ausschreiben, wird diese Zeichenfolge nur einmal und nicht zweimal in die Daten eingefügt, wie dies bei einem normalen LLVM-Bytecode zu erwarten wäre.

Zweitens wird Bitcode im Binärarchiv nicht wie erwartet als separate Architektur ausgeliefert. Es wird nicht auf die gleiche Weise ausgeliefert, wie beispielsweise x86 und ARM in einer Binärdatei (FAT-Archiv) abgelegt werden. Stattdessen verwenden sie einen speziellen Abschnitt in der architekturspezifischen MachO-Binärdatei mit dem Namen "__LLVM", der mit jeder unterstützten (dh duplizierten) Architektur ausgeliefert wird. Ich gehe davon aus, dass dies ein Mangel des Compilersystems ist, der möglicherweise in Zukunft behoben wird, um Doppelspurigkeiten zu vermeiden.

C-Code (kompiliert mit clang -fembed-bitcode hi.c -S -emit-llvm):

#include <stdio.h>

int main() {
    printf("hi there!");
    return 0;
}

LLVM IR Ausgang:

; ModuleID = '/var/folders/rd/sv6v2_f50nzbrn4f64gnd4gh0000gq/T/hi-a8c16c.bc'
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-Apple-macosx10.10.0"

@.str = private unnamed_addr constant [10 x i8] c"hi there!\00", align 1
@llvm.embedded.module = appending constant [1600 x i8] c"\DE\C0\17\0B\00\00\00\00\14\00\00\00$\06\00\00\07\00\00\01BC\C0\DE!\0C\00\00\86\01\00\00\0B\82 \00\02\00\00\00\12\00\00\00\07\81#\91A\C8\04I\06\1029\92\01\84\0C%\05\08\19\1E\04\8Bb\80\10E\02B\92\0BB\84\102\148\08\18I\0A2D$H\0A\90!#\C4R\80\0C\19!r$\07\C8\08\11b\A8\A0\[email protected]\C6\F0\01\00\00\00Q\18\00\00\C7\00\00\00\1Bp$\F8\FF\FF\FF\FF\01\90\00\0D\08\03\82\1D\CAa\1E\E6\A1\0D\E0A\1E\CAa\1C\D2a\1E\CA\A1\0D\CC\01\1E\DA!\1C\C8\010\87p`\87y(\07\80p\87wh\03s\90\87ph\87rh\03xx\87tp\07z(\07yh\83r`\87th\07\80\1E\E4\A1\1E\CA\01\18\DC\E1\1D\DA\C0\1C\E4!\1C\DA\A1\1C\DA\00\1E\DE!\1D\DC\81\1E\CAA\1E\DA\A0\1C\D8!\1D\DA\A1\0D\DC\E1\1D\DC\A1\0D\D8\A1\1C\C2\C1\1C\00\C2\1D\DE\A1\0D\D2\C1\1D\CCa\1E\DA\C0\1C\E0\A1\0D\DA!\1C\E8\01\1D\00s\08\07v\98\87r\00\08wx\876p\87pp\87yh\03s\80\876h\87p\A0\07t\00\CC!\1C\D8a\1E\CA\01 \E6\81\1E\C2a\1C\D6\A1\0D\E0A\1E\DE\81\1E\CAa\1C\E8\E1\1D\E4\A1\0D\C4\A1\1E\CC\C1\1C\CAA\1E\DA`\1E\D2A\1F\CA\01\C0\03\80\A0\87p\90\87s(\07zh\83q\80\87z\00\C6\E1\1D\E4\A1\1C\E4\00 \E8!\1C\E4\E1\1C\CA\81\1E\DA\C0\1C\CA!\1C\E8\A1\1E\E4\A1\1C\E6\01X\83y\98\87y(\879`\835\18\07|\88\03;`\835\98\87y(\076X\83y\98\87r\90\036X\83y\98\87r\98\03\80\A8\07w\98\87p0\87rh\03s\80\876h\87p\A0\07t\00\CC!\1C\D8a\1E\CA\01 \EAa\1E\CA\A1\0D\E6\E1\1D\CC\81\1E\DA\C0\1C\D8\E1\1D\C2\81\1E\00s\08\07v\98\87r\006\C8\88\F0\FF\FF\FF\FF\03\C1\0E\E50\0F\F3\D0\06\F0 \0F\E50\0E\E90\0F\E5\D0\06\E6\00\0F\ED\10\0E\E4\00\98C8\B0\C3<\94\[email protected]\B8\C3;\B4\819\C8C8\B4C9\B4\01<\BCC:\B8\03=\94\83<\B4A9\B0C:\B4\[email protected]\0F\F2P\0F\E5\00\0C\EE\F0\0Em`\0E\F2\10\0E\EDP\0Em\00\0F\EF\90\0E\[email protected]\0F\E5 \0FmP\0E\EC\90\0E\ED\D0\06\EE\F0\0E\EE\D0\06\ECP\0E\E1`\0E\00\E1\0E\EF\D0\06\E9\E0\0E\E60\0Fm`\0E\F0\D0\06\ED\10\0E\F4\80\0E\809\84\03;\CCC9\00\84;\BCC\1B\B8C8\B8\C3<\B4\819\C0C\1B\B4C8\D0\03:\00\E6\10\0E\EC0\0F\E5\00\10\[email protected]\0F\E10\0E\EB\D0\06\F0 \0F\[email protected]\0F\E50\0E\F4\F0\0E\F2\D0\06\E2P\0F\E6`\0E\E5 \0Fm0\0F\E9\A0\0F\E5\00\E0\[email protected]\D0C8\C8\C39\94\03=\B4\C18\C0C=\00\E3\F0\0E\F2P\0Er\00\10\F4\10\0E\F2p\0E\[email protected]\0Fm`\0E\E5\10\0E\F4P\0F\F2P\0E\F3\00\AC\C1<\CC\C3<\94\C3\1C\B0\C1\1A\8C\03>\C4\81\1D\B0\C1\1A\CC\C3<\94\03\1B\AC\C1<\CCC9\C8\01\1B\AC\C1<\CCC9\CC\[email protected]\D4\83;\CCC8\98C9\B4\819\C0C\1B\B4C8\D0\03:\00\E6\10\0E\EC0\0F\E5\00\10\F50\0F\E5\D0\06\F3\F0\0E\[email protected]\0Fm`\0E\EC\F0\0E\[email protected]\0F\809\84\03;\CCC9\00\00I\18\00\00\02\00\00\00\13\82`B \00\00\00\89 \00\00\0D\00\00\002\22\08\09 d\85\04\13\22\A4\84\04\13\22\E3\84\A1\90\14\12L\88\8C\0B\84\84L\100s\04H*\00\C5\1C\01\18\94`\88\08\AA0F7\[email protected]\02\00\134|\C0\03;\F8\05;\A0\836\08\07x\80\07v(\876h\87p\18\87w\98\07|\88\038p\838\80\037\80\83\0DeP\0Em\D0\0Ez\F0\0Em\90\[email protected]\07z`\07t\D0\06\E6\80\07p\A0\07q \07x\D0\06\EE\80\07z\10\07v\A0\07s \07z`\07t\D0\06\B3\10\07r\80\07:\0FDH #EB\80\1D\8C\10\18I\00\[email protected]\00\00\C0\10\A7\00\00 \00\00\00\00\00\00\00\868\08\10\00\02\00\00\00\00\00\00\90\05\02\00\00\08\00\00\002\1E\98\0C\19\11L\90\8C\09&G\C6\04C\9A\22(\01\0AM\D0i\10\1D]\96\97C\00\00\00y\18\00\00\1C\00\00\00\1A\03L\90F\02\134A\18\08&PIC Level\13\84a\D80\04\C2\C05\08\82\83c+\03ab\B2j\02\B1+\93\9BK{s\03\B9q\81q\81\01A\19c\0Bs;k\B9\81\81q\81q\A9\99q\99I\D9\10\14\8D\D8\D8\EC\DA\5C\DA\DE\C8\EA\D8\CA\5C\CC\D8\C2\CE\E6\A6\04C\1566\BB6\974\B227\BA)A\01\00y\18\00\002\00\00\003\08\80\1C\C4\E1\1Cf\14\01=\88C8\84\C3\8CB\80\07yx\07s\98q\0C\E6\00\0F\ED\10\0E\F4\80\0E3\0CB\1E\C2\C1\1D\CE\A1\1Cf0\05=\88C8\84\83\1B\CC\03=\C8C=\8C\03=\CCx\8Ctp\07{\08\07yH\87pp\07zp\03vx\87p \87\19\CC\11\0E\EC\90\0E\E10\0Fn0\0F\E3\F0\0E\F0P\0E3\10\C4\1D\DE!\1C\D8!\1D\C2a\1Ef0\89;\BC\83;\D0C9\B4\03<\BC\83<\84\03;\CC\F0\14v`\07{h\077h\87rh\077\80\87p\90\87p`\07v(\07v\F8\05vx\87w\80\87_\08\87q\18\87r\98\87y\98\81,\EE\F0\0E\EE\E0\0E\F5\C0\0E\EC\00q \00\00\05\00\00\00&`<\11\D2L\85\05\10\0C\804\[email protected]\F8\D2\14\01\00\00a \00\00\0B\00\00\00\13\04A,\10\00\00\00\03\00\00\004#\00dC\19\020\18\83\01\003\11\[email protected]\0C\83\11\C1\00\00#\06\04\00\1CB\12\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00", section "__LLVM,__bitcode"
@llvm.cmdline = appending constant [67 x i8] c"-triple\00x86_64-Apple-macosx10.10.0\00-emit-llvm\00-disable-llvm-optzns\00", section "__LLVM,__cmdline"

; Function Attrs: nounwind ssp uwtable
define i32 @main() #0 {
  %1 = alloca i32, align 4
  store i32 0, i32* %1
  %2 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([10 x i8]* @.str, i32 0, i32 0))
  ret i32 0
}

declare i32 @printf(i8*, ...) #1

attributes #0 = { nounwind ssp uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="core2" "target-features"="+ssse3,+cx16,+sse,+sse2,+sse3" "unsafe-fp-math"="false" "use-soft-float"="false" }
attributes #1 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="core2" "target-features"="+ssse3,+cx16,+sse,+sse2,+sse3" "unsafe-fp-math"="false" "use-soft-float"="false" }

!llvm.module.flags = !{!0}
!llvm.ident = !{!1}

!0 = !{i32 1, !"PIC Level", i32 2}
!1 = !{!"Apple LLVM version 7.0.0 (clang-700.0.53.3)"}

Das Datenarray im IR ändert sich auch in Abhängigkeit von der Optimierung und anderen Einstellungen für die Codegenerierung von clang. Mir ist völlig unbekannt, in welchem ​​Format oder in was auch immer.

BEARBEITEN:

Aufgrund des Hinweises auf Twitter habe ich mich entschlossen, dies noch einmal zu überprüfen und zu bestätigen. Ich folgte diesem Blog-Beitrag und holte mit seinem Bitcode-Extraktions-Tool die Apple-Archiv-Binärdatei aus der ausführbaren MachO-Datei. Und nachdem ich das Archiv Apple mit dem Dienstprogramm xar extrahiert habe, habe ich es erhalten (natürlich mit llvm-dis in Text konvertiert)

; ModuleID = '1'
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-Apple-macosx10.10.0"

@.str = private unnamed_addr constant [10 x i8] c"hi there!\00", align 1

; Function Attrs: nounwind ssp uwtable
define i32 @main() #0 {
  %1 = alloca i32, align 4
  store i32 0, i32* %1
  %2 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str, i32 0, i32 0))
  ret i32 0
}

declare i32 @printf(i8*, ...) #1

attributes #0 = { nounwind ssp uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="core2" "target-features"="+ssse3,+cx16,+sse,+sse2,+sse3" "unsafe-fp-math"="false" "use-soft-float"="false" }
attributes #1 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="core2" "target-features"="+ssse3,+cx16,+sse,+sse2,+sse3" "unsafe-fp-math"="false" "use-soft-float"="false" }

!llvm.module.flags = !{!0}
!llvm.ident = !{!1}

!0 = !{i32 1, !"PIC Level", i32 2}
!1 = !{!"Apple LLVM version 7.0.0 (clang-700.1.76)"}

Der einzige bemerkenswerte Unterschied zwischen dem Nicht-Bitcode-IR und dem Bitcode-IR besteht darin, dass die Dateinamen für jede Architektur auf 1, 2 usw. reduziert wurden.

Ich habe auch bestätigt, dass der in eine Binärdatei eingebettete Bitcode nach Optimierungen generiert wird. Wenn Sie mit -O3 kompilieren und den Bitcode extrahieren, unterscheidet sich dies von der Kompilierung mit -O0.

Und um zusätzliche Gutschriften zu erhalten, habe ich außerdem bestätigt, dass Apple beim Herunterladen einer iOS 9-App keinen Bitcode an Geräte sendet. Sie enthalten eine Reihe anderer seltsamer Abschnitte, die ich nicht als __LINKEDIT erkannt habe, aber sie enthalten kein __LLVM .__-Bundle und scheinen daher keinen Bitcode in der endgültigen Binärdatei zu enthalten, die auf einem Gerät ausgeführt wird. Seltsamerweise liefert Apple immer noch fette Binärdateien mit separatem 32/64-Bit-Code an iOS 8-Geräte.

19
Earlz

Bitcode (iOS, watchOS)

Bitcode ist eine Zwischendarstellung eines kompilierten Programms. Apps, die Sie zu iTunes Connect hochladen und die Bitcode enthalten, werden im App Store kompiliert und verlinkt. Durch das Einfügen von Bitcode kann Apple Ihre App-Binärdatei in Zukunft erneut optimieren, ohne dass eine neue Version Ihrer App an den Store gesendet werden muss.


Grundsätzlich ähnelt dieses Konzept Java, bei dem der Bytecode auf verschiedenen JVMs ausgeführt wird und in diesem Fall der Bitcode im iTune-Speicher abgelegt wird, anstatt den Zwischencode auf verschiedenen Plattformen (Geräten) bereitzustellen, die er kompiliert Code, für dessen Ausführung keine virtuelle Maschine erforderlich ist.

Daher müssen wir den Bitcode einmal erstellen und er wird für bestehende oder kommende Geräte verfügbar sein. Es bereitet Apple Kopfzerbrechen, es mit jeder Plattform, die sie haben, kompatibel zu machen.

Entwickler müssen keine Änderungen vornehmen und die App erneut senden, um neue Plattformen zu unterstützen.

Nehmen wir das Beispiel von iPhone 5s, als Apple x64 den Chip darin einführte. Obwohl x86 Apps vollständig mit der x64 Architektur kompatibel waren, muss der Entwickler die Architektur oder einen Code ändern, um die x64 Plattform vollständig nutzen zu können. Sobald die App fertig ist, wird sie zur Überprüfung an den App Store gesendet.

Wenn dieses Bitcode-Konzept früher eingeführt wurde, müssen die Entwickler keine Änderungen vornehmen, um die Bit-Architektur x64 zu unterstützen.

12

Update

Apple hat klargestellt dass das Slicing unabhängig von der Aktivierung des Bitcodes erfolgt. Ich habe dies auch in der Praxis beobachtet, wo eine nicht-Bitcode-fähige App nur als die für das Zielgerät geeignete Architektur heruntergeladen wird.

Original

Genauer :

Bitcode. Archivieren Sie Ihre App zur Übermittlung an den App Store in einer Zwischendarstellung, die im Auslieferungszustand in ausführbare 64- oder 32-Bit-Dateien für die Zielgeräte kompiliert wird.

Schneiden. Durch die Aufnahme von Kunstwerken in den Asset-Katalog und die Kennzeichnung für eine Plattform kann der App Store nur das liefern, was für die Installation benötigt wird.

So wie ich das lese, erhalten Downloader Ihrer App nur die kompilierte Architektur, die sie für ihr eigenes Gerät benötigen, wenn Sie Bitcode unterstützen.

4
Ben Flynn