Antworten:
Bitcode bezieht sich auf den Codetyp: "LLVM-Bitcode", der an iTunes Connect gesendet wird. Auf diese Weise kann Apple bestimmte Berechnungen verwenden, um Apps weiter zu optimieren (z. B. möglicherweise die Größe der ausführbaren Dateien zu verringern). 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 basierend auf der Auflösung und Architektur des Geräts für das Gerät eines Benutzers optimiert. Für das Schneiden ist kein Bitcode erforderlich. (Beispiel: nur mit @ 2x Bildern auf einer 5s)
App Thinning ist die Kombination aus Slicing-, Bitcode- und On-Demand-Ressourcen
Bitcode ist eine Zwischendarstellung eines kompilierten Programms. Apps, die Sie in iTunes Connect hochladen und die Bitcode enthalten, werden im App Store kompiliert und verknüpft. Durch das Einfügen von Bitcode kann Apple Ihre App-Binärdatei in Zukunft erneut optimieren, ohne eine neue Version Ihrer App an den Store senden zu müssen.
Laut Dokumentation :
Bitcode ist eine Zwischendarstellung eines kompilierten Programms. Apps, die Sie in iTunes Connect hochladen und die Bitcode enthalten, werden im App Store kompiliert und verknüpft. Durch das Einfügen von Bitcode kann Apple Ihre App-Binärdatei in Zukunft erneut optimieren, ohne eine neue Version Ihrer App an den Store senden zu müssen.
Update: Dieser Satz in „Neue Funktionen in Xcode 7“ hat mich für eine lange Zeit zu denken , dass Bitcode für erforderlich Slicing App Größe zu reduzieren:
Wenn Sie zur Übermittlung an den App Store archivieren, kompiliert Xcode Ihre App zu einer Zwischendarstellung. Der App Store kompiliert den Bitcode dann nach Bedarf in die ausführbaren 64- oder 32-Bit-Dateien.
Dies ist jedoch nicht der Fall. Bitcode und Slicing funktionieren unabhängig voneinander: Beim Slicing geht es darum, die App-Größe zu reduzieren und App-Bundle-Varianten zu generieren , und bei Bitcode geht es um bestimmte binäre Optimierungen. Ich habe dies überprüft, indem ich die in ausführbaren Dateien von Nicht-Bitcode-Apps enthaltenen Architekturen überprüft und festgestellt habe, dass sie nur die erforderlichen enthalten.
Mit Bitcode können andere App-Ausdünnungskomponenten namens Slicing App-Bundle-Varianten mit bestimmten ausführbaren Dateien für bestimmte Architekturen generieren, z. B. enthält die iPhone 5S-Variante nur die ausführbare Datei arm64, das iPad Mini armv7 usw.
Für 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 Bitcode erforderlich.
Aus Xcode 7 Referenz:
Wenn Sie diese Einstellung aktivieren, sollte das Ziel oder Projekt während der Kompilierung Bitcode für Plattformen und Architekturen generieren, die dies unterstützen. Bei Archiv-Builds wird 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 einige Links, die zum tieferen Verständnis von Bitcode beitragen :
Da die genaue Frage lautet: "Was macht Bitcode?", Möchte ich einige dünne technische Details nennen, die ich bisher herausgefunden habe. Das meiste davon ist praktisch nicht mit 100% iger Sicherheit herauszufinden, bis Apple den Quellcode für diesen Compiler veröffentlicht
Zuerst Apples Bitcode nicht erscheint dasselbe wie LLVM Bytecode zu sein. Zumindest konnte ich keine Ähnlichkeit zwischen ihnen feststellen. Es scheint einen proprietären Header zu haben (beginnt immer mit "xar!") Und wahrscheinlich eine Referenzmagie zur Verbindungszeit, die Datenverdopplungen verhindert. Wenn Sie eine fest codierte Zeichenfolge schreiben, wird diese Zeichenfolge nur einmal in die Daten eingefügt und nicht zweimal, wie dies bei einem normalen LLVM-Bytecode zu erwarten wäre.
Zweitens wird Bitcode nicht wie erwartet als separate Architektur im Binärarchiv ausgeliefert. Es wird nicht auf die gleiche Weise ausgeliefert, wie beispielsweise x86 und ARM in einer Binärdatei (FAT-Archiv) zusammengefasst sind. Stattdessen verwenden sie einen speziellen Abschnitt in der architekturspezifischen MachO-Binärdatei mit dem Namen "__LLVM", der mit jeder unterstützten Architektur geliefert wird (dh dupliziert wird). Ich gehe davon aus, dass dies mit ihrem Compilersystem ein Mangel ist und möglicherweise in Zukunft behoben wird, um die Duplizierung 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\A8@\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\03@\B8\C3;\B4\819\C8C8\B4C9\B4\01<\BCC:\B8\03=\94\83<\B4A9\B0C:\B4\03@\0F\F2P\0F\E5\00\0C\EE\F0\0Em`\0E\F2\10\0E\EDP\0Em\00\0F\EF\90\0E\EE@\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\F3@\0F\E10\0E\EB\D0\06\F0 \0F\EF@\0F\E50\0E\F4\F0\0E\F2\D0\06\E2P\0F\E6`\0E\E5 \0Fm0\0F\E9\A0\0F\E5\00\E0\01@\D0C8\C8\C39\94\03=\B4\C18\C0C=\00\E3\F0\0E\F2P\0Er\00\10\F4\10\0E\F2p\0E\E5@\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\01@\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\E6@\0Fm`\0E\EC\F0\0E\E1@\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\10@3\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\0Ev@\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\00@\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\06@\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\CA@\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 welchem Format dies ist.
BEARBEITEN:
Dem Hinweis auf Twitter folgend, habe ich mich entschlossen, dies erneut zu besuchen und zu bestätigen. Ich folgte diesem Blog-Beitrag und benutzte sein Bitcode-Extraktor-Tool, um die Apple Archive-Binärdatei aus der ausführbaren MachO-Datei zu entfernen. Und nachdem ich das Apple-Archiv mit dem Dienstprogramm xar extrahiert hatte, bekam ich dies (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 nur 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, ist dies anders als beim Kompilieren mit -O0.
Und um zusätzliche Gutschriften zu erhalten, habe ich auch 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.
xar!
ist Archivdateiformat von Apple.
Bitcode (iOS, watchOS)
Bitcode ist eine Zwischendarstellung eines kompilierten Programms. Apps, die Sie in iTunes Connect hochladen und die Bitcode enthalten, werden im App Store kompiliert und verknüpft. Durch das Einfügen von Bitcode kann Apple Ihre App-Binärdatei in Zukunft erneut optimieren, ohne eine neue Version Ihrer App an den Store senden zu müssen.
Grundsätzlich ähnelt dieses Konzept Java, bei dem Bytecode auf verschiedenen JVMs ausgeführt wird. In diesem Fall wird der Bitcode im iTune-Speicher abgelegt und statt den Zwischencode an verschiedene Plattformen (Geräte) weiterzugeben, wird der kompilierte Code bereitgestellt, der nicht benötigt wird jede auszuführende virtuelle Maschine.
Daher müssen wir den Bitcode einmal erstellen und er wird für vorhandene oder kommende Geräte verfügbar sein. Es ist das Problem von Apple, zu kompilieren und es mit jeder Plattform kompatibel zu machen, die sie haben.
Entwickler müssen keine Änderungen vornehmen und die App erneut senden, um neue Plattformen zu unterstützen.
Nehmen wir das Beispiel des iPhone 5s, als Apple einen x64
Chip einführte . Obwohl x86
Apps vollständig mit der x64
Architektur kompatibel waren, muss x64
der Entwickler die Architektur oder einen Code ändern, um die Plattform vollständig nutzen zu können . Sobald er fertig ist, wird die App zur Überprüfung an den App Store gesendet.
Wenn dieses Bitcode-Konzept früher gestartet wurde, müssen wir Entwickler keine Änderungen vornehmen, um die x64
Bit-Architektur zu unterstützen.
Aktualisieren
Apple hat klargestellt, dass das Schneiden 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
Bitcode. Archivieren Sie Ihre App zur Übermittlung an den App Store in einer Zwischendarstellung, die bei Auslieferung in ausführbare 64- oder 32-Bit-Dateien für die Zielgeräte kompiliert wird.
Schneiden. Mit dem im Asset-Katalog enthaltenen und für eine Plattform gekennzeichneten Bildmaterial kann der App Store nur das bereitstellen, was für die Installation erforderlich ist.
So wie ich das lese, erhalten Downloader Ihrer App, wenn Sie Bitcode unterstützen, nur die kompilierte Architektur, die für ihr eigenes Gerät erforderlich ist.