Rust: Prend en charge le code binaire de l'App Store d'Apple

Créé le 24 août 2016  ·  89Commentaires  ·  Source: rust-lang/rust

Bitcode est l'avenir de la distribution d'applications d'Apple et nous ne le prenons pas en charge actuellement. Cela est délicat car Apple choisit la version de LLVM qu'il souhaite et la met à niveau selon ses caprices. Nous ne pouvons pas coupler notre LLVM au leur car nous avons nos propres besoins et ne pouvons pas être obligés de mettre à niveau chaque fois qu'Apple le décide.

Voici quelques options :

  • Nous livrons une chaîne d'outils entièrement distincte pour cibler le bitcode Apple. C'est assez laid.
  • Nous modifions rustc pour charger dynamiquement LLVM, créons un package rust-llvm et un package optionnel rust-llvm-apple, et demandons à rustc de charger le LLVM apple pour gérer leur bitcode.
  • Nous créons une caisse rustc_llvm_apple et lions simplement deux LLVM entiers dans rustc à tout moment. Cela ne volerait probablement pas
  • Nous créons une version de rustc appelée rustc-apple et l'expédions dans un package optionnel rustc-apple. C'est exactement comme rustc sauf qu'au lieu d'être lié à rustc_llvm, il est lié à rustc_llvm_apple. Lorsque rustc reçoit une demande d'émission de bitcode, il s'en remet complètement au binaire rustc-apple. En fait, j'aime beaucoup cette solution.
  • Nous pourrions enquêter sur un désinfectant de bitcode pour traduire notre bitcode en le leur. Je pense que la probabilité de succès ici est faible à cause de la maintenance. Je crois que RenderScript fait cela.

Je pense que les solutions de chargement dynamique LLVM et de report vers une rouille alternative sont les plus prometteuses.

cc https://users.rust-lang.org/t/ios-rust-integration/6928/4

cc @bluejekyll

A-LLVM A-rustbuild C-enhancement E-hard O-ios T-compiler T-dev-tools

Commentaire le plus utile

J'ai réussi à lier rustc nightly-2019-09-05 aarch64-apple-ios and rustflags = "-C lto -Z embed-bitcode" staticlib avec l'application clang-1100.0.33.5 (Xcode 11 beta 7) and -fembed-bitcode . Le code source est https://github.com/saturday06/rust-ios-bitcode-test .

Tous les 89 commentaires

Nous modifions rustc pour charger dynamiquement LLVM, créons un package rust-llvm et un package optionnel rust-llvm-apple, et demandons à rustc de charger le LLVM apple pour gérer leur bitcode.

Le chargement dynamique de LLVM n'est certainement pas une option. L'API LLVM est moins stable que son bitcode et, si nous construisons avec LLVM xy, alors avoir LLVM xz au lieu de xy brisera presque certainement rustc. Connectez-vous simplement au système LLVM de manière statique (comme le fait déjà --llvm-root ).

Nous créons une caisse rustc_llvm_apple et lions simplement deux LLVM entiers dans rustc à tout moment. Cela ne volerait probablement pas

Il suffit de lier le système LLVM (statiquement) pour les distributions Apple. D'après mon expérience, cela fonctionne déjà plutôt bien.

Nous pourrions enquêter sur un désinfectant de bitcode pour traduire notre bitcode en le leur. Je pense que la probabilité de succès ici est faible à cause de la maintenance. Je crois que RenderScript fait cela.

D'accord… alors, le fait est que le format de bitcode LLVM est plutôt stable entre les versions de LLVM. Apple fait-il quelque chose d'inhabituel pour que cela ne soit pas vrai, ou le format bitcode utilisé n'est-il pas complètement LLVM (c'est-à-dire qu'il contient des éléments spécifiques à Apple) ?


J'ai l'impression d'avoir entendu depuis 2013 que l'utilisation du bitcode LLVM comme format de distribution est stupide. Je suis certainement d'accord; la distribution de bibliothèques binaires natives ne fonctionne plus pour iOS ?

Je suis également très intéressé par ce qui se passerait lorsque Apple passerait à la version LLVM avec un format bitcode incompatible en interne et que les gens compileraient toujours des trucs avec d'anciens compilateurs.

J'ai brièvement expérimenté cela, c'est-à-dire produire du bitcode pendant les constructions de fret, puis j'ai essayé de créer une bibliothèque statique avec le bitcode inclus. Lorsque j'ai essayé de lier llvm à la bibliothèque bitcode, j'ai obtenu une version LLVM incompatible à partir du bitcode.

Je n'ai pas de test facile pour reproduire cela, mais je suppose qu'il n'y a qu'une vérification de version stupide qui nie la liaison entre les différentes versions de LLVM ? Ou, j'ai juste fait quelque chose de complètement faux. J'essaierai de proposer un cas de test lorsque j'aurai le temps de revoir cela.

Il serait utile d'avoir le message d'erreur exact de llvm-link.

@bluejekyll LLVM a un certain nombre de fichiers bitcode dans son répertoire de test. Les tests sur ces fichiers bitcode sont exécutés en continu (llvm-dis-3.8/opt-3.8 comprend très bien un fichier bitcode de 3 ans à partir de 3.2, par exemple), il doit donc s'agir de quelque chose d'Apple.

Il suffit de lier le système LLVM (statiquement) pour les distributions Apple. D'après mon expérience, cela fonctionne déjà plutôt bien.

C'est un peu plus facile à dire qu'à faire - pour autant que je sache, la seule version d'apple-llvm bénie pour les téléchargements sur l'App Store est celle livrée avec le Xcode actuel. Cela signifie également potentiellement maintenir les liaisons LLVM pour deux versions LLVM (pas nécessairement deux versions mineures voisines non plus). Je ne pense pas qu'il soit valable d'utiliser simplement une ancienne version d'apple-llvm.

Je suis également très intéressé par ce qui se passerait lorsque Apple passerait à la version LLVM avec un format bitcode incompatible en interne et que les gens compileraient toujours des trucs avec d'anciens compilateurs.

Je pense qu'ils évitent cela en autorisant uniquement le dernier Xcode à soumettre des applications (et je suis presque sûr qu'il est gravé dans l'image de sortie de la version LLVM que vous avez utilisée).

IIRC, le bitcode est empaqueté pour chaque architecture, car le bitcode inter-architecture n'est pas généré par clang (je pense que c'est un anti-objectif de clang et de bitcode en général). Il est stocké dans une section pour chaque fichier objet, il est donc au moins dupliqué. Cela pourrait expliquer en partie pourquoi quelqu'un a mentionné que le bitcode n'était peut-être pas la meilleure façon de procéder.

J'ai un peu l'impression que toutes les solutions recommandées sont un peu dégoûtantes. La façon la moins compliquée à laquelle je puisse penser est de permettre à différentes cibles de surcharger le comportement de codegen et d'avoir le chemin de codegen Apple dans une caisse dynamique. (Ce qui serait juste le chemin de codegen standard compilé avec apple-llvm.)

Étant donné que ce bogue mentionne l'App Store, cela vaut-il la peine de parler ici de l'histoire de la gestion des exceptions ? (c'est- panic=abort dire que

LLVM a un certain nombre de fichiers bitcode dans son répertoire de test. Les tests sur ces fichiers bitcode sont exécutés en continu (llvm-dis-3.8/opt-3.8 comprend très bien un fichier bitcode de 3 ans à partir de 3.2, par exemple), il doit donc s'agir de quelque chose d'Apple.

@nagisa merci de me l'avoir fait savoir. Cela me donne l'espoir qu'il pourrait encore y avoir une solution ici, et que je faisais probablement quelque chose de mal.

@ricky26 bons points.

pour autant que je sache, la seule version bénie d'apple-llvm pour les téléchargements sur l'App Store est celle livrée avec le Xcode actuel.

Xcode LLVM sur Apple n'est-il pas la même chose que le système LLVM ? Je voulais dire le Xcode LLVM alors. Nous devrions nous assurer que xcode est toujours la version la plus récente lors de l'expédition de trains rustc.

Bien sûr, la façon dont Apple fait les choses nous exclut de produire un bitcode Apple valide avec une ancienne version de rustc et nous oblige essentiellement à jeter tous les avantages que notre histoire de stabilité offre par la fenêtre, et je ne vois aucun moyen de résoudre ce problème.

Cela signifie également potentiellement maintenir les liaisons LLVM pour deux versions LLVM

Nous maintenons déjà la prise en charge des versions LLVM 3.7 à 3.9 (et potentiellement du tronc). Tant que le LLVM de Xcode n'est pas une version ancienne, je pense que nous sommes bons à cet égard. Si Xcode LLVM est vraiment une version ancienne/personnalisée/etc, alors je ne pense pas que nous puissions du tout prendre en charge cette fonctionnalité. D'autant plus que nous n'avons pas la possibilité d'envoyer des correctifs à _that_ LLVM afin d'ajouter les fonctionnalités dont nous avons besoin. Je ne voudrais pas non plus verrouiller Rustc à prendre en charge 3.7 pour toujours au cas où Apple déciderait de ne pas mettre à jour Xcode LLVM avant 2038.

: cependant, si rustc a été construit contre LLVM xy, il doit être lié exactement à LLVM xy.

Le chargement dynamique de LLVM n'est certainement pas une option. L'API LLVM est moins stable que son bitcode et, si nous construisons avec LLVM xy, alors avoir LLVM xz au lieu de xy brisera presque certainement rustc. Connectez-vous simplement au système LLVM de manière statique (comme le fait déjà --llvm-root).

@nagisa L'API C++ est instable, mais nous utilisons l'API C et avons eu beaucoup de succès en prenant en charge plusieurs versions de LLVM à la fois. Je ne vois pas la différence en termes de support API.

Il suffit de lier le système LLVM (statiquement) pour les distributions Apple. D'après mon expérience, cela fonctionne déjà plutôt bien.

Nous pourrions simplement expédier le LLVM d'Apple pour toutes les plates-formes Apple, mais cela signifie coupler notre LLVM à Apple pour même la génération de code machine de bureau, et exclut la possibilité de prendre en charge le bitcode iOS sur des hôtes non Apple.

D'accord… alors, le fait est que le format de bitcode LLVM est plutôt stable entre les versions de LLVM. Apple fait-il quelque chose d'inhabituel pour que cela ne soit pas vrai, ou le format bitcode utilisé n'est-il pas complètement LLVM (c'est-à-dire qu'il contient des éléments spécifiques à Apple) ?

Le format bitcode n'est pas stable entre les versions.

la distribution de bibliothèques binaires natives ne fonctionne plus pour iOS ?

Cela fonctionne aujourd'hui. Ce n'est pas la méthode préférée et il n'est pas évident qu'elle continuera à être prise en charge.

Cela signifie également potentiellement maintenir les liaisons LLVM pour deux versions LLVM (pas nécessairement deux versions mineures voisines non plus). Je ne pense pas qu'il soit valable d'utiliser simplement une ancienne version d'apple-llvm.

@ricky26 Nous

Tant que le LLVM de Xcode n'est pas une version ancienne, je pense que nous sommes bons à cet égard.

Depuis cette page https://gist.github.com/yamaya/2924292 :

clang-700.0.72 => LLVM 3.7.0
clang-700.1.76 => LLVM 3.7.0
clang-700.1.81 => LLVM 3.7.0
clang-703.0.29 => LLVM 3.8.0
clang-703.0.31 => LLVM 3.8.0

L'API C++ est instable, mais nous utilisons l'API C et avons eu beaucoup de succès en prenant en charge plusieurs versions de LLVM à la fois. Je ne vois pas la différence en termes de support API.

Ce n'est pas vrai. Nous avons (assez grand !) un certain nombre de liaisons aux API C++ sous la forme de rustllvm. Il existe un certain nombre de cas où nous compilons ce wrapper en fonction de la version de LLVM compilée. Si la version de LLVM utilisée et compilée ne correspond pas, vous obtiendrez des erreurs d'éditeur de liens dynamiques, ou pire, des problèmes lors de l'exécution.

exclut la possibilité de prendre en charge le bitcode iOS sur des hôtes non Apple.

Si Apple ne veut pas utiliser le bitcode généré par autre chose que son fork de LLVM, alors je ne vois pas comment nous pourrions faire quoi que ce soit ici à part maintenir un fork similaire et faire de la rétro-ingénierie de leurs correctifs internes.

Le format bitcode n'est pas stable entre les versions.

Bien sûr, mais il est tout à fait juste de supposer que le bitcode entre différentes révisions de LLVM, connu sous le nom de 3.7.0, par exemple, est suffisamment compatible pour générer du bitcode destiné à être consommé par une autre version de LLVM de la série 3.7.0. C'est certainement mieux que de se lier dynamiquement à libLLVM.

¹ : d'autant plus que le bitcode de la série 3.2 est toujours compatible avec 3.8 LLVM, même s'il s'agit d'un très petit spécimen.

Quelques notes:

  • Xcode n'est même pas livré avec une libLLVM pouvant être reliée (statique ou dynamique), seulement une libclang.dylib qui se lie statiquement à LLVM.
  • Apple envoie la source à son « clang » (y compris LLVM) sous « Outils de développement » sur https://opensource.apple.com , mais ce site a tendance à prendre une éternité pour être mis à jour.
  • L'histoire est peut-être meilleure avec Swift, qui a son propre fork de LLVM avec des balises de version - mais elles peuvent ne pas correspondre parfaitement à ce qui est livré avec Xcode. (Il est possible d'utiliser des instantanés de chaînes d'outils open source avec Xcode, mais les projets construits avec de telles chaînes d'outils ne peuvent pas être soumis à l'App Store.)

cc @rust-lang/compilateur

Je serais curieux de savoir comment les autres langages de programmation prévoient de gérer cela. En particulier mono et c'est parti.

La réponse de Unity à ce problème est il2cpp - en construisant tous leurs assemblys IL dans du code C++.

Bogue de golang pertinent : https://github.com/golang/go/issues/12682 ; la suggestion semble être qu'ils pourraient utiliser la chaîne d'outils go LLVM (qui n'est pas aussi présente que la chaîne d'outils go standard).

Dans l'ensemble, l'histoire de la prise en charge du bitcode en dehors d'Apple est médiocre.

Mono proprement dit passe par apple LLVM il semblerait : http://tirania.org/blog/archive/2015/Sep-02.html

Une pierre d'achoppement sera que vous ne pouvez pas effectuer d'assemblage en ligne en bitcode :(

Pour l'histoire mono j'ai eu un échange rapide avec Miguel de Icaza sur ce que fait Mono pour les curieux : https://twitter.com/mitsuhiko/status/769458873237434368

@mitsuhiko Vous _pouvez_ avoir un assemblage en ligne en bitcode sur iOS et tvOS, mais pas watchOS, pour une raison quelconque.

Un mouvement là-dessus ? Je ne me sens pas du tout à l'aise avec l'utilisation de Rust sur iOS sans un plan pour prendre en charge le bitcode. Apple a l'habitude de rendre des choses facultatives comme celle-ci non facultatives assez soudainement, et en effet, le bitcode est déjà requis sur watchOS et tvOS.

J'ai un peu l'impression que toutes les solutions recommandées sont un peu dégoûtantes. La façon la moins compliquée à laquelle je puisse penser est de permettre à différentes cibles de surcharger le comportement de codegen et d'avoir le chemin de codegen Apple dans une caisse dynamique. (Ce qui serait juste le chemin de codegen standard compilé avec apple-llvm.)

Cette approche (par @ricky26) me semble la plus naturelle en tant qu'utilisateur de rustc.

Je ne crois pas que quoi que ce soit ait changé à ce sujet récemment, à ma connaissance du moins. Avec l' annonce récente de LLVM sur la gestion des versions, ils ont indiqué que le bitcode devrait (je pense) toujours être chargeable par les futures versions de LLVM. Cela peut signifier que ce problème est "résolu" à un niveau fondamental, mais cela nécessiterait toujours une interface plus ergonomique pour extraire tout le bitcode.

Y a-t-il des mises à jour à ce sujet ?

Ce commentateur sur HackerNews a réussi à utiliser le Bitcode généré à partir de Rust sur macOS et iOS. Le fil contient des informations détaillées sur la façon d'activer le bitcode pour les binaires de rouille, ce qui semble être une excellente nouvelle !

https://news.ycombinator.com/item?id=14305084

En tant que commentateur en question, notes rapides :

  • J'ai utilisé -C lto --emit llvm-bc pour que rustc émette un fichier .bc contenant la caisse actuelle et toutes les dépendances. Cela fonctionne, mais est essentiellement un hack ; en particulier, cela ne fonctionne pas pour les dépendances C, y compris jemalloc (bien que cela ne soit pas utilisé sur iOS de toute façon). Il vaudrait mieux que rustc prenne en charge correctement l'émission de Mach-O avec un "bitcode intégré" ; vous pouvez regarder la source de clang pour voir comment c'est fait.

  • Si vous voulez l'essayer et que le hack ne vous dérange pas, cela semble "fonctionner", à l'exception du problème de version :

  • Le principal obstacle pratique est que Rust se synchronise plus fréquemment avec le tronc LLVM que Xcode, qui ne semble le faire que chaque année. Les versions plus récentes de LLVM peuvent charger l'ancien bitcode, mais pas l'inverse, vous devez donc soit utiliser une ancienne version de rustc, soit créer la dernière contre un ancien LLVM. (En fait, rustc 1.17 semble toujours fonctionner avec Xcode 8.x, mais pas tous les soirs depuis la mise à niveau de LLVM 4.0 ; ce n'est qu'une coïncidence cependant.)

  • Idéalement, Rust expédierait des binaires officiels construits avec une version LLVM appropriée. En pratique, il semble bien d'utiliser la bonne version de LLVM d'origine, mais si vous souhaitez utiliser le fork d'Apple :

    • Comme je l'ai dit dans un commentaire précédent, Xcode ne fournit pas de binaires LLVM sous aucune forme pouvant être liée, même dynamiquement ; uniquement clang et libclang.dylib (qui exporte l'API Clang mais pas celle LLVM).
    • Mais, comme je l'ai également dit, le code source monte généralement sur opensource.apple.com (sous Outils de développement -> clang ; l'archive inclut tout LLVM), juste de manière quelque peu incohérente/après un délai. Cependant, surtout compte tenu des garanties de compatibilité ascendante étendues notées par @alexcrichton , ce n'est peut-être pas la fin du monde de ne pas toujours être à jour. Actuellement, la version source la plus récente concerne Xcode 8.2.1, tandis que la dernière est la 8.3.2.

(À titre de test, je viens d'essayer de compiler Rust avec Xcode 8.2.1 Clang. rustllvm ne parvient pas à compiler, car son nid de #if LLVM_VERSION_GE(..) conditionnels, qui sont censés lui permettre de compiler avec les deux LLVM plus ancien et plus récent, est confus par cette branche - qui prétend être LLVM 3.9svn, mais au niveau de l'API se situe quelque part entre 3.8 et 3.9. Cela ne vaut probablement pas la peine d'être corrigé, car Xcode est presque dû pour sa prochaine actualisation annuelle de toute façon.)

Des progrès ont-ils été réalisés sur ce front ? Sinon, est-ce que vous (équipe principale) considéreriez cette épreuve comme un problème avec un correctif permanent solide en vue ou vous attendez-vous à ce que ce changement de version reste dans un avenir prévisible ?

J'envisage d'implémenter des parties d'une application iOS dans Rust pour son système de type supérieur et sa sémantique de bas niveau et je préfère ne pas être coincé avec des hacks/retards non-bitcode ou réguliers chaque fois qu'il y a une mise à jour pour Xcode ou rustc.

@regexident

Je pense que nous allons implémenter des versions LLVM échangeables pour d'autres raisons. Si cela est mis en œuvre, nous ne devrions pas avoir de problème à expédier des trans séparément pour Apple, wasm et tout le reste.

cc #45684

Le bitcode d'Apple n'est-il pas encore vraiment dangereux ala https://medium.com/@FredericJacobs/why -im-not-enabling-bitcode-f35cd8fbfcc5 Impossible de vérifier les builds. Problèmes de cryptographie. etc.

@burges Pour certaines applications, c'est absolument un problème.

Mais pour watchOS et tvOS, Apple a en fait besoin de Bitcode pour les soumissions sur l'App Store. Vous n'avez pas le choix. À part "ne pas faire de crypto ou de trucs critiques sur ces plates-formes". Il faut également craindre qu'Apple applique Bitcode pour iOS à un moment donné dans le futur. Je préférerais ne pas avoir de produit en brique à ce stade.

J'ai essayé de construire avec Rust 1.24.0 pour iOS en utilisant l'astuce -C lto --emit=llvm-bc , mais l'éditeur de liens a donné les erreurs suivantes :

Undefined symbols for architecture x86_64:
  "_backtrace_create_state", referenced from:
      std::sys_common::gnu::libbacktrace::init_state::h686c3e443c712b0f in Logger(x86_64.o)
  "_backtrace_syminfo", referenced from:
      std::panicking::default_hook::_$u7b$$u7b$closure$u7d$$u7d$::h598a932d5bb0d80b in Logger(x86_64.o)
      core::iter::iterator::Iterator::position::_$u7b$$u7b$closure$u7d$$u7d$::hbf03153d55553502 in Logger(x86_64.o)
  "_backtrace_pcinfo", referenced from:
      std::panicking::default_hook::_$u7b$$u7b$closure$u7d$$u7d$::h598a932d5bb0d80b in Logger(x86_64.o)
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

Des idées quel pourrait être le problème?

Edit : il semble que je puisse au moins supprimer ce problème en enveloppant tout le code dans chaque fn externe public avec AssertUnwindSafe

libbacktrace est une bibliothèque C qui est incluse dans l'arborescence des sources de Rust :

https://github.com/rust-lang/rust/tree/master/src/libbacktrace

Vous devrez compiler cela en tant que bitcode d'une manière ou d'une autre.

Je suis confus, car je ne peux trouver qu'un libbacktrace conçu pour mon ordinateur portable, mais pas pour le système d'exploitation du téléphone. Comment rust insère-t-il ces symboles dans la stdlib ? Existe-t-il un moyen plus simple de le faire en désactivant d'une manière ou d'une autre la fonctionnalité de traçage ? J'ai supprimé la variable d'environnement RUST_BACKTRACE mais cela n'a pas aidé. J'ai lu que vous pouvez compiler rustc sans backtraces, mais j'espérais quelque chose de plus simple, par exemple dans le fichier cargo.toml de mon projet

Fondamentalement, vous voulez construire l'arbre source de rustc tout en lui disant de passer -fembed-bitcode au compilateur C. Idéalement, vous pourriez simplement l'ajouter à CFLAGS ; malheureusement, je viens d'essayer, et cela n'a pas fonctionné correctement en raison de deux problèmes avec gcc-rs (utilisé par le système de construction de rustc pour créer des dépendances C). Cependant, je l'ai fait fonctionner avec une procédure un peu bidon:

cd /tmp/build
cat >ccwrap.py <<END

#!/usr/bin/env python
import os, sys
os.execv('/usr/bin/xcrun', ['clang', '-fembed-bitcode'] + [arg for arg in sys.argv[1:] if arg not in {'-ffunction-sections', '-fdata-sections'}])

END

chmod 755 ccwrap.py
ln -s /usr/bin/ar ar
export CC_aarch64_apple_ios=`pwd`/ccwrap.py
/usr/src/rust/configure --target=aarch64-apple-ios
make

Cela devrait vous rapporter un libbacktrace.a (en ./build/aarch64-apple-ios/native/libbacktrace/.libs/ ) avec bitcode intégré. __LLVM,__bitcode de ce qui sont par ailleurs des bibliothèques natives, de la même manière que clang : alors il n'y aurait pas besoin de compiler et de lier manuellement les fichiers .bc.

(En fait, étant donné que l'erreur que vous avez citée ressemble à une erreur normale de l'éditeur de liens, je pense que vous pouvez la surmonter simplement en liant un libbacktrace.a régulier et sans bitcode. Mais au mieux, cela donnerait un fichier de sortie avec un bitcode intégré cassé.)

Les problèmes susmentionnés :

  • gcc-rs transmet -ffunction-sections et -fdata-sections sans aucun moyen de les désactiver ; clang s'en plaint lorsqu'il est combiné avec -fembed-bitcode (même si -fno-function-sections est passé plus tard).

J'ai déposé un rapport de problème et, comme solution de contournement, la procédure ci-dessus utilise un script wrapper qui supprime ces arguments. Mais cela a causé un deuxième problème:

  • gcc-rs essaie de trouver ar dans le même répertoire que CC_aarch64_apple_ios (!?); le réglage manuel de AR_aarch64_apple_ios n'a eu aucun effet

Je n'ai pas pu reproduire cela avec le dernier cc-rs (renommé de gcc-rs ), donc je n'ai pas déposé de problème. Pour contourner le problème, la procédure ci-dessus crée des liens symboliques ar dans le même répertoire.

Merci pour les suggestions ! En fait, j'avais juste besoin de bitcode pour mon propre code, pas pour le backtrace, donc j'ai juste utilisé la libbacktrace compilée sans aucune intégration de bitcode

Avec le hack que j'ai essayé, je rencontre maintenant un autre problème : dsymutil segfaults lorsque j'essaie de créer un dSYM pour cela. L'exécution normale sans dSYM fonctionne bien, mais la création dSYM est interrompue pour une raison quelconque. J'ai supprimé ma libbacktrace.a, je l'ai remplacée par des fonctions d'espace réservé vides, et tout a bien fonctionné, il semble donc qu'il y ait un problème avec ma bibliothèque de rouille.

Cela ressemble à un bogue dans dsymutil, qui devrait être signalé en amont à LLVM. Pouvez-vous essayer d'exécuter dsymutil sous LLDB et de publier une trace du crash ? Ou pour obtenir de meilleures informations de débogage, vous pouvez essayer de créer LLVM en mode débogage et de le reproduire avec cela.

(Notez que le binaire dans une installation LLVM d'origine s'appelle llvm-dsymutil , mais de nos jours, le dsymutil Xcode n'est qu'un lien symbolique vers llvm-dsymutil . dsymutil était autrefois un utilitaire source distinct et fermé, mais pendant quelques années, cette version a été expédiée sous le nom dsymutil-classic et n'est pas utilisée par défaut.)

@comex par curiosité, la caisse de cc devrait-elle tout compiler avec -fembed-bitcode ? Ou si nous utilisons le clang "officiel", est-il possible d'éviter d'intégrer le bitcode ?

(désolé, je ne connais pas très bien les bonnes pratiques ios !)

Pour le code Rust lui-même, serait-il préférable d'émettre simplement du bytecode au lieu de fichiers objets ? Est-ce quelque chose que Clang/l'éditeur de liens peut comprendre ?

@alexcrichton

la caisse cc devrait-elle tout compiler avec -fembed-bitcode ? Ou si nous utilisons le clang "officiel", est-il possible d'éviter d'intégrer le bitcode ?

L'utilisation du clang officiel n'élimine pas le besoin de bitcode intégré. Au lieu de cela, le bitcode est inclus - en plus du code natif - dans l'archive d'application téléchargée sur Apple, puis Apple peut le recompiler côté serveur, par exemple pour l'optimiser pour différentes microarchitectures.

Il serait probablement logique de transmettre -fembed-bitcode par défaut sur iOS/watchOS/tvOS. Si c'est le cas, lors de la construction en mode débogage, -fembed-bitcode-marker doit être passé (à la place ou en plus, cela n'a pas d'importance) ; cela indique à clang de n'inclure qu'une section de bitcode factice plutôt qu'un bitcode réel, car le bitcode intégré n'est nécessaire que pour les archives finales de l'application et il accélère légèrement la compilation pour l'omettre. En fait, Xcode passe -fembed-bitcode-marker pour tout autre que la construction de l'archive finale de l'application, même les versions de développement qui ont des optimisations - mais puisque cc n'a pas de concept distinct de "version vraiment finale mode", il devrait probablement le passer en mode débogage. Notez qu'il est sûr d'intégrer du bitcode même si la version finale ne l'exige pas.

Pour le code Rust lui-même, serait-il préférable d'émettre simplement du bytecode au lieu de fichiers objets ? Est-ce quelque chose que Clang/l'éditeur de liens peut comprendre ?

Clang et ld prennent tous les deux en charge les fichiers bitcode bruts passés en entrée ; ceci est normalement utilisé lorsque LTO est activé ( -flto ), auquel cas les fichiers .o générés par clang sont en fait du bitcode brut, pas Mach-O. (Celles-ci peuvent toujours être transformées en bibliothèques statiques à l'aide de la commande lipo normale.) Cependant, cela est distinct du format "bitcode intégré", qui consiste en un Mach-O avec un code binaire inséré dans la section __LLVM,__bitcode , dans en plus du code natif dans les sections habituelles. Ce format est utilisé dans les fichiers objet lorsque LTO est désactivé, ainsi que dans les exécutables liés finaux ou les bibliothèques dynamiques, quel que soit le paramètre LTO. (Si LTO est activé, l'éditeur de liens est responsable de la création de cette section ; si LTO est désactivé, l'éditeur de liens concatène simplement les sections __LLVM,__bitcode de chaque fichier objet comme il le ferait pour toute autre section, plutôt que de générer une seule combinaison module bitcode. ) EDIT : en fait, il fait quelque chose d'un peu plus compliqué , générant une archive xar des sections bitcode et les plaçant dans une section nommée __LLVM,__bundle ; de toute façon, pas quelque chose dont nous devons nous soucier.

Je pense qu'idéalement, rustc devrait produire un "bitcode intégré" par défaut sur iOS, pas un bitcode brut. Ce n'est pas trop difficile à faire et cela évite de casser la compilation incrémentielle - en particulier en mode débogage où vous pouvez simplement produire une section de bitcode factice, ala -fembed-bitcode-marker , mais potentiellement en mode de publication aussi, puisque l'éditeur de liens ne fait que bourrer les objets ' sections de bitcode ensemble plutôt que de faire quoi que ce soit de coûteux au moment de la liaison.

Voici comment clang génère du bitcode intégré :

https://github.com/llvm-mirror/clang/blob/master/lib/CodeGen/BackendUtil.cpp#L1242

Relativement simple - avant d'appeler le backend, il vide le module LLVM actuel en tant que bitcode, puis
les insère sous forme de données binaires dans une nouvelle variable globale (dans ce même module !), placée dans la section __LLVM,__bitcode . Cela semble être une sorte de conception bidon (pourquoi le frontend doit-il le faire manuellement ?), mais cela ne devrait pas être trop difficile à reproduire dans rustc.

@comex, cette approche a du sens, même si je pense qu'il y a des raisons (voir #48833 que je viens de créer) pour utiliser le clang d'Apple comme backend, alors que nous réfléchissons à des changements comme celui-ci. De plus, est-il facile de nous compiler à partir du bitcode intégré ?

@michaeleiselsc Désolé, je ne comprends pas ce que vous entendez par "nous compiler à partir du bitcode intégré".

Comme dans, au lieu de simplement donner un binaire à l'App Store avec le bitcode intégré, il y a aussi des avantages à prendre le bitcode et à le construire nous-mêmes en utilisant Apple clang. Deux avantages qui m'intéressent sont les correctifs en aval d'Apple clang et la possibilité d'utiliser des désinfectants de clang, par exemple le désinfectant de couverture.

@comex ok donc en creusant un peu, il semble que l'implémentation dans rustc soit assez facile (relativement), mais j'ai quelques questions :

  • Pourquoi -fembed-bitcode-marker une chose ? En utilisant clang localement, il émet simplement une statique vide dans une section. Cela signifie-t-il que la simple présence de la section signifie quelque chose? Est-ce qu'un outil le long de la route dans iOS se brise si la section n'est pas là ? (mais il ne regarde pas réellement à l'intérieur de la section parce qu'il est vide ?
  • Savez-vous si la section __cmdline est nécessaire ? Il semble que -fembed-bitcode intègre également une forme de ligne de commande dans le binaire. Je ne sais pas vraiment ce que nous mettrions ici car ce n'est probablement pas la ligne de commande de rustc, mais est-ce qu'un outil examine cela? La compilation est-elle interrompue si -fembed-bitcode=bitcode est utilisé avec iOS ?
  • Et enfin, y a-t-il une raison de vouloir désactiver cela ? Ou devrions-nous simplement l'activer inconditionnellement pour les cibles iOS et passer à autre chose ?

Pourquoi -fembed-bitcode-marker est-il une chose ?

Je pense qu'il est utilisé par xcode pour indiquer que quelque chose est censé utiliser du bitcode mais que le bitcode n'a pas été réellement compilé. Si vous essayez d'archiver un tel projet plus tard, ld échouera avec une erreur.

À la question de savoir si nous voulons toujours activer cela, il y a certainement certains cas auxquels nous voudrions faire attention. Par exemple, si quelqu'un le soumet à une plate-forme de distribution d'applications bêta comme HockeyApp, est-ce que HockeyApp supprimera cette section de code binaire, ou les bêta-testeurs devront-ils télécharger un binaire beaucoup plus volumineux que nécessaire ?

@mitsuhiko Oui, l'idée est que l'éditeur de liens peut vérifier que la version est correctement configurée pour le bitcode, même si vous testez actuellement des versions qui n'ont pas réellement besoin de bitcode.

Par exemple, si vous compilez un fichier C sans mentionner le bitcode, puis essayez de le lier avec -fembed-bitcode-marker , vous obtenez :

$ clang -c -o test.o test.c
$ clang -dynamiclib -o test.dylib test.o -fembed-bitcode-marker
ld: warning: all bitcode will be dropped because 'test.o' was built
without 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.

L'avertissement disparaît si vous passez également -fembed-bitcode-marker sur la première ligne.

@alexcrichton Quant à __cmdline … hmm… il semble que l'éditeur de liens exige sa présence (recherchez "Créer un bitcode") :

https://opensource.apple.com/source/ld64/ld64-274.2/src/ld/parsers/macho_relocatable_file.cpp.auto.html

Mais je ne vois rien qui se soucie de la valeur réelle. Il vaut probablement mieux y mettre une valeur fictive.

Ce problème a-t-il été résolu en fusionnant #48896 ?

J'ai joué avec cela sur les versions nocturnes, et cela fonctionne très bien jusqu'à ce que vous essayiez d'archiver avec Xcode. Il semble qu'il ajoute fembed-bitcode-marker mais pas fembed-bitcode à la sortie de la bibliothèque statique Rust. Il est compilé avec cargo lipo --release avec :

$ cargo --version
cargo 1.27.0-nightly (af3f1cd29 2018-05-03)
$ cargo lipo --version
cargo-lipo 2.0.0-beta-2
$ rustc --version
rustc 1.27.0-nightly (565235ee7 2018-05-07)
ld: '/Users/chrisbal/Documents/Beach/rust-universal-template/target/universal/release/libexample.a(example_generic-be72fb1769c1779b.example_generic6-152d14edfb6970f54250733c74e59b7.rs.rcgu.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. for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

Quand j'exécute otool -arch arm64 -l /Users/chrisbal/Documents/Beach/rust-universal-template/target/universal/release/libexample.a | grep bitcode j'obtiens beaucoup de sectname __bitcode , mais je ne sais pas comment vérifier s'il s'agit bien de bitcode et pas seulement de marqueurs.

J'utilise des caisses imbriquées, alors peut-être que la caisse "générique" interne n'obtient pas les drapeaux bitcode ?

edit: voici notre repo démontrant le problème https://github.com/Raizlabs/rust-universal-template/tree/879e7412d729e8963586c5b083d51b09733aec32

@chrisballinger , cela fonctionne avec un indicateur supplémentaire, voir
RUSTFLAGS="-Z embed-bitcode" cargo lipo --release

$ cargo --version
cargo 1.28.0-nightly (f352115d5 2018-05-15)
$ cargo lipo --version
cargo-lipo 2.0.0-beta-2
$ rustc --version
rustc 1.28.0-nightly (952f344cd 2018-05-18)

Mais j'ai une autre erreur de compilation uniquement pour arm7 arch :

.rs.rcgu.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. for architecture armv7

Est-ce que quelqu'un sait comment réparer arm7 arch ?

Malheureusement, je ne peux pas le faire fonctionner aussi bien, obtenant la même erreur que @chrisballinger :

ld: '/sandbox/target/universal/release/librgame.a(std-da6dba40351cda22.std3-d36cd881bae00a8b5fc36289b5737f78.rs.rcgu.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. for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

J'ai essayé de le compiler avec RUSTFLAGS="-Z embed-bitcode" cargo lipo --release et de le définir dans .cargo/config . Il ajoute cependant le drapeau :

` Executing: "cargo" "build" "--target" "x86_64-apple-ios" "--lib" "--features" "" "--color" "auto" "--release" "--verbose" Compiling libc v0.2.42 Compiling rand_core v0.2.1 Running `rustc --crate-name libc /Users/aleksandrivanov/.cargo/registry/src/github.com-1ecc6299db9ec823/libc-0.2.42/src/lib.rs --crate-type lib --emit=dep-info,link -C opt-level=3 --cfg 'feature="default"' --cfg 'feature="use_std"' -C metadata=dce309634355ac97 -C extra-filename=-dce309634355ac97 --out-dir /Users/aleksandrivanov/Sandbox/Projects/tetris/rgame/target/x86_64-apple-ios/release/deps --target x86_64-apple-ios -L dependency=/Users/aleksandrivanov/Sandbox/Projects/tetris/rgame/target/x86_64-apple-ios/release/deps -L dependency=/Users/aleksandrivanov/Sandbox/Projects/tetris/rgame/target/release/deps --cap-lints allow -Zembed-bitcode` ...

Des mises à jour ici ? Considérer fortement une bibliothèque de base partagée pour notre application et sans ce c++ fixe est l'option probable.

@chrisballinger , peut-il être lié à https://github.com/rust-lang/rust/issues/52686?

@volodg Non, ce problème date d'il y a quelque temps.

Avec la fusion de #48896, est-ce censé fonctionner immédiatement ?

Je suis sur 1.29.1 et les objets n'ont toujours pas de bitcode intégré par défaut. Comme mentionné précédemment par @volodg , vous pouvez obtenir de la rouille pour les intégrer à l'aide de RUSTFLAGS="-Z embed-bitcode" . Mais, d'après ce que j'ai vécu, vous rencontrez alors un problème où les propres bibliothèques de Rust (compiler_builtins, std) ne sont pas compilées avec embed-bitcode. Peut-être que la reconstruction des cibles iOS à l'aide de xargo avec embed-bitcode fonctionnerait, mais je n'ai pas essayé.

J'ai essayé d'utiliser xargo comme vous l'avez proposé mais le problème semble toujours être là :(

En utilisant ce Xargo.toml

[dependencies]
std = {}
[target]
features = ["jemalloc"]

En ajoutant également ceci à Cargo.toml :

[profile.release]
panic = "abort"

J'ai compilé en utilisant xargo build --release --target $TARGET pour toutes ces cibles :

  • aarch64-apple-darwin
  • armv7-apple-darwin
  • armv7s-apple-darwin
  • i386-pomme-darwin
  • x86_84-apple-darwin

Ensuite, j'ai utilisé lipo pour créer une bibliothèque statique.

J'ai toujours une erreur d'éditeur de liens :

ld: '../../cargo/target/universal/libgreetings.a(greetings-ceeec73d35f7dbe0.greetings.9kcaav8v-cgu.2.rcgu.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. for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

Un peu plus loin avec le chemin xargo.

Mon Xargo.toml

[dependencies]
std = {}

Mon Cargo.toml

[profile.release]
panic = "abort"

Je ne sais pas si c'est nécessaire, mais à partir de la doc xargo, vous devez explicitement utiliser extern crate compiler_builtins , que j'ai ajouté à mon lib.rs.

J'ai ensuite compilé avec : RUSTFLAGS="-Z embed-bitcode" xargo build --target $TARGET --release pour compiler. Assurez-vous qu'il compile core/std/compiler_bultins. xargo clean ne nettoie pas correctement les versions précédentes de ce que j'ai expérimenté, donc un rm -rf ~/.xargo était nécessaire pour recompiler std lorsque j'ai essayé différents Xargo.toml tweaks.

Mais alors, en archivant dans Xcode 10, j'obtiens (au lien armv7 ):

Intrinsic has incorrect argument type!
void (i8*, i8, i32, i1)* @llvm.memset.p0i8.i32
Intrinsic has incorrect argument type!
void (i8*, i8*, i32, i1)* @llvm.memcpy.p0i8.p0i8.i32
Intrinsic has incorrect argument type!
...
(lots of it)
...
LLVM ERROR: Broken module found, compilation aborted!
clang: error: linker command failed with exit code 1 (use -v to see invocation)

Cela signifie-t-il que le bogue dépend du LLVM ?

EDIT : Comment pourrions-nous aider à avancer dans ce dossier ?

Quelqu'un a-t-il essayé cela récemment? Il semble qu'armv7 soit le plus gros problème ?

Salut à tous. Je suis ce fil depuis un certain temps maintenant et je suis très heureux de voir que le bitcode Apple est pris en charge avec Rust. Quelqu'un a-t-il été capable jusqu'à présent de faire ce travail? Qu'est-ce qui manque actuellement et comment pourrions-nous aider?
Merci!

Après quelques heures à traquer ce problème, j'ai trouvé la raison pour laquelle l'intégration de bitcode de Rust ne fonctionne pas dans Xcode. La réponse courte est que la version LLVM de Xcode attend le bitcode LLVM 6.0 , tandis que Rust est passé à LLVM 7.0 en juillet 2018 .

Maintenant, la longue réponse...

Comme nous pouvons le voir dans le journal des modifications de LLVM 7.0, ils ont modifié les signatures pour @llvm.memcpy , @llvm.memmove et @llvm.memset , et l'erreur de construction Xcode était claire sur le mauvais type d'argument comme on le voit dans mon commentaire précédent .

Soit dit en passant, Kotlin Native a ajouté la prise en charge de l'embed-bitcode en octobre 2018 et fonctionne apparemment bien dans Xcode . La raison en est que Kotlin utilise toujours LLVM 6.0 .

Voyant cela, j'ai essayé de compiler en utilisant une ancienne version de Rust avant le passage à 7.0. J'ai essayé avec nightly-2018-06-01-x86_64-apple-darwin , et succès, ça compile !

J'ai également essayé de compiler sans utiliser Xargo sans succès. Toutes les dépendances doivent être compilées avec l'intégration de bitcode.

Donc, en fin de compte, à moins qu'Apple ne remplace sa version LLVM, je ne pense pas que nous verrons de sitôt la prise en charge du bitcode intégré... À moins que quelqu'un ne trouve un moyen astucieux de convertir le bitcode intégré en bitcode 6.0...

@appaquet Merci d'être

Merci @appaquet pour ta réponse claire. Maintenant, je suppose que nous devons juste compter sur Apple pour faire la bonne chose

Vue de côté de quelqu'un qui s'intéresse au multiplateforme pour mobile et a comparé la plupart des solutions prometteuses (React Native, Flutter, Kotlin/Native, Rust)

Réagissez natif. Prend en charge le bitcode depuis le début, car Bridge est essentiellement écrit en C++ et interprète simplement le code JS au moment de l'exécution.

Battement. Ne prend pas encore en charge le bitcode - https://github.com/flutter/flutter/issues/15288

Kotlin/Natif. JetBrains considère les plates-formes mobiles comme une priorité et bien que cela leur ait pris un certain temps et qu'il ne s'agisse que de marqueurs de bitcode (pas encore de bitcode complet), c'est assez bon pour commencer à travailler avec - voir https://github.com/JetBrains/kotlin-native/ pull/1564 et https://github.com/JetBrains/kotlin-native/issues/1202#issuecomment -444022513

Rouiller. Prend en charge le bitcode pour LLVM 7, alors qu'Apple utilise la version 6.

Si je veux avoir à la fois une logique métier et une interface utilisateur multiplateforme, j'opterais pour React Native ou Flutter. Mais pour beaucoup, beaucoup d'applications sérieuses, ce chemin est trop risqué. React Native n'est pas assez performant et la stabilité de l'API et des dépendances est un problème (la v1.0 va-t-elle jamais arriver ?). Flutter est un peu immature mais semble gagner de plus en plus de traction.

Maintenant, si je veux partager uniquement la logique métier dans un certain type de modules (comme le faisaient les grosses applications précédentes avec C++ et JNI/Obj-C++), puis créer une interface utilisateur vraiment native, au début, j'ai le choix entre les quatre. Ensuite, je raye React Native, car prendre JavaScriptCore complet et un pont pour exécuter la logique métier entre JS<->Native semble un peu exagéré (l'initialisation de ce pont est également assez chère). Flutter peut potentiellement être utilisé mais n'est pas destiné à cela , donc encore une fois, je finirais par utiliser le cadre de l'interface utilisateur pour exécuter la logique métier. De plus, il ne prend pas en charge le bitcode.
Rust et Kotlin/Native visent tous deux ce créneau, disposent d'un outillage décent, produisent du binaire natif (performances et empreinte !). Bitcode est un gros problème pour ceux qui souhaitent adopter Rust comme langage pour créer des modules multiplateformes sur des plateformes mobiles. Et maintenant Kotlin/Native a un avantage.

Pour résumer pourquoi le bitcode est très important pour les développeurs iOS. Je ne peux rien écrire sur tvOS ou watchOS. De nombreux frameworks tiers distribués sous forme de binaires ont le bitcode activé (des dizaines d'exemples, du haut de ma tête Google IMA - la publicité vidéo la plus populaire). Certains audits de sécurité l'exigent. Et enfin, chaque fois qu'Apple dit "à partir de l'année prochaine, nous n'accepterons plus d'applications sans bitcode entièrement intégré", tout le monde obtient un compte à rebours.

Maintenant, je suppose que nous devons juste compter sur Apple pour faire la bonne chose

Ouais, c'est ça, c'est pour ça qu'Apple est connu ;)
Je ne sais pas quelle serait la meilleure solution (la rétrogradation temporaire vers LLVM 6 n'est pas une option, n'est-ce pas ?), mais Rust perd complètement les développeurs iOS et multiplateformes mobiles.

Merci beaucoup pour cette explication détaillée @oleksandr-yefremov. J'ai lu un peu sur le sujet et j'ai trouvé ce commentaire intéressant : https://gist.github.com/yamaya/2924292#gistcomment -2738480

La version de LLVM est liée à la version de Swift utilisée dans XCode. Jusqu'à présent, le soutien suivant a été appliqué :

Xcode 8.3  --> swift 3.1 --> llvm 4.0.0
Xcode 9.0  --> swift 4.0 --> llvm 4.0.0
Xcode 9.3  --> swift 4.1 --> llvm 5.0.2
Xcode 10.0 --> swift 4.2 --> llvm 6.0.1

En regardant le swift-5.0-branch , j'ai remarqué que la version déclarée de LLVM est 7.0.0 : https://github.com/apple/swift-llvm/blob/swift-5.0-branch/ CMakeLists.txt#L25 -L33

Je ne sais pas s'il y a d'autres bloqueurs ici, mais il me semble que nous pourrions utiliser Rust pour produire des binaires Bitcode 🎉

Il semble que Xcode 10.2 inclura Swift 5.0 et devrait en effet être publié très bientôt. Mais d'un autre côté, LLVM 8.0 devrait sortir la semaine prochaine. Rust sera probablement mis à niveau avant qu'Apple ne commence à l'utiliser.

Pour que Rust prenne correctement en charge le bitcode, nous aurions besoin que les architectures Apple ARM de Rust utilisent une version épinglée de LLVM (peut-être à partir du référentiel https://github.com/apple/swift-llvm - Apple ne semble pas utiliser le package LLVM publié mais leurs propres branches). Cette version de LLVM ne serait mise à jour que lorsque Apple publierait une nouvelle version finale de Xcode avec une version LLVM différente.

Au fait, il semble que le dernier Rust soit constructible avec LLVM 6, ce qui semble définitivement faisable : https://github.com/rust-lang/rust/blob/master/src/bootstrap/native.rs#L282
Vous auriez certainement besoin que des personnes interviennent lorsqu'un problème est créé pour mettre à jour la version requise de LLVM (celle de LLVM 6 : https://github.com/rust-lang/rust/issues/55842).

@vincentisambart Rust utilise déjà LLVM 8 pour les builds nocturnes depuis 5 mois IIRC.
LLVM 6 est une version minimale prise en charge si vous souhaitez le construire vous-même et il est testé sur CI : https://github.com/rust-lang/rust/blob/706e67b0a0143d651eb03f2fa2c30645899e81ff/src/ci/docker/x86_64-gnu-llvm-6.0 /Dockerfile

Maintenant, je suppose que nous devons juste compter sur Apple pour faire la bonne chose

Je poursuis quelque chose dans ce sens depuis un certain temps (et je suis maintenant sorti) et je suppose que du point de vue de la plate-forme, cela n'a pas de sens pour Apple de le faire, car :

  • Swift veut être Rust de plusieurs manières (voir le manifeste de propriété pour l'un) mais est à la traîne
  • Apple a besoin que Swift soit et reste leur principal langage de plate-forme, il n'est donc pas logique qu'ils facilitent un autre grand langage sur leur plate-forme ni qu'ils poussent Swift dans d'autres environnements.

Rust utilise déjà LLVM 8 pour les builds nocturnes depuis 5 mois IIRC.

Ensuite, même si Apple commence à prendre en charge le bitcode LLVM 7, le bitcode généré par les versions officielles récentes de Rust peut ne pas fonctionner. Même si c'est le cas, cela pourrait casser la prochaine fois que Rust passera à une version de LLVM avec une modification incompatible dans le bitcode généré.

LLVM 6 est une version minimale prise en charge si vous souhaitez la construire vous-même et elle est testée sur CI

Ensuite, avoir les versions officielles *-apple-ios de Rust avec LLVM 6 (ou mieux quelque chose comme https://github.com/apple/swift-llvm/releases/tag/swift-4.2.2-RELEASE - si qui fonctionne) pourrait résoudre les problèmes de bitcode.

Je pense que Rust est actuellement livré avec deux backends LLVM (Emscripten et standard) après la fusion de https://github.com/rust-lang/rust/issues/46819.
Bien que #46819 mentionne le backend ios LLVM pour le bitcode, il n'a pas été implémenté.

Ne pas faire complètement dérailler cela, mais ne serait-il pas globalement plus logique d'essayer de permettre la transpilation en C pour de tels cas ? Il est peu probable que Rust soit en mesure de rester à jour avec les exigences de bitcode du côté d'Apple.

Même s'il existe effectivement des sources potentielles d'incompatibilités, cela ouvre la porte à des tests où l'on pourrait tenter de compiler avec une ancienne version compatible de Rust, celle qui embarque la bonne version LLVM pour Apple.

Dans une approche multiplateforme complète, cela reste évidemment assez bloquant car il faudrait pouvoir compiler le même code source à la fois à partir de la dernière version de Rust pour bénéficier des dernières améliorations et aussi pour pouvoir compiler à partir d'un ancien version de Rust, spécifiquement pour produire des binaires compatibles bitcode pour l'écosystème Apple. C'est faisable, mais pas convenable.

Je suis toujours assez excité de voir cela se produire car cela ouvrira au moins la porte à davantage de personnes pour tester cela et nous pousser tous dans la bonne direction.

S'exprimant en tant que personne qui essaie actuellement de décider d'une approche pour l'écriture de code mobile multiplateforme pour une équipe assez importante, nous ne pouvons littéralement pas utiliser Rust si nous ne pouvons pas générer de bitcode. L'une de nos applications s'appuie sur le bitcode pour pouvoir générer un binaire suffisamment petit à télécharger sur les réseaux cellulaires, et nous avons de gros clients qui insistent là-dessus.

Sur la base de tout ce que je vois à propos de Rust, je pense qu'il a l'avantage le plus à long terme de toutes les possibilités que je vois là-bas (Kotlin Multiplatform, compilation croisée Swift, Mono, Dart, C++, React Native), mais aurait certainement besoin de bitcode être entièrement pris en charge, même si cela signifiait ne pas être en mesure de suivre les dernières versions de Rust.

Même si le bitcode fonctionnait, Rust ne peut toujours pas cibler watchOS ou tvOS, n'est-ce pas ?

Il est peu probable que Rust soit en mesure de rester à jour avec les exigences de bitcode du côté d'Apple.

Le problème ici est que le LLVM de Rust est trop récent , pas qu'il soit trop ancien . Je suis d'accord que nous devrions avoir une meilleure histoire de compatibilité ici.

Dans quelle mesure est-il possible pour rustc de prendre en charge plusieurs LLVM ?

Connexe : Prise en charge des cibles tvOS et watchOS (et simulateur)

Il utilise déjà plusieurs LLVM. Pour les cibles emscripten, il utilise le fork LLVM d'emscripten qui se trouve sur LLVM 6 atm.

Le problème ici est que le LLVM de Rust est _trop nouveau_, pas qu'il soit _trop ancien_. Je suis d'accord que nous devrions avoir une meilleure histoire de compatibilité ici.

Le problème n'est pas qu'il soit trop ancien ou trop récent, mais que même si la rouille correspond à la version LLVM, cela peut se casser à nouveau dans n'importe quelle version d'iOS. Apple (pour autant que je sache) ne garantit en aucun cas une quelconque stabilité en ce qui concerne le bitcode.

Le problème n'est pas qu'il soit trop ancien ou trop récent, mais que même si la rouille correspond à la version LLVM, cela peut se casser à nouveau dans n'importe quelle version d'iOS. Apple (pour autant que je sache) ne garantit en aucun cas une quelconque stabilité en ce qui concerne le bitcode.

En pratique, nous voyons des mises à jour majeures de Xcode une fois par an lorsque de nouvelles versions iOS sortent. Lorsque cela se produit, les développeurs savent très clairement qu'ils doivent commencer à soumettre des applications avec une version plus récente de Xcode, c'est donc rarement surprenant. Je ne dirais pas que c'est particulièrement difficile à planifier.

Je ne dirais pas que c'est particulièrement difficile à planifier.

Puisqu'il n'y a absolument aucune garantie concernant le bitcode, cela pourrait devenir quelque chose de très difficile à planifier. Imaginez qu'ils décident d'une version à l'autre d'utiliser leur propre format de bitcode qui ne se retrouve pas dans une version open source de LLVM.

Puisqu'il n'y a absolument aucune garantie concernant le bitcode, cela pourrait devenir quelque chose de très difficile à planifier. Imaginez qu'ils décident d'une version à l'autre d'utiliser leur propre format de bitcode qui ne se retrouve pas dans une version open source de LLVM.

Si nous présumons simplement qu'Apple va apporter des changements décisifs sans se soucier de qui que ce soit d'autre, bien sûr. Avoir une documentation plus claire sur leurs plans pour Bitcode ne s'améliore pas beaucoup si nous supposons qu'ils sont malveillants ou qu'ils s'en moquent tout simplement.

Mais ils ont clairement fait de Swift une partie importante de leur plate-forme et plusieurs milliers de développeurs en dépendent, y compris leurs propres équipes et certains de leurs partenaires les plus importants. Swift est basé sur le LLVM entièrement open source et est lui-même entièrement développé à l'air libre, y compris la chaîne d'outils que Xcode utilise pour générer le bitcode qu'Apple accepte.

Donc, pour qu'ils changent soudainement ce format sans que personne ne s'en aperçoive ou ne s'en soucie, il faudrait qu'ils prennent leurs référentiels Swift et LLVM privés, n'est-ce pas ? C'est certainement possible, mais cela ne me semble pas très probable.

Si l'équipe Rust décide que le risque de cela est une bonne raison de ne pas prendre en charge le bitcode, c'est certainement leur prérogative. Je serais un peu triste à ce sujet, mais ce n'est pas à moi de dire aux autres où passer leur temps.

Puisqu'il n'y a absolument aucune garantie concernant le bitcode, cela pourrait devenir quelque chose de très difficile à planifier. Imaginez qu'ils décident d'une version à l'autre d'utiliser leur propre format de bitcode qui ne se retrouve pas dans une version open source de LLVM.

Apple publie Xcode Beta vers début juin et la version finale en septembre. Après 6 à 9 mois plus tard, il arrête d'accepter les applications créées avec les anciennes versions de Xcode sur Appstore.

Je pense qu'il y a suffisamment de temps pour préparer les changements de bitcode pendant cette chronologie.

Je viens de tester avec Xcode 10.2 beta 3 (qui inclut Swift 5 avec LLVM 7) et j'ai pu établir une liaison avec un Rust récent tous les soirs avec bitcode intégré. Évidemment, cela ne fonctionne qu'avec les cibles iOS, car Rust n'a pas de cibles watchOS/tvOS .

Je conviens également que Rust doit pouvoir utiliser le fork Apple LLVM pour toutes les cibles liées à Apple afin de maintenir la compatibilité bitcode.

Oui, la fenêtre de sortie bêta semble raisonnable. Je pense que l'idée qu'Apple va fermer la source LLVM ou leur format bitcode est très improbable, mais Apple exige que le bitcode dans les futures versions d'iOS sonne comme si cela se produirait. Et qui sait, peut-être qu'ils commenceront même à exiger du bitcode pour les soumissions du Mac App Store avec le projet Marzipan.

Le genre de manière non garantie de gérer la compatibilité proposée est certes débile, mais je pense que les plates-formes mobiles devraient éventuellement devenir des plates -

J'espère qu'une approche officiellement approuvée par l'équipe du compilateur encouragerait quelqu'un à travailler là-dessus, mais je pense qu'un commentaire précédent de @brson résume l'hésitation :

Nous maintenons avec succès la compatibilité entre plusieurs versions de LLVM. Tant que Apple et le nôtre ne s'éloignent pas trop l'un de l'autre, cela devrait être faisable, mais il y a toujours le risque d'une telle rupture que le fossé ne peut pas être franchi.

Ou peut-être que le bitcode se stabilisera à l'avenir et nous oublierons tous que ce débat n'a jamais eu lieu 🙏

Je vais manger mon chapeau maintenant

Dans lequel j'ai dit :

l'idée qu'Apple va fermer la source LLVM ou leur format bitcode est très improbable

Ce qui était surtout en réponse à la méfiance exprimée par @mitsuhiko :

Imaginez qu'ils décident d'une version à l'autre d'utiliser leur propre format de bitcode qui ne se retrouve pas dans une version open source de LLVM.

Mais si vous regardez le problème #48833 , il y a certainement un précédent. Comme @comex l'a écrit précédemment :

il y a eu des cas où des fonctionnalités apparaissent dans le LLVM de Xcode avant le tronc LLVM - comme l'intégralité du port arm64, lorsqu'il a été développé à l'origine, car Apple voulait garder secret son intention d'expédier des appareils arm64

Et l'histoire de @michaeleiselsc du même numéro :

une application sur laquelle je travaillais a été durement touchée par des redémarrages aléatoires en décembre 2016, et cela est dû à un problème spécifique que LLVM open source n'a résolu qu'en décembre 2017. Lorsque nous sommes passés de LLVM open source à LLVM d'Apple en décembre 2016, le problème a été corrigé

Étant donné que l'idée est d'utiliser le LLVM d'Apple avec Rust, cela ne semble pas si mal, mais il y a certainement un risque d'avoir parfois un bogue désagréable en raison d'implémentations divergentes 😢. Ce n'est pas un risque que tous les projets peuvent assumer. Transpiler semble être une meilleure option à ce stade, mais jusqu'à présent, cela ne semble pas tout à fait possible .

Je pense toujours que l'utilisation de LLVM d'Apple devrait être prise en charge, mais il devrait y avoir des avertissements clairs dans la documentation expliquant qu'il n'y a aucune garantie que les choses continueront de fonctionner (un niveau 1.5 ou quelque chose du genre).

Kotlin/Natif. JetBrains considère les plates-formes mobiles comme une priorité et bien que cela leur ait pris un certain temps et qu'il ne s'agisse que de marqueurs de bitcode (pas encore de bitcode complet), c'est assez bon pour commencer à travailler avec - voir JetBrains/kotlin-native#1564 et JetBrains/kotlin-native# 1202 (commentaire)

Merci de l'avoir signalé @oleksandr-yefremov ! J'ai creusé un peu plus loin et j'ai pu reproduire l'approche kotlin/native en golang . Je pense que vous devriez pouvoir faire la même chose, ce qui permettrait d'utiliser la rouille dans les applications iOS/tvOS/watchOS compatibles bitcode sans nécessairement émettre de bitcode.

Le bitcode fonctionne-t-il maintenant ? Quelqu'un a-t-il essayé ?

@volodg Je suis un novice de la rouille. Cependant, j'ai parcouru ce didacticiel avec la dernière rouille tous les soirs (au moment de la rédaction de rustc 1.37.0-nightly (088b98730 2019-07-03) ) et cela n'a PAS fonctionné.

On dirait que les marqueurs sont là..

$ otool -arch arm64 -l librust.a  | grep bitcode
  sectname __bitcode
...

Mais j'obtiens l'erreur suivante lors de la construction pour un appareil iOS (le simulateur fonctionne):

ld: '/Users/amrox/Documents/Projects/rust-ios-example/hello-rust/libs/librust.a(rust-e6011ffb55678675.rust.8yq9vjk7-cgu.3.rcgu.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. for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

C'est tout ce que j'ai obtenu.

J'ai réussi à lier rustc nightly-2019-09-05 aarch64-apple-ios and rustflags = "-C lto -Z embed-bitcode" staticlib avec l'application clang-1100.0.33.5 (Xcode 11 beta 7) and -fembed-bitcode . Le code source est https://github.com/saturday06/rust-ios-bitcode-test .

  • Savez-vous si la section __cmdline est nécessaire ?

Deux ans plus tard, je peux répondre à cette question : pour le déploiement sur des appareils physiques ou la création d'archives Xcode, une ligne de commande vide convient, mais pour les soumissions sur l'App Store, Apple effectue la validation de la ligne de commande clang. J'ai mis une description plus longue dans ce PR, qui comprend un correctif hacky pour le faire fonctionner : https://github.com/getditto/rust-bitcode/pull/7

J'aimerais faire cela en amont d'une manière ou d'une autre, mais les options ne sont pas attrayantes. Créons-nous des options de cliquetis lorsque nous ciblons iOS ? Fournissons-nous une envvar pour choisir exactement comment mentir au cas où Apple modifierait ses règles de validation ? Je serais heureux de faire le changement s'il y a un choix raisonnable ici.

-Cembed-bitcode=no ne fonctionne pas pour la cible ios. il y a encore une section bitcode dans le fichier .a
comment construire sans bitcode ?

Cette page vous a été utile?
0 / 5 - 0 notes