Risposte:
Bitcode si riferisce al tipo di codice: "LLVM Bitcode" che viene inviato a iTunes Connect. Ciò consente ad Apple di utilizzare determinati calcoli per riottimizzare ulteriormente le app (ad esempio: eventualmente ridimensionare le dimensioni degli eseguibili). Se Apple deve modificare il tuo eseguibile, può farlo senza caricare una nuova build.
Ciò differisce da: Slicing che è il processo di ottimizzazione della tua app per il dispositivo di un utente in base alla risoluzione e all'architettura del dispositivo. L'affettatura non richiede Bitcode. (Es: includendo solo @ 2x immagini su un 5s)
Il diradamento delle app è la combinazione di risorse di taglio, bitcode e su richiesta
Bitcode è una rappresentazione intermedia di un programma compilato. Le app caricate su iTunes Connect che contengono bitcode verranno compilate e collegate su App Store. L'inclusione di bitcode consentirà ad Apple di ottimizzare nuovamente il file binario della tua app in futuro senza la necessità di inviare una nuova versione della tua app allo store.
Secondo i documenti :
Bitcode è una rappresentazione intermedia di un programma compilato. Le app caricate su iTunes Connect che contengono bitcode verranno compilate e collegate su App Store. L'inclusione di bitcode consentirà ad Apple di ottimizzare nuovamente il file binario della tua app in futuro senza la necessità di inviare una nuova versione della tua app allo store.
Aggiornamento: Questa frase in "Le nuove funzionalità di Xcode 7" mi ha fatto pensare per lungo tempo che codice binario che è necessario per affettare per ridurre le dimensioni di app:
Quando archivi per l'invio all'App Store, Xcode compilerà la tua app in una rappresentazione intermedia. L'App Store quindi compilerà il bitcode negli eseguibili a 64 o 32 bit, se necessario.
Tuttavia questo non è vero, codice binario che e affettare lavoro indipendentemente: Sfogliatrici tratta di ridurre dimensioni e generando app app fascio varianti, e codice binario che è circa ottimizzazioni determinate binari. L'ho verificato controllando le architetture incluse negli eseguibili di app non bitcode e trovando che includono solo quelle necessarie.
Bitcode consente ad un altro componente di assottigliamento app chiamato Slicing di generare varianti di bundle di app con particolari eseguibili per architetture particolari, ad esempio la variante iPhone 5S includerà solo eseguibile arm64, iPad Mini armv7 e così via.
Per le app iOS, il codice di accesso è predefinito, ma facoltativo. Se fornisci bitcode, tutte le app e i framework nel bundle dell'app devono includere bitcode. Per le app watchOS e tvOS, è richiesto bitcode.
Dal riferimento Xcode 7:
L'attivazione di questa impostazione indica che la destinazione o il progetto devono generare bitcode durante la compilazione per piattaforme e architetture che lo supportano. Per le build di archivio, il codice bit verrà generato nel file binario collegato per l'invio all'app store. Per altre build, il compilatore e il linker verificheranno se il codice è conforme ai requisiti per la generazione di bitcode, ma non genererà bitcode effettivo.
Ecco un paio di link che aiuteranno a comprendere meglio Bitcode :
Dato che la domanda esatta è "cosa abilita il bitcode", vorrei fornire alcuni piccoli dettagli tecnici che ho capito finora. La maggior parte di questo è praticamente impossibile da capire con certezza al 100% fino a quando Apple non rilascia il codice sorgente per questo compilatore
Innanzitutto, il bitcode di Apple non sembra essere la stessa cosa del bytecode LLVM. Almeno, non sono stato in grado di capire alcuna somiglianza tra loro. Sembra avere un'intestazione proprietaria (inizia sempre con "xar!") E probabilmente qualche magia di riferimento del tempo di collegamento che impedisce la duplicazione dei dati. Se si scrive una stringa codificata, questa stringa verrà inserita nei dati solo una volta, anziché due volte come ci si aspetterebbe se fosse un normale codice byte LLVM.
In secondo luogo, il bitcode non viene realmente distribuito nell'archivio binario come un'architettura separata, come ci si potrebbe aspettare. Non viene spedito nello stesso modo in cui si dice che x86 e ARM sono messi in un binario (archivio FAT). Invece, usano una sezione speciale nel binario MachO specifico per l'architettura denominata "__LLVM" che viene spedita con ogni architettura supportata (cioè duplicata). Presumo che questo sia un problema con il loro sistema di compilazione e potrebbe essere risolto in futuro per evitare la duplicazione.
Codice C (compilato con clang -fembed-bitcode hi.c -S -emit-llvm
):
#include <stdio.h>
int main() {
printf("hi there!");
return 0;
}
Uscita IR LLVM:
; 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)"}
L'array di dati che si trova nell'IR cambia anche in base all'ottimizzazione e alle altre impostazioni di generazione del codice di clang. Mi è del tutto ignoto in quale formato o cosa sia.
MODIFICARE:
Seguendo il suggerimento su Twitter, ho deciso di rivisitare questo e di confermarlo. Ho seguito questo post del blog e ho usato il suo strumento di estrazione di bitcode per estrarre il file binario di Apple Archive dall'eseguibile MachO. E dopo aver estratto l'archivio Apple con l'utilità xar, ho ottenuto questo (convertito in testo con llvm-dis ovviamente)
; 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)"}
L'unica differenza notevole tra IR senza bitcode e IR con bitcode è che i nomi dei file sono stati ridotti a solo 1, 2, ecc. Per ogni architettura.
Ho anche confermato che il bitcode incorporato in un file binario viene generato dopo le ottimizzazioni. Se compili con -O3 ed estrai il bitcode, sarà diverso da se compili con -O0.
E solo per ottenere credito extra, ho anche confermato che Apple non spedisce bitcode ai dispositivi quando scarichi un'app iOS 9. Includono una serie di altre strane sezioni che non ho riconosciuto come __LINKEDIT, ma non includono il bundle __LLVM .__, e quindi non sembrano includere bitcode nell'ultimo binario che gira su un dispositivo. Stranamente, tuttavia, Apple spedisce ancora binari grassi con codice separato 32 / 64bit ai dispositivi iOS 8.
xar!
è il formato del file di archivio di Apple.
Bitcode (iOS, watchOS)
Bitcode è una rappresentazione intermedia di un programma compilato. Le app caricate su iTunes Connect che contengono bitcode verranno compilate e collegate su App Store. L'inclusione di bitcode consentirà ad Apple di ottimizzare nuovamente il file binario della tua app in futuro senza la necessità di inviare una nuova versione della tua app allo store.
Fondamentalmente questo concetto è in qualche modo simile a Java in cui il codice byte viene eseguito su diverse JVM e in questo caso il bitcode viene inserito nell'archivio iTune e invece di fornire il codice intermedio a piattaforme (dispositivi) diversi fornisce il codice compilato che non necessita qualsiasi macchina virtuale da eseguire.
Quindi dobbiamo creare il bitcode una volta e sarà disponibile per i dispositivi esistenti o futuri. È il mal di testa di Apple compilare e renderlo compatibile con ogni piattaforma che hanno.
Gli sviluppatori non devono apportare modifiche e inviare nuovamente l'app per supportare nuove piattaforme.
Facciamo l'esempio di iPhone 5s quando Apple ha introdotto il x64
chip al suo interno. Sebbene le x86
app siano totalmente compatibili con l' x64
architettura ma per utilizzare appieno la x64
piattaforma, lo sviluppatore deve modificare l'architettura o un po 'di codice. Al termine, l'app viene inviata all'app store per la revisione.
Se questo concetto di bitcode è stato lanciato in precedenza, allora gli sviluppatori non devono apportare modifiche per supportare l' x64
architettura bit.
Aggiornare
Apple ha chiarito che lo slicing si verifica indipendentemente dall'abilitazione del bitcode. L'ho osservato anche in pratica dove un'app abilitata senza bitcode verrà scaricata solo come architettura appropriata per il dispositivo di destinazione.
Originale
Codice binario che. Archivia l'app per l'invio all'App Store in una rappresentazione intermedia, che viene compilata in eseguibili a 64 o 32 bit per i dispositivi di destinazione al momento della consegna.
Affettare. Le opere d'arte incorporate nel Catalogo risorse e contrassegnate per una piattaforma consentono all'App Store di fornire solo ciò che è necessario per l'installazione.
Il modo in cui leggo questo, se supporti bitcode, i downloader della tua app otterrà solo l'architettura compilata necessaria per il proprio dispositivo.