Réponses:
Bitcode fait référence au type de code: "LLVM Bitcode" qui est envoyé à iTunes Connect. Cela permet à Apple d'utiliser certains calculs pour réoptimiser davantage les applications (par exemple: éventuellement réduire la taille des exécutables). Si Apple doit modifier votre exécutable, il peut le faire sans télécharger une nouvelle version.
Cela diffère de: le découpage qui est le processus d'Apple optimisant votre application pour l'appareil d'un utilisateur en fonction de la résolution et de l'architecture de l'appareil. Le découpage ne nécessite pas de Bitcode. (Ex: n'incluant que les images @ 2x sur un 5s)
L'App Thinning est la combinaison de ressources de découpage, de bitcode et à la demande
Bitcode est une représentation intermédiaire d'un programme compilé. Les applications que vous téléchargez sur iTunes Connect qui contiennent du code bitmap seront compilées et liées sur l'App Store. L'inclusion de bitcode permettra à Apple de ré-optimiser votre binaire d'application à l'avenir sans avoir à soumettre une nouvelle version de votre application au magasin.
Selon les documents :
Bitcode est une représentation intermédiaire d'un programme compilé. Les applications que vous téléchargez sur iTunes Connect qui contiennent du code bitmap seront compilées et liées sur l'App Store. L'inclusion de bitcode permettra à Apple de ré-optimiser votre binaire d'application à l'avenir sans avoir à soumettre une nouvelle version de votre application au magasin.
Mise à jour: Cette phrase dans "Nouvelles fonctionnalités de Xcode 7" m'a fait penser pendant longtemps que Bitcode est nécessaire pour que Slicing réduise la taille de l'application:
Lorsque vous archivez pour soumission à l'App Store, Xcode compilera votre application dans une représentation intermédiaire. L'App Store compilera ensuite le code bit dans les exécutables 64 ou 32 bits si nécessaire.
Cependant, ce n'est pas vrai, Bitcode et Slicing fonctionnent indépendamment: Slicing consiste à réduire la taille de l'application et à générer des variantes de bundle d'applications, et Bitcode concerne certaines optimisations binaires. J'ai vérifié cela en vérifiant les architectures incluses dans les exécutables des applications non-bitcode et en constatant qu'elles n'en incluent que les nécessaires.
Bitcode permet à un autre composant App Thinning appelé Slicing de générer des variantes de bundle d'applications avec des exécutables particuliers pour des architectures particulières, par exemple, la variante iPhone 5S inclura uniquement l'exécutable arm64, l'iPad Mini armv7, etc.
Pour les applications iOS, le bitcode est la valeur par défaut, mais facultatif. Si vous fournissez un bitcode, toutes les applications et tous les frameworks du bundle d'applications doivent inclure le bitcode. Pour les applications watchOS et tvOS, un bitcode est requis.
De la référence Xcode 7:
L'activation de ce paramètre indique que la cible ou le projet doit générer un bitcode lors de la compilation pour les plates-formes et architectures qui le prennent en charge. Pour les builds d'archives, le bitcode sera généré dans le binaire lié pour être soumis à l'App Store. Pour les autres builds, le compilateur et l'éditeur de liens vérifieront si le code est conforme aux exigences pour la génération de bitcode, mais ne générera pas de bitcode réel.
Voici quelques liens qui vous aideront à mieux comprendre Bitcode :
Étant donné que la question exacte est "qu'est-ce que permet le bitcode", je voudrais donner quelques détails techniques minces que j'ai compris jusqu'à présent. La plupart de cela est pratiquement impossible à comprendre avec 100% de certitude jusqu'à ce qu'Apple publie le code source de ce compilateur
Tout d'abord, le bitcode d'Apple ne semble pas être la même chose que le bytecode LLVM. Au moins, je n'ai pas pu trouver de ressemblance entre eux. Il semble avoir un en-tête propriétaire (commence toujours par "xar!") Et probablement une magie de référence au moment du lien qui empêche les duplications de données. Si vous écrivez une chaîne codée en dur, cette chaîne ne sera insérée dans les données qu'une seule fois, plutôt que deux comme on pourrait s'y attendre si c'était un bytecode LLVM normal.
Deuxièmement, le bitcode n'est pas vraiment livré dans l'archive binaire en tant qu'architecture distincte comme on pourrait s'y attendre. Il n'est pas livré de la même manière que disons que x86 et ARM sont mis dans un seul binaire (archive FAT). Au lieu de cela, ils utilisent une section spéciale dans le binaire MachO spécifique à l'architecture nommée "__LLVM" qui est livrée avec chaque architecture prise en charge (c'est-à-dire dupliquée). Je suppose que c'est un court terme avec leur système de compilation et peut être corrigé à l'avenir pour éviter la duplication.
Code C (compilé avec clang -fembed-bitcode hi.c -S -emit-llvm
):
#include <stdio.h>
int main() {
printf("hi there!");
return 0;
}
Sortie 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)"}
Le tableau de données qui se trouve dans l'IR change également en fonction de l'optimisation et d'autres paramètres de génération de code de clang. Je ne sais absolument pas dans quel format ou quoi que ce soit.
ÉDITER:
Suite à l'allusion sur Twitter, j'ai décidé de revisiter cela et de le confirmer. J'ai suivi ce billet de blog et utilisé son outil d'extraction de bitcode pour extraire le binaire Apple Archive de l'exécutable MachO. Et après avoir extrait les archives Apple avec l'utilitaire xar, j'ai obtenu ceci (converti en texte avec llvm-dis bien sûr)
; 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)"}
La seule différence notable entre l'IR non-bitcode et l'IR bitcode est que les noms de fichiers ont été supprimés à seulement 1, 2, etc. pour chaque architecture.
J'ai également confirmé que le bitcode incorporé dans un binaire est généré après optimisations. Si vous compilez avec -O3 et extrayez le bitcode, ce sera différent de si vous compilez avec -O0.
Et juste pour obtenir un crédit supplémentaire, j'ai également confirmé qu'Apple n'envoie pas de bitcode aux appareils lorsque vous téléchargez une application iOS 9. Ils incluent un certain nombre d'autres sections étranges que je ne reconnais pas comme __LINKEDIT, mais ils n'incluent pas le bundle __LLVM .__, et ne semblent donc pas inclure le code bit dans le binaire final qui s'exécute sur un périphérique. Curieusement, Apple expédie toujours de gros fichiers binaires avec un code 32 / 64bit séparé aux appareils iOS 8.
xar!
est le format de fichier d'archive d'Apple.
Bitcode (iOS, watchOS)
Bitcode est une représentation intermédiaire d'un programme compilé. Les applications que vous téléchargez sur iTunes Connect qui contiennent du code bitmap seront compilées et liées sur l'App Store. L'inclusion de bitcode permettra à Apple de ré-optimiser votre binaire d'application à l'avenir sans avoir à soumettre une nouvelle version de votre application au magasin.
Fondamentalement, ce concept est quelque peu similaire à java où le code d'octet est exécuté sur différentes machines virtuelles Java et dans ce cas, le bitcode est placé sur iTune Store et au lieu de donner le code intermédiaire à différentes plates-formes (appareils), il fournit le code compilé qui n'a pas besoin n'importe quelle machine virtuelle à exécuter.
Nous devons donc créer le bitcode une fois et il sera disponible pour les appareils existants ou à venir. C'est le casse-tête d'Apple de compiler et de le rendre compatible avec chaque plate-forme qu'ils ont.
Les développeurs n'ont pas à apporter de modifications ni à soumettre à nouveau l'application pour prendre en charge de nouvelles plateformes.
Prenons l'exemple de l'iPhone 5 lorsque Apple y a introduit une x64
puce. Bien que les x86
applications soient totalement compatibles avec l' x64
architecture, mais pour utiliser pleinement la x64
plate-forme, le développeur doit changer l'architecture ou du code. Une fois terminé, l'application est soumise à l'App Store pour examen.
Si ce concept de bitcode a été lancé plus tôt, nous, les développeurs, n'avons pas à apporter de modifications pour prendre en charge l' x64
architecture bit.
Mettre à jour
Apple a précisé que le découpage se produit indépendamment de l'activation du bitcode. J'ai également observé cela dans la pratique où une application non compatible bitcode ne sera téléchargée qu'en tant qu'architecture appropriée pour le périphérique cible.
Original
Bitcode. Archivez votre application pour la soumettre à l'App Store dans une représentation intermédiaire, qui est compilée en exécutables 64 ou 32 bits pour les appareils cibles lors de la livraison.
Tranchage. Les illustrations incorporées au catalogue d'actifs et balisées pour une plate-forme permettent à l'App Store de fournir uniquement ce qui est nécessaire pour l'installation.
La façon dont je lis cela, si vous prenez en charge le bitcode, les téléchargeurs de votre application obtiendront uniquement l'architecture compilée nécessaire pour leur propre appareil.