Rust: Suporte ao código de bits da loja de aplicativos da Apple

Criado em 24 ago. 2016  ·  89Comentários  ·  Fonte: rust-lang/rust

Bitcode é o futuro da distribuição de aplicativos da Apple e não o suportamos agora. Fazer isso é complicado porque a Apple escolhe qualquer versão do LLVM que eles desejam e o atualiza de acordo com seus caprichos. Não podemos acoplar nosso LLVM ao deles porque temos nossas próprias necessidades e não podemos ser forçados a atualizar sempre que a Apple decidir.

Aqui estão algumas opções:

  • Enviamos uma cadeia de ferramentas totalmente separada para direcionar o bitcode da Apple. Isso é bem feio.
  • Mudamos o rustc para carregar dinamicamente o LLVM, criamos um pacote rust-llvm e um pacote rust-llvm-apple opcional e fazemos com que o rustc carregue o LLVM da apple para lidar com seu código de bits.
  • Criamos uma caixa rustc_llvm_apple e apenas vinculamos dois LLVMs inteiros em rustc o tempo todo. Isso provavelmente não voaria
  • Criamos uma compilação de rustc chamada rustc-apple e a enviamos em um pacote opcional rustc-apple. É exatamente como o rustc, exceto que, em vez de vincular ao rustc_llvm, ele se vincula ao rustc_llvm_apple. Quando rustc recebe uma solicitação para emitir bitcode, ele apenas adia completamente o binário rustc-apple. Eu realmente gosto bastante desta solução.
  • Poderíamos investigar um desinfetante de bitcode para traduzir nosso bitcode para o deles. Acho que a probabilidade de sucesso aqui é baixa por causa da manutenção. Eu acredito que o RenderScript faz isso.

Eu acho que o carregamento dinâmico do LLVM e as soluções de adiar para alternar-rustc são mais promissoras.

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

Comentários muito úteis

Consegui vincular rustc nightly-2019-09-05 aarch64-apple-ios and rustflags = "-C lto -Z embed-bitcode" staticlib com clang-1100.0.33.5 (Xcode 11 beta 7) and -fembed-bitcode app. O código-fonte é https://github.com/saturday06/rust-ios-bitcode-test .

Todos 89 comentários

Mudamos o rustc para carregar dinamicamente o LLVM, criamos um pacote rust-llvm e um pacote rust-llvm-apple opcional e fazemos com que o rustc carregue o LLVM da apple para lidar com seu código de bits.

Carregar dinamicamente o LLVM certamente não é uma opção. A API LLVM é menos estável que seu código de bits e, se construirmos contra LLVM xy, ter LLVM xz em vez de xy quase certamente quebrará o rustc. Basta vincular ao sistema LLVM estaticamente (como --llvm-root já faz).

Criamos uma caixa rustc_llvm_apple e apenas vinculamos dois LLVMs inteiros em rustc o tempo todo. Isso provavelmente não voaria

Basta vincular o sistema LLVM (estaticamente) para distribuições de maçã. Na minha experiência já funciona bem.

Poderíamos investigar um desinfetante de bitcode para traduzir nosso bitcode para o deles. Acho que a probabilidade de sucesso aqui é baixa por causa da manutenção. Eu acredito que o RenderScript faz isso.

Ok… então, o fato é que o formato de bitcode LLVM é meio estável entre as versões do LLVM. A apple faz algo incomum para que isso não seja verdade, ou o formato de bitcode usado não é LLVM completamente (ou seja, tem coisas específicas da apple)?


Sinto que ouvi desde 2013 que usar o bitcode LLVM como formato de distribuição é estúpido. Eu certamente concordo; a distribuição de bibliotecas binárias nativas não funciona mais para iOS?

Também estou muito interessado no que aconteceria quando a Apple atualizasse para a versão LLVM com formato de bitcode incompatível internamente e as pessoas ainda compilassem coisas com compiladores antigos.

Eu experimentei brevemente com isso, ou seja, código de bits de saída durante compilações de carga, então tentei criar uma biblioteca estática com o código de bits incluído. Quando tentei vincular o llvm na biblioteca de bitcode, obtive uma versão LLVM incompatível do bitcode.

Eu não tenho um teste fácil para reproduzir isso, mas meu palpite é que há apenas uma verificação de versão idiota que nega a vinculação entre diferentes versões do LLVM? Ou, eu apenas fiz algo totalmente errado. Vou tentar criar um caso de teste quando tiver algum tempo para analisar isso novamente.

Seria útil ter uma mensagem de erro exata do llvm-link.

@bluejekyll LLVM possui vários arquivos de bitcode em seu diretório de teste. Testes contra esses arquivos de bitcode são executados continuamente (llvm-dis-3.8/opt-3.8 entende um arquivo de bitcode de 3 anos de 3.2 muito bem, por exemplo), então deve ser alguma coisa da Apple.

Basta vincular o sistema LLVM (estaticamente) para distribuições de maçã. Na minha experiência já funciona bem.

Isso é um pouco mais fácil dizer do que fazer - até onde eu sei, a única versão abençoada do apple-llvm para uploads na App Store é a que vem com o Xcode atual. Isso também significa potencialmente manter as ligações do LLVM para duas versões do LLVM (não necessariamente duas versões secundárias vizinhas). Não acho válido usar apenas uma versão antiga do apple-llvm.

Também estou muito interessado no que aconteceria quando a Apple atualizasse para a versão LLVM com formato de bitcode incompatível internamente e as pessoas ainda compilassem coisas com compiladores antigos.

Eu acho que eles evitam isso permitindo apenas que o Xcode mais recente envie aplicativos (e tenho certeza de que ele está gravado na imagem de saída qual versão do LLVM você usou).

IIRC, o bitcode é empacotado para cada arquitetura, já que o bitcode entre arquiteturas não é gerado pelo clang (acho que é um anti-objetivo do clang e do bitcode em geral). Ele é armazenado em uma seção para cada arquivo de objeto, portanto, no mínimo, é duplicado. Isso pode ser parte do motivo pelo qual alguém mencionou que o bitcode pode não ser a melhor maneira de fazer isso.

Sinto que todas as soluções recomendadas são um pouco nojentas. A maneira menos confusa que posso pensar é permitir que diferentes alvos sobrecarreguem o comportamento do codegen e que o caminho do codegen da Apple esteja em uma caixa dinâmica. (O que seria apenas o caminho de codegen regular compilado em apple-llvm.)

Como esse bug menciona a App Store, vale a pena falar sobre a história do tratamento de exceções aqui? (ou seja, panic=abort é estritamente necessário no momento.)

O LLVM possui vários arquivos de bitcode em seu diretório de teste. Testes contra esses arquivos de bitcode são executados continuamente (llvm-dis-3.8/opt-3.8 entende um arquivo de bitcode de 3 anos de 3.2 muito bem, por exemplo), então deve ser alguma coisa da Apple.

@nagisa obrigado por me informar isso. Isso me dá esperança de que ainda pode haver uma solução aqui, e que eu provavelmente estava fazendo algo errado.

@ricky26 bons pontos.

até onde eu sei, a única versão abençoada do apple-llvm para uploads na App Store é aquela enviada com o Xcode atual.

O Xcode LLVM na apple não é a mesma coisa que o LLVM do sistema? Eu quis dizer o Xcode LLVM então. Teríamos que garantir que o xcode seja sempre a versão mais recente ao enviar trens rustc.

É claro que a maneira como a apple faz as coisas exclui a produção de um bitcode válido da apple com uma versão antiga do rustc e essencialmente nos força a jogar todos os benefícios que nossa história de estabilidade oferece pela janela, e não vejo como isso possa ser corrigido.

Isso também significa potencialmente manter as ligações do LLVM para duas versões do LLVM

Já mantemos¹ suporte para LLVM versões 3.7 a 3.9 (e potencialmente trunk). Contanto que o LLVM do Xcode não seja uma versão antiga, acho que estamos bem nesse sentido. Se o Xcode LLVM for realmente uma versão antiga/personalizada/etc, então não nos vemos sendo capazes de oferecer suporte a esse recurso. Especialmente porque não temos a opção de enviar patches para _that_ LLVM para adicionar os recursos que precisamos. Eu também não gostaria de bloquear o rustc para suportar o 3.7 para sempre, caso a Apple decidisse não atualizar o Xcode LLVM até 2038.

¹: no entanto, se o rustc foi construído contra o LLVM xy, ele deve estar vinculado exatamente ao LLVM xy.

Carregar dinamicamente o LLVM certamente não é uma opção. A API LLVM é menos estável que seu código de bits e, se construirmos contra LLVM xy, ter LLVM xz em vez de xy quase certamente quebrará o rustc. Basta vincular ao sistema LLVM estaticamente (como --llvm-root já faz).

@nagisa A API C++ é instável, mas usamos a API C e tivemos muito sucesso no suporte a várias versões do LLVM de uma só vez. Não vejo diferença em termos de suporte à API.

Basta vincular o sistema LLVM (estaticamente) para distribuições de maçã. Na minha experiência já funciona bem.

Poderíamos simplesmente enviar o LLVM da Apple para todas as plataformas da Apple, mas isso significa acoplar nosso LLVM às Apples para geração de código de máquina de desktop, e exclui a opção de suportar bitcode do iOS em hosts que não sejam da Apple.

Ok… então, o fato é que o formato de bitcode LLVM é meio estável entre as versões do LLVM. A apple faz algo incomum para que isso não seja verdade, ou o formato de bitcode usado não é LLVM completamente (ou seja, tem coisas específicas da apple)?

O formato de bitcode não é estável entre as versões.

a distribuição de bibliotecas binárias nativas não funciona mais para iOS?

Ele funciona hoje. Não é o método preferido e não é óbvio que continuará a ser suportado.

Isso também significa potencialmente manter as ligações do LLVM para duas versões do LLVM (não necessariamente duas versões secundárias vizinhas). Não acho válido usar apenas uma versão antiga do apple-llvm.

@ricky26 Mantemos com sucesso a compatibilidade entre várias versões do LLVM. Contanto que a Apple e a nossa não se afastem muito, isso deve ser factível, mas sempre há o risco de uma quebra tão grande que a divisão não pode ser cruzada, e eu sei que há grandes mudanças na API chegando.

Contanto que o LLVM do Xcode não seja uma versão antiga, acho que estamos bem nesse sentido.

A partir desta página 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

A API C++ é instável, mas usamos a API C e tivemos muito sucesso no suporte a várias versões do LLVM de uma só vez. Não vejo diferença em termos de suporte à API.

Isso não é verdade. Temos (bastante grandes!) várias ligações para APIs C++ na forma de rustllvm. Há vários casos em que compilamos esse wrapper dependendo da versão do LLVM compilada. Caso a versão do LLVM usada e compilada não corresponda, você receberá erros de vinculador dinâmico ou, pior, terá problemas em tempo de execução.

exclui a opção de suporte ao bitcode do iOS em hosts que não sejam da Apple.

Se a Apple não quiser pegar o bitcode gerado por nada além de seu fork do LLVM, então não vejo como poderíamos fazer algo aqui além de manter um fork semelhante e fazer engenharia reversa em seus patches internos.

O formato de bitcode não é estável entre as versões.

Claro, mas é bastante justo supor¹ que o bitcode entre várias revisões do LLVM conhecido como 3.7.0, por exemplo, é suficientemente compatível para fins de geração de bitcode para consumo por outra compilação do LLVM da série 3.7.0. Certamente é melhor do que vincular ao libLLVM dinamicamente.

¹: especialmente considerando que o bitcode da série 3.2 ainda é compatível com 3.8 LLVM, mesmo que seja um espécime muito pequeno.

Algumas notas:

  • O Xcode nem vem com uma libLLVM vinculável (estática ou dinâmica), apenas uma libclang.dylib que vincula estaticamente ao LLVM.
  • A Apple envia a fonte para seu 'clang' (incluindo LLVM) em 'Developer Tools' em https://opensource.apple.com , mas esse site tende a levar uma eternidade para ser atualizado.
  • A história pode ser melhor com o Swift, que tem seu próprio fork do LLVM com tags de lançamento - mas eles podem não corresponder perfeitamente ao que é enviado com o Xcode. (É possível usar instantâneos de cadeia de ferramentas de código aberto com o Xcode, mas projetos criados com essas cadeias de ferramentas não podem ser enviados à App Store.)

cc @rust-lang/compiler

Seria curioso saber como outras linguagens de programação planejam lidar com isso. Em particular mono e ir.

A resposta do Unity para esse problema é il2cpp - construindo todos os seus assemblies IL em código C++.

Bug golang relevante: https://github.com/golang/go/issues/12682; a sugestão parece ser que eles poderiam usar a cadeia de ferramentas go LLVM (que não é tão apresentada quanto a cadeia de ferramentas go padrão).

Em suma, a história do suporte a bitcode fora da Apple é ruim.

Mono propriamente dito vai via apple LLVM, parece: http://tirania.org/blog/archive/2015/Sep-02.html

Um obstáculo será que você não pode carregar assembly inline em bitcode :(

Para a história do mono, tive uma conversa rápida com Miguel de Icaza sobre o que o Mono faz para os curiosos: https://twitter.com/mitsuhiko/status/769458873237434368

@mitsuhiko Você _pode_ ter assembly embutido em bitcode no iOS e tvOS, mas não no watchOS, por algum motivo.

Algum movimento sobre isso? Não me sinto bem em usar Rust no iOS sem um plano para dar suporte ao bitcode. A Apple tem um histórico de tornar coisas opcionais como não opcionais de repente e, de fato, o código de bits já é necessário no watchOS e tvOS.

Sinto que todas as soluções recomendadas são um pouco nojentas. A maneira menos confusa que posso pensar é permitir que diferentes alvos sobrecarreguem o comportamento do codegen e que o caminho do codegen da Apple esteja em uma caixa dinâmica. (O que seria apenas o caminho de codegen regular compilado em apple-llvm.)

Essa abordagem (por @ricky26) parece ser a mais natural para mim como usuário do rustc.

Eu não acredito que nada mudou sobre isso recentemente, pelo menos, pelo menos. Com o recente anúncio do LLVM sobre versionamento, eles indicaram que o bitcode deve (eu acho) sempre ser carregável por versões futuras do LLVM. Isso pode significar que esse problema está "resolvido" em um nível fundamental, mas ainda exigiria uma interface mais ergonômica para extrair todo o código de bits.

Existem atualizações sobre isso?

Este comentarista no HackerNews conseguiu usar Bitcode gerado a partir de Rust no macOS e iOS. O tópico tem algumas informações detalhadas sobre como habilitar o bitcode para binários de ferrugem, o que parece uma ótima notícia!

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

Como o comentarista em questão, notas rápidas:

  • Eu usei -C lto --emit llvm-bc para fazer o rustc emitir um arquivo .bc contendo a grade atual e todas as dependências. Isso funciona, mas é essencialmente um hack; em particular, não funciona para dependências C, incluindo jemalloc (embora isso não seja usado no iOS de qualquer maneira). Seria melhor se o rustc suportasse corretamente a emissão de Mach-Os com "bitcode embutido"; você pode olhar para a fonte do clang para ver como é feito.

  • Se você quiser experimentá-lo e não se importar com o hack, parece 'simplesmente funcionar', exceto pelo problema da versão:

  • O principal obstáculo prático é que o Rust sincroniza com o tronco LLVM com mais frequência do que o Xcode, que parece fazê-lo apenas anualmente. As versões mais recentes do LLVM podem carregar o bitcode antigo, mas não o contrário, portanto, você deve usar uma versão antiga do rustc ou compilar a mais recente em um LLVM antigo. (Na verdade, o rustc 1.17 parece ainda funcionar com o Xcode 8.x, mas não todas as noites desde a atualização do LLVM 4.0; isso é apenas coincidência.)

  • Idealmente, o Rust enviaria binários oficiais construídos em uma versão LLVM adequada. Na prática, parece bom usar a versão correta do estoque LLVM, mas se você quiser usar o fork da Apple:

    • Como eu disse em um comentário anterior, o Xcode não envia binários LLVM em nenhuma forma vinculável, mesmo dinamicamente; apenas clang e libclang.dylib (que exporta a API Clang, mas não a LLVM).
    • Mas, como eu também disse, o código-fonte geralmente sobe em opensource.apple.com (em Developer Tools -> clang; o arquivo inclui todo o LLVM), apenas um pouco inconsistente/após um atraso. No entanto, especialmente devido às garantias expandidas de compatibilidade com versões anteriores observadas por @alexcrichton , pode não ser o fim do mundo nem sempre estar atualizado. Atualmente, a versão fonte mais recente é para o Xcode 8.2.1, enquanto a mais recente é a 8.3.2.

(Como teste, tentei compilar Rust no Xcode 8.2.1 Clang. rustllvm falha ao compilar, porque seu ninho de condicionais #if LLVM_VERSION_GE(..) , que servem para permitir que ele compile em ambos LLVM mais antigo e mais novo, fica confuso com este ramo - que afirma ser LLVM 3.9svn, mas em termos de API está em algum lugar entre 3.8 e 3.9. Provavelmente não vale a pena consertar, já que o Xcode está quase pronto para sua próxima atualização anual de qualquer maneira.)

Houve algum progresso nesta frente? Alternativamente, você (equipe principal) consideraria essa provação um problema com uma correção permanente sólida à vista ou espera que essa coisa de salto de versão permaneça no futuro próximo?

Estou pensando em implementar partes de um aplicativo iOS em Rust por seu sistema de tipo superior e semântica de baixo nível e prefiro não ficar preso a hacks/atrasos não-bitcode ou regulares sempre que houver uma atualização para Xcode ou rustc.

@regexident

Acho que vamos implementar versões LLVM trocáveis ​​por outros motivos. Se isso for implementado, não devemos ter problemas para enviar trans separados para Apple, wasm e tudo mais.

cc#45684

O bitcode da Apple ainda não é realmente perigoso ala https://medium.com/@FredericJacobs/why -im-not-enabling-bitcode-f35cd8fbfcc5 Impossível verificar compilações. Problemas para criptografia. etc.

@burdges Para certos aplicativos, isso é absolutamente um problema.

Mas para watchOS e tvOS, a Apple de fato exige Bitcode para envios na App Store. Você não tem escolha. Além de "não faça criptografia ou coisas críticas nessas plataformas". Também é preciso temer que a Apple imponha Bitcode para iOS em algum momento no futuro. Eu prefiro não ter um produto brickado nesse ponto.

Eu tentei construir com Rust 1.24.0 para iOS usando o truque -C lto --emit=llvm-bc , mas o linker deu os seguintes erros:

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)

Alguma ideia do que pode ser o problema?

Edit: parece que eu posso pelo menos suprimir esse problema envolvendo todo o código em cada fn externo público com AssertUnwindSafe

libbacktrace é uma biblioteca C que está incluída na árvore de origem do Rust:

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

Você terá que compilar isso como bitcode de alguma forma.

Estou confuso, porque só consigo encontrar um libbacktrace criado para o meu laptop, mas não para os sistemas operacionais do telefone. Como a ferrugem insere esses símbolos no stdlib? Existe uma maneira mais fácil de fazer isso, desativando de alguma forma a funcionalidade de backtrace? Eu removi o RUST_BACKTRACE env var, mas isso não ajudou. Eu li que você pode compilar rustc sem backtraces, mas eu esperava algo mais fácil, por exemplo, no arquivo cargo.toml do meu projeto

Fundamentalmente, você quer construir a árvore de origem rustc enquanto diz para passar -fembed-bitcode para o compilador C. Idealmente, você só poderia adicioná-lo a CFLAGS ; infelizmente, acabei de tentar isso e não funcionou corretamente devido a dois problemas com gcc-rs (usado pelo sistema de compilação do rustc para criar dependências C). No entanto, consegui que funcionasse com um procedimento um pouco hacky:

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

Isso deve gerar um libbacktrace.a (em ./build/aarch64-apple-ios/native/libbacktrace/.libs/ ) com bitcode incorporado. __LLVM,__bitcode do que são bibliotecas nativas, da mesma forma que o clang faz: então não haveria necessidade de compilar e vincular manualmente os arquivos .bc.

(Na verdade, como o erro que você citou parece um erro de vinculador normal, acho que você poderia superá-lo apenas vinculando um libbacktrace.a normal, sem código de bits incorporado. Mas, na melhor das hipóteses, isso resultaria em um arquivo de saída com código de bits incorporado quebrado.)

Os problemas mencionados:

  • gcc-rs passa -ffunction-sections e -fdata-sections sem como desativá-los; clang reclama disso quando combinado com -fembed-bitcode (mesmo que -fno-function-sections seja passado mais tarde).

Eu arquivei um relatório de problema e, como solução alternativa, o procedimento acima usa um script wrapper que remove esses argumentos. Mas isso causou um segundo problema:

  • gcc-rs tenta encontrar ar no mesmo diretório que CC_aarch64_apple_ios (!?); configurar manualmente AR_aarch64_apple_ios não teve efeito

Não consegui reproduzir isso com o cc-rs mais recente (renomeado de gcc-rs ), então não registrei um problema. Como solução alternativa, o procedimento acima faz um link simbólico de ar no mesmo diretório.

Obrigado pelas sugestões! Na verdade, eu só precisava de bitcode para meu próprio código, não para o material de backtrace, então usei o libbacktrace compilado sem qualquer incorporação de bitcode

Com o hack que tentei, agora estou enfrentando outro problema: dsymutil segfaults quando tento criar um dSYM para ele. A execução normal sem um dSYM funciona bem, mas a criação do dSYM é interrompida por algum motivo. Eu removi meu libbacktrace.a, substituí-o por funções de espaço reservado vazias e as coisas funcionaram bem, então parece que há um problema com minha lib de ferrugem.

Isso soa como um bug no dsymutil, que deve ser relatado no upstream para o LLVM. Você pode tentar executar o dsymutil no LLDB e postar um backtrace da falha? Ou para obter melhores informações de depuração, você pode tentar construir o LLVM no modo de depuração e reproduzi-lo com isso.

(Observe que o binário em uma instalação de estoque LLVM é chamado llvm-dsymutil , mas hoje em dia o dsymutil do Xcode é apenas um link simbólico para llvm-dsymutil . dsymutil costumava ser um utilitário de código fechado separado, mas por alguns anos essa versão foi enviada como dsymutil-classic e não usada por padrão.)

@comex por curiosidade, a caixa cc compilar tudo com -fembed-bitcode ? Ou se estivermos usando o clang "oficial", tudo bem evitar a incorporação de bitcode?

(desculpe, não estou muito familiarizado com as práticas recomendadas do ios!)

Para o próprio código Rust, seria melhor se apenas emitimos bytecode em vez de arquivos de objeto? Isso é algo que Clang/o vinculador pode entender?

@alexcrichton

a caixa cc compilar tudo com -fembed-bitcode ? Ou se estivermos usando o clang "oficial", tudo bem evitar a incorporação de bitcode?

Usar o clang oficial não elimina a necessidade de bitcode embutido. Em vez disso, o bitcode é incluído - além do código nativo - no arquivo do aplicativo carregado para a Apple, e a Apple pode recompilá-lo no lado do servidor, por exemplo, para otimizar diferentes microarquiteturas.

Provavelmente faria sentido passar -fembed-bitcode por padrão no iOS/watchOS/tvOS. Em caso afirmativo, ao compilar no modo de depuração, -fembed-bitcode-marker deve ser passado (em vez disso ou além disso, não importa); isso diz ao clang para incluir apenas uma seção de código de bits fictício em vez de qualquer código de bits real, já que o código de bits incorporado é necessário apenas para os arquivos finais do aplicativo e acelera um pouco a compilação para omiti-lo. Na verdade, o Xcode passa -fembed-bitcode-marker para tudo além de construir o arquivo final do aplicativo, até mesmo compilações de desenvolvimento que tenham otimizações - mas como cc não tem um conceito separado de "versão realmente final mode", ele provavelmente deve passar no modo de depuração. Observe que é seguro incorporar bitcode mesmo que a compilação final não o exija.

Para o próprio código Rust, seria melhor se apenas emitimos bytecode em vez de arquivos de objeto? Isso é algo que Clang/o vinculador pode entender?

Ambos clang e ld suportam arquivos de código de bits brutos passados ​​como entradas; isso normalmente é usado quando o LTO está habilitado ( -flto ), caso em que os arquivos .o que o clang gera são na verdade bitcode bruto, não Mach-O. (Eles ainda podem ser formados em bibliotecas estáticas usando o comando lipo normal.) Entretanto, isso é separado do formato "bitcode incorporado", que consiste em um Mach-O com bitcode inserido na seção __LLVM,__bitcode , além do código nativo nas seções usuais. Esse formato é usado em arquivos de objeto quando o LTO está desativado, bem como em executáveis ​​vinculados finais ou bibliotecas dinâmicas, independentemente da configuração do LTO. (Se o LTO estiver ativado, o vinculador é responsável por criar esta seção; se o LTO estiver desativado, o vinculador simplesmente concatena as seções __LLVM,__bitcode de cada arquivo de objeto como faria para qualquer outra seção, em vez de gerar uma única módulo bitcode. ) EDIT: na verdade, ele faz algo um pouco mais complicado , gerando um arquivo xar das seções bitcode e colocando-as em uma seção chamada __LLVM,__bundle ; de qualquer forma, não é algo com o qual temos que nos preocupar.

Eu acho que idealmente o rustc deve produzir "bitcode incorporado" por padrão no iOS, não bitcode bruto. Não é muito difícil de fazer e evita quebrar a compilação incremental - especialmente no modo de depuração, onde você pode apenas produzir uma seção de bitcode fictícia, ala -fembed-bitcode-marker , mas potencialmente no modo de lançamento também, já que o vinculador apenas enche os objetos ' seções de código de bits juntas em vez de fazer algo caro no momento do link.

Veja como clang gera bitcode incorporado:

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

Relativamente simples - antes de invocar o back-end, ele despeja o módulo LLVM atual como bitcode e, em seguida,
coloca isso como dados binários em uma nova variável global (no mesmo módulo!), colocada na seção __LLVM,__bitcode . Parece um design meio hacky (por que o frontend tem que fazer isso manualmente?), mas não deve ser muito difícil de reproduzir no rustc.

@comex essa abordagem faz sentido, embora eu ache que existam razões (veja #48833 que acabei de fazer) para usar o clang da Apple como back-end, enquanto estamos pensando em mudanças como essa. Além disso, quão fácil é compilar a partir do bitcode incorporado?

@michaeleiselsc Desculpe, não entendo o que você quer dizer com "compilar-nos a partir do bitcode incorporado".

Como em, em vez de apenas fornecer um binário para a App Store com bitcode incorporado, também há benefícios em pegar o bitcode e construí-lo usando o Apple clang. Dois benefícios que me interessam são as correções downstream que a Apple clang tem e a capacidade de usar sanitizantes clang, por exemplo, o sanitizante de cobertura.

@comex ok, então cavando um pouco, parece que a implementação em rustc é bastante fácil (relativamente), mas tenho algumas perguntas:

  • Por que -fembed-bitcode-marker uma coisa? Usando clang localmente, ele apenas emite uma estática vazia em uma seção. Isso significa que a mera presença da seção significa alguma coisa? Alguma ferramenta ao longo do caminho no iOS quebra se a seção não estiver lá? (mas na verdade não parece dentro da seção porque está vazio?
  • Você sabe se a seção __cmdline é necessária? Parece que -fembed-bitcode também incorpora alguma forma de linha de comando no binário. Não tenho certeza do que colocaríamos aqui, pois provavelmente não é a linha de comando do rustc, mas alguma ferramenta analisa isso? A compilação é interrompida se -fembed-bitcode=bitcode for usado com iOS?
  • E, finalmente, existe uma razão para querer desabilitar isso? Ou devemos habilitar isso incondicionalmente para os destinos do iOS e seguir em frente?

Por que -fembed-bitcode-marker é uma coisa?

Eu acho que é usado pelo xcode para indicar que algo deve usar bitcode, mas o bitcode não foi realmente compilado. Se você tentar arquivar tal projeto mais tarde, o ld falhará com um erro.

Para a questão de saber se queremos sempre habilitar isso, definitivamente há alguns casos com os quais gostaríamos de ter cuidado. Por exemplo, se alguém o enviar para uma plataforma de distribuição de aplicativos beta como o HockeyApp, o HockeyApp removerá essa seção de código de bits ou os testadores beta terão que baixar um binário muito maior do que o necessário?

@mitsuhiko Sim, a ideia é que o vinculador possa verificar se a compilação está configurada corretamente para bitcode, mesmo se você estiver testando compilações que não precisam de bitcode.

Por exemplo, se você compilar um arquivo C sem mencionar o bitcode, tente vinculá-lo com -fembed-bitcode-marker , você obtém:

$ 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.

O aviso desaparece se você passar -fembed-bitcode-marker na primeira linha também.

@alexcrichton Quanto a __cmdline … hmm… parece que o vinculador exige que ele esteja presente (procure por "Criar código de bits"):

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

Mas não vejo nada que se importe com o valor real. Provavelmente é melhor colocar um valor fictício lá.

Esse problema foi resolvido mesclando #48896?

Eu tenho brincado com isso nas compilações noturnas e funciona muito bem até você tentar arquivar com o Xcode. Parece que está adicionando fembed-bitcode-marker, mas não fembed-bitcode, à saída da biblioteca estática Rust. É compilado com cargo lipo --release com:

$ 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)

Quando executo otool -arch arm64 -l /Users/chrisbal/Documents/Beach/rust-universal-template/target/universal/release/libexample.a | grep bitcode recebo muito sectname __bitcode , mas não sei como verificar se isso é bitcode real e não apenas marcadores.

Estou usando caixas aninhadas, então talvez a caixa "genérica" ​​interna não esteja recebendo os sinalizadores de bitcode?

edit: aqui está nosso repositório demonstrando o problema https://github.com/Raizlabs/rust-universal-template/tree/879e7412d729e8963586c5b083d51b09733aec32

@chrisballinger , funciona com sinalizador adicional, veja
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)

Mas eu tenho outro erro de compilação apenas para 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

Alguém sabe como corrigir arm7 arch ?

Infelizmente, não consigo fazer funcionar também, recebendo o mesmo erro 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)

Eu tentei compilá-lo com RUSTFLAGS="-Z embed-bitcode" cargo lipo --release e defini-lo em .cargo/config . Ele adiciona o sinalizador embora:

` 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` ...

Alguma atualização aqui? Considerar fortemente uma biblioteca principal compartilhada para nosso aplicativo e sem esse c++ fixo é a opção provável.

@chrisballinger , pode estar relacionado a https://github.com/rust-lang/rust/issues/52686?

@volodg Não, este problema é de um tempo atrás.

Com a fusão de #48896, é suposto funcionar imediatamente?

Estou na versão 1.29.1 e os objetos ainda não possuem código de bits incorporado por padrão. Como mencionado anteriormente por @volodg , você pode obter ferrugem para incorporá-los usando RUSTFLAGS="-Z embed-bitcode" . Mas, pelo que experimentei, você entra em problemas em que as próprias bibliotecas do Rust (compiler_builtins, std) não são compiladas com código de bits incorporado. Talvez a reconstrução de destinos iOS usando xargo com código de bits incorporado funcione, mas não tentei.

Eu tentei usar xargo como você propôs, mas o problema parece ainda estar aqui :(

Usando este Xargo.toml

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

Também adicionando isso a Cargo.toml :

[profile.release]
panic = "abort"

Eu compilei usando xargo build --release --target $TARGET para todos esses destinos:

  • aarch64-apple-darwin
  • armv7-apple-darwin
  • armv7s-apple-darwin
  • i386-maçã-darwin
  • x86_84-apple-darwin

Então eu usei lipo para criar uma biblioteca estática.

Eu ainda tenho um erro de linker:

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)

Fui um pouco mais longe com o caminho do xargo.

Meu Xargo.toml

[dependencies]
std = {}

Meu Cargo.toml

[profile.release]
panic = "abort"

Eu não sei se é necessário, mas do xargo doc, você precisa usar explicitamente extern crate compiler_builtins , que adicionei ao meu lib.rs.

Eu então compilei com: RUSTFLAGS="-Z embed-bitcode" xargo build --target $TARGET --release para compilar. Certifique-se de compilar core/std/compiler_bultins. xargo clean não limpa compilações anteriores corretamente do que eu experimentei, então um rm -rf ~/.xargo foi necessário para recompilar std quando tentei diferentes ajustes de Xargo.toml .

Mas então, arquivando no Xcode 10, recebo (em armv7 linking):

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)

Isso significa que o bug depende do lado do LLVM?

EDIT : Como podemos ajudar a avançar nesta questão?

Alguém tentou isso recentemente? Parece que o armv7 é o maior problema?

Olá a todos. Eu tenho acompanhado este tópico por um tempo agora e estou muito animado para ver o bitcode da Apple sendo suportado com Rust. Alguém conseguiu até agora fazer este trabalho? O que está faltando atualmente e como podemos ajudar?
Obrigado!

Depois de algumas horas caçando esse problema, descobri o motivo pelo qual a incorporação de bitcode do Rust não está funcionando no Xcode. A resposta curta é que a versão LLVM do Xcode está esperando o bitcode LLVM 6.0 , enquanto o Rust julho de 2018 .

Agora, a resposta longa...

Como podemos ver no changelog do LLVM 7.0 , eles mudaram assinaturas para @llvm.memcpy , @llvm.memmove e @llvm.memset , e o erro de compilação do Xcode foi claro sobre o tipo de argumento errado como visto no meu comentário anterior .

A propósito, o Kotlin Native adicionou suporte para código de bits incorporado em outubro de 2018 e aparentemente está LLVM 6.0 .

Vendo isso, tentei compilar usando uma versão mais antiga do Rust antes do aumento para 7.0. Eu tentei com nightly-2018-06-01-x86_64-apple-darwin , e sucesso, ele compila !

Também tentei compilar sem usar o Xargo sem sucesso. Todas as dependências precisam ser compiladas com incorporação de bitcode.

Portanto, a menos que a Apple aumente sua versão LLVM, não acho que veremos suporte para bitcode incorporado tão cedo ... A menos que alguém encontre uma maneira inteligente de converter bitcode incorporado para bitcode de 6.0 ...

@appaquet Obrigado por chegar ao fundo disso! Foi um grande mistério para mim e acho que nunca mergulharia tão fundo quanto você. É bom saber que provavelmente deve começar a funcionar assim que a Apple aumentar a versão do LLVM.

Obrigado @appaquet pela sua resposta clara. Agora acho que temos que confiar na Apple para fazer a coisa certa

Visão lateral de alguém que tem interesse em multiplataforma para mobile e comparou a maioria das soluções promissoras (React Native, Flutter, Kotlin/Native, Rust)

Reagir Nativo. Suporta bitcode desde o início, porque essencialmente o bridge é escrito em C++ e está apenas interpretando o código JS em tempo de execução.

Flutuar. Ainda não suporta bitcode - https://github.com/flutter/flutter/issues/15288

Kotlin/Nativo. A JetBrains está considerando as plataformas móveis como uma prioridade e, embora tenha demorado um pouco e seja apenas marcadores de bitcode (ainda não é um bitcode completo), é bom o suficiente para começar a trabalhar - consulte https://github.com/JetBrains/kotlin-native/ pull/1564 e https://github.com/JetBrains/kotlin-native/issues/1202#issuecomment -444022513

Ferrugem. Suporta bitcode para LLVM 7, enquanto a Apple usa a versão 6.

Se eu quiser ter lógica de negócios e plataforma cruzada de interface do usuário, eu usaria React Native ou Flutter. Mas para muitos, muitos aplicativos sérios, esse caminho é muito arriscado. O React Native não tem desempenho suficiente e a estabilidade da API e dependência é um problema (a v1.0 virá?). Flutter é um pouco imaturo, mas parece ganhar cada vez mais tração.

Agora, se eu quiser compartilhar apenas a lógica de negócios em algum tipo de módulo (como os grandes aplicativos anteriores fizeram com C++ e JNI/Obj-C++) e, em seguida, criar uma interface do usuário verdadeiramente nativa, no início, tenho uma escolha entre todos os quatro. Então eu risco o React Native, porque usar JavaScriptCore completo e ponte para executar a lógica de negócios entre JS<->Native parece um pouco exagerado (inicializar essa ponte também é bastante caro). Flutter potencialmente pode ser usado, mas não se destina dessa maneira , então, novamente, eu acabaria usando a estrutura de interface do usuário para executar a lógica de negócios. Além disso, não suporta bitcode.
Rust e Kotlin/Native estão ambos visando esse nicho, possuem ferramentas decentes, produzem binários nativos (desempenho e pegada!). Bitcode é um grande problema para quem quer adotar Rust como linguagem para construção de módulos multiplataforma em plataformas móveis. E agora o Kotlin/Native tem uma vantagem.

Para resumir por que o bitcode é muito importante para desenvolvedores iOS. Não é possível escrever nada no tvOS ou watchOS. Muitos frameworks de terceiros que são distribuídos como binários têm bitcode ativado (dezenas de exemplos, do topo da minha cabeça Google IMA - anúncio de vídeo mais popular). Algumas auditorias de segurança exigem isso. E, finalmente, sempre que a Apple diz "a partir do próximo ano, não aceitamos mais aplicativos sem bitcode totalmente incorporado", todo mundo recebe um cronômetro.

Agora acho que temos que confiar na Apple para fazer a coisa certa

Sim, certo, é por isso que a Apple é notória;)
Não sei qual seria a melhor solução (rebaixar temporariamente para o LLVM 6 não é uma opção, certo?), mas o Rust está perdendo completamente os desenvolvedores de plataformas móveis e iOS.

Muito obrigado por esta explicação detalhada @oleksandr-yefremov. Andei lendo um pouco sobre o assunto e achei esse comentário interessante: https://gist.github.com/yamaya/2924292#gistcomment -2738480

A versão do LLVM está vinculada à versão do Swift usada no XCode. Até o momento foi aplicado o seguinte suporte:

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

Ao olhar para o swift-5.0-branch , notei que a versão declarada do LLVM nele é 7.0.0 : https://github.com/apple/swift-llvm/blob/swift-5.0-branch/ CMakeLists.txt#L25 -L33

Não sei se há mais bloqueadores aqui, mas parece-me que podemos usar Rust para gerar binários de Bitcode 🎉

Parece que o Xcode 10.2 incluirá o Swift 5.0 e deve ser lançado em breve. Mas, por outro lado, o LLVM 8.0 está programado para ser lançado na próxima semana. O Rust provavelmente será atualizado antes que a Apple comece a usá-lo.

Para que o Rust suporte corretamente o bitcode, precisaríamos que as arquiteturas ARM da Apple do Rust usassem uma versão fixada do LLVM (talvez do repositório https://github.com/apple/swift-llvm – a Apple não parece usar o lançou o pacote LLVM, mas suas próprias ramificações). Essa versão do LLVM só seria atualizada quando a Apple lançasse uma nova versão final do Xcode com uma versão diferente do LLVM.

Aliás, parece que o Rust mais recente pode ser construído com o LLVM 6, então isso definitivamente parece factível: https://github.com/rust-lang/rust/blob/master/src/bootstrap/native.rs#L282
Você definitivamente precisaria de pessoas intervindo quando um problema é criado para atualizar a versão necessária do LLVM (a do LLVM 6: https://github.com/rust-lang/rust/issues/55842).

@vincentisambart Rust já usa o LLVM 8 para compilações noturnas há 5 meses IIRC.
O LLVM 6 é uma versão com suporte mínimo se você quiser construí-lo sozinho e for testado no CI: https://github.com/rust-lang/rust/blob/706e67b0a0143d651eb03f2fa2c30645899e81ff/src/ci/docker/x86_64-gnu-llvm-6.0 /Dockerfile

Agora acho que temos que confiar na Apple para fazer a coisa certa

Eu tenho perseguido algo nesse sentido por um tempo (e agora saí) e acho que, em termos de plataforma, não faz sentido para a Apple fazer isso, porque:

  • Swift quer ser Rust de várias maneiras (veja o manifesto de propriedade para uma), mas está muito atrasado
  • A Apple precisa que o Swift seja e continue sendo sua principal linguagem de plataforma, então não faz sentido para eles facilitar outro grande idioma em sua plataforma nem para empurrar o Swift para outros ambientes

Rust já usa o LLVM 8 para compilações noturnas há 5 meses IIRC.

Então, mesmo que a Apple comece a oferecer suporte ao código de bits LLVM 7, o código de bits gerado pelas versões oficiais recentes do Rust pode não funcionar. Mesmo que isso aconteça, ele pode quebrar na próxima vez que o Rust passar para uma versão do LLVM com uma alteração incompatível no bitcode gerado.

O LLVM 6 é uma versão com suporte mínimo se você quiser construí-lo sozinho e for testado em CI

Em seguida, ter as compilações oficiais *-apple-ios do Rust sendo construídas com o LLVM 6 (ou melhor, algo como https://github.com/apple/swift-llvm/releases/tag/swift-4.2.2-RELEASE – se que funciona) pode corrigir os problemas de bitcode.

Acho que o Rust atualmente é fornecido com dois back-ends LLVM (Emscripten e padrão) após a fusão de https://github.com/rust-lang/rust/issues/46819.
Embora #46819 mencione o back-end IOS LLVM para bitcode, ele não foi implementado.

Não para inviabilizar isso inteiramente, mas não faria mais sentido tentar habilitar a transpilação para C para esses casos? É improvável que Rust consiga manter-se atualizado com os requisitos de bitcode do lado da Apple.

Mesmo que existam fontes potenciais de incompatibilidades, isso abre a porta para testes em que poderíamos tentar compilar com uma versão mais antiga compatível do Rust, que incorpora a versão LLVM correta para a Apple.

Em uma abordagem completa de plataforma cruzada, isso ainda é bastante bloqueante, obviamente, pois precisaríamos compilar o mesmo código-fonte da versão mais recente do Rust para nos beneficiar das melhorias mais recentes e também para poder compilar de uma versão mais antiga versão do Rust, especificamente para gerar binários compatíveis com bitcode para o ecossistema da Apple. Isso é factível, mas não adequado.

Ainda estou muito empolgado para ver isso acontecendo, pois pelo menos abrirá as portas para mais pessoas testarem isso e nos levarão à direção certa.

Falando como alguém que está agora tentando decidir sobre uma abordagem para escrever código móvel multiplataforma para uma equipe bastante grande, literalmente não podemos usar Rust se não pudermos gerar bitcode. Um de nossos aplicativos depende de bitcode para poder gerar um binário pequeno o suficiente para fazer download em redes celulares, e temos alguns grandes clientes que insistem nisso.

Com base em tudo o que vejo sobre Rust, acho que ele tem a vantagem de longo prazo de qualquer uma das possibilidades que vejo por aí (Kotlin Multiplatform, compilação cruzada de Swift, Mono, Dart, C++, React Native), mas definitivamente precisaria de bitcode ser totalmente suportado, mesmo que isso significasse não poder acompanhar os últimos lançamentos do Rust.

Mesmo que o bitcode funcione, o Rust ainda não pode direcionar o watchOS ou o tvOS de qualquer maneira, pode?

É improvável que Rust consiga manter-se atualizado com os requisitos de bitcode do lado da Apple.

O problema aqui é que o LLVM do Rust é muito novo , não que seja muito antigo . Concordo que deveríamos ter uma história de compatibilidade melhor aqui.

Quão viável é para o rustc oferecer suporte a vários LLVMs?

Relacionado: Suporta alvos tvOS e watchOS (e simulador)

Ele já usa vários LLVMs. Para os destinos do emscripten, ele usa o fork LLVM do emscripten que está no LLVM 6 atm.

O problema aqui é que o LLVM do Rust é _muito novo_, não que seja _muito antigo_. Concordo que deveríamos ter uma história de compatibilidade melhor aqui.

O problema não é que seja muito antigo ou muito novo, mas que, mesmo que a ferrugem corresponda à versão do LLVM, em qualquer versão do iOS isso pode quebrar novamente. A Apple (até onde eu sei) não garante de forma alguma qualquer estabilidade em relação ao bitcode.

O problema não é que seja muito antigo ou muito novo, mas que, mesmo que a ferrugem corresponda à versão do LLVM, em qualquer versão do iOS isso pode quebrar novamente. A Apple (até onde eu sei) não garante de forma alguma qualquer estabilidade em relação ao bitcode.

Na prática, vemos as principais atualizações do Xcode uma vez por ano quando novas versões do iOS são lançadas. Quando isso acontece, os desenvolvedores têm um aviso bem claro de que precisam começar a enviar aplicativos com uma versão mais recente do Xcode, por isso raramente é surpreendente. Eu não diria que isso é particularmente difícil de planejar.

Eu não diria que isso é particularmente difícil de planejar.

Como não há absolutamente nenhuma garantia em torno do bitcode, isso pode se transformar em algo muito difícil de planejar. Imagine que eles decidiriam de uma versão para outra usar seu próprio formato de bitcode que não termina em uma versão de código aberto do LLVM.

Como não há absolutamente nenhuma garantia em torno do bitcode, isso pode se transformar em algo muito difícil de planejar. Imagine que eles decidiriam de uma versão para outra usar seu próprio formato de bitcode que não termina em uma versão de código aberto do LLVM.

Se vamos apenas presumir que a Apple fará mudanças importantes sem levar em consideração mais ninguém, com certeza. Ter alguma documentação mais clara sobre seus planos para o Bitcode não melhora muito se assumirmos que eles são maliciosos ou simplesmente não se importam.

Mas eles claramente fizeram do Swift uma parte importante de sua plataforma e muitos milhares de desenvolvedores dependem dela, incluindo suas próprias equipes e alguns de seus parceiros mais importantes. O Swift é baseado no LLVM de código totalmente aberto e está sendo desenvolvido totalmente em aberto, incluindo a cadeia de ferramentas que o Xcode usa para gerar o bitcode que a apple aceita.

Então, para eles mudarem repentinamente esse formato sem que ninguém percebesse ou se importasse, exigiria que eles tornassem seus repositórios Swift e LLVM privados, certo? Certamente é possível, mas não me parece super provável.

Se a equipe Rust decidir que o risco disso é uma boa razão para não suportar bitcode, essa é certamente a prerrogativa deles. Eu ficaria um pouco triste com isso, mas não é minha função dizer aos outros onde gastar seu tempo.

Como não há absolutamente nenhuma garantia em torno do bitcode, isso pode se transformar em algo muito difícil de planejar. Imagine que eles decidiriam de uma versão para outra usar seu próprio formato de bitcode que não termina em uma versão de código aberto do LLVM.

A Apple lança o Xcode Beta no início de junho e a versão final em setembro. Após 6 a 9 meses, ele para de aceitar aplicativos compilados com versões mais antigas do Xcode na Appstore.

Acho que há tempo suficiente para preparar as alterações de bitcode durante essa linha do tempo.

Acabei de testar com o Xcode 10.2 beta 3 (que inclui o Swift 5 com LLVM 7) e pude vincular com um Rust recente todas as noites com bitcode incorporado. Obviamente, isso só funciona com destinos iOS, já que Rust não possui destinos watchOS/tvOS .

Eu também concordo que Rust precisa ser capaz de usar o fork Apple LLVM para todos os alvos relacionados à Apple para manter a compatibilidade de bitcode.

Sim, a janela de lançamento beta parece razoável. Acho que a ideia de que a Apple fechará o LLVM de origem ou seu formato de bitcode é muito improvável, mas a Apple exigindo bitcode em versões futuras do iOS definitivamente parece que isso acontecerá. E quem sabe, talvez eles até comecem a exigir bitcode para envios da Mac App Store com o projeto Marzipan.

O tipo de maneira não garantida de lidar com a compatibilidade proposta é reconhecidamente nojenta, mas acho que as plataformas móveis devem eventualmente se tornar plataformas Tier 1 , especialmente para casos em que você teria usado C++ de outra forma, como para o desenvolvimento de videogames. Além disso, você também pode desenvolver jogos com Rust para a Apple TV.

Espero que uma abordagem oficialmente sancionada pela equipe do compilador incentive alguém a trabalhar nisso, mas acho que um comentário anterior de @brson resume a hesitação:

Mantemos com sucesso a compatibilidade entre várias versões do LLVM. Contanto que a Apple e a nossa não se afastem muito, deve ser factível, mas sempre há o risco de uma quebra tão grande que a divisão não pode ser cruzada

Ou talvez o bitcode se estabilize no futuro e todos nós vamos esquecer que esse debate aconteceu 🙏

Vou comer meu chapéu agora 😞

Em que eu disse:

a ideia de que a Apple fechará o LLVM de origem ou seu formato de bitcode é muito improvável

O que foi principalmente em resposta à desconfiança expressa por @mitsuhiko :

Imagine que eles decidiriam de uma versão para outra usar seu próprio formato de bitcode que não termina em uma versão de código aberto do LLVM.

Mas se você observar a questão #48833 , definitivamente há um precedente. Como @comex escreveu anteriormente:

houve casos em que os recursos aparecem no LLVM do Xcode antes do tronco LLVM - como toda a porta arm64, quando foi originalmente desenvolvida, porque a Apple queria manter em segredo que eles planejavam enviar dispositivos arm64

E a história de @michaeleiselsc da mesma edição:

um aplicativo em que eu estava trabalhando foi duramente atingido por reinicializações aleatórias em dezembro de 2016 e é causado por um problema específico que o LLVM de código aberto corrigiu apenas em dezembro de 2017. Quando passamos do LLVM de código aberto para o LLVM da Apple em dezembro de 2016, o problema foi corrigido

Dado que a ideia é usar o LLVM da Apple com Rust, não parece tão ruim, mas definitivamente existe o risco de ter um bug desagradável ocasional por causa de implementações divergentes 😢. Não é um risco que todos os projetos podem assumir. Transpilar parece uma opção melhor neste momento, mas até agora, não parece tão possível .

Ainda acho que o uso do LLVM da Apple deve ser suportado, mas deve haver avisos claros na documentação explicando que não há garantias de que as coisas continuarão funcionando (A Tier 1.5 ou algo assim).

Kotlin/Nativo. A JetBrains está considerando as plataformas móveis como uma prioridade e, embora tenha demorado um pouco e seja apenas marcadores de bitcode (ainda não é um bitcode completo), é bom o suficiente para começar a trabalhar - veja JetBrains/kotlin-native#1564 e JetBrains/kotlin-native# 1202 (comentário)

Obrigado por apontar isso @oleksandr-yefremov! Eu cavei um pouco mais e consegui replicar a abordagem kotlin/native em golang . Acredito que vocês deveriam poder fazer o mesmo, o que permitiria o uso de ferrugem em aplicativos iOS/tvOS/watchOS habilitados para bitcode sem necessariamente emitir bitcode.

O bitcode funciona agora? Alguém tentou?

@volodg Eu sou um novato em ferrugem. No entanto, executei este tutorial com a última ferrugem todas as noites (no momento em que escrevi rustc 1.37.0-nightly (088b98730 2019-07-03) ) e NÃO funcionou.

Parece que os marcadores estão lá..

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

Mas recebo o seguinte erro ao compilar para o dispositivo iOS (o simulador funciona):

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)

Isso é o máximo que eu tenho.

Consegui vincular rustc nightly-2019-09-05 aarch64-apple-ios and rustflags = "-C lto -Z embed-bitcode" staticlib com clang-1100.0.33.5 (Xcode 11 beta 7) and -fembed-bitcode app. O código-fonte é https://github.com/saturday06/rust-ios-bitcode-test .

  • Você sabe se a seção __cmdline é necessária?

Dois anos depois, posso responder a isso - para implantar em dispositivos físicos ou criar arquivos Xcode, um cmdline vazio é bom, no entanto, para envios da App Store, a Apple executa a validação da linha de comando clang. Eu coloquei uma descrição mais longa neste PR, que inclui um patch hacky para fazê-lo funcionar: https://github.com/getditto/rust-bitcode/pull/7

Eu gostaria de upstream isso de alguma forma, mas as opções não são atraentes. Criamos algumas opções de clang ao segmentar o iOS? Fornecemos um envvar para escolher exatamente como mentir caso a Apple altere suas regras de validação? Eu ficaria feliz em fazer a mudança se houver uma escolha razoável aqui.

-Cembed-bitcode=no não funciona para o destino ios. ainda há uma seção de bitcode em um arquivo .a
como construir sem bitcode?

Esta página foi útil?
0 / 5 - 0 avaliações