Passei algum tempo investigando esse problema e agora o rustc gera código que o emscripten pode traduzir, mas o javascript compilado falha quando atinge uma função de tempo de execução. A próxima etapa é começar a construir o tempo de execução usando emcc
como compilador. Elimine todas as coisas que não são construídas por trás de EMSCRIPTEN
ifdefs.
Emscripten está adicionando uma maneira de tratar a montagem embutida como javascript, então todas as partes do tempo de execução que não são construídas com emscripten podem ser implementadas embutidas com javascript.
Como alternativa, poderíamos reimplementar o tempo de execução aos poucos em javascript e não nos incomodar em compilá-lo em C ++. Essa abordagem não é recomendada.
Veja também # 3608.
Ainda seria bom; não em qualquer marco de maturidade.
Ainda seria bom, mas não é muito importante. Isso deve ficar mais fácil, já que muito do tempo de execução está sendo reescrito em ferrugem.
Veja também https://github.com/mozilla/rust/issues/7282
Agora que o tempo de execução foi escrito em Rust, como isso muda as perspectivas desse bug? Seria muito difícil fazer um Hello World sem tempo de execução rodar por meio do emscripten?
Não deve ser particularmente difícil adicionar um suporte realmente bom para emscripten agora. Já funciona muito bem com núcleo de ferrugem. No compilador, precisamos adicionar suporte para o triplo de destino adequado, configurar os vários atributos de destino corretamente e, em seguida, isolar as poucas partes do tempo de execução que atualmente não podem funcionar em js, threading e troca de contexto.
Uma vez que o modo de agendamento 1: 1 amadurece um pouco mais, podemos até ser capazes de adicionar suporte para tarefas por meio de web workers, embora atualmente isso requeira uma solução diferente de passagem de mensagens. Dependendo de qual suporte de paralelismo é adicionado a js / emscripten, podemos eventualmente ser capazes de suportar a semântica de passagem de mensagem de rust com precisão.
@brson : Acho que # 10780 seria o maior bloqueador no momento. O Rust produzirá bases de aterrissagem com chamadas para atualizar o tamanho usado para fazer a segurança da pilha por meio do suporte de pilha segmentada do LLVM.
Graças a -Z no-landing-pads
agora funciona bem! Adicionar suporte explícito para isso à biblioteca padrão é possível, mas a maioria não vai funcionar de qualquer maneira (arquivos, tcp, udp, etc.), então não acho que seja necessário. Se e quando a biblioteca padrão obter suporte independente, ela começará a funcionar e podemos abrir mais problemas com base na funcionalidade que podemos mapear para JavaScript.
Se estiver tudo bem, gostaria de deixar em aberto por enquanto. Acho que fazer isso seria um bom passo para garantir que a biblioteca padrão seja extensível e capaz de rodar em qualquer número de plataformas.
Eu concordo que a maior parte do trabalho provavelmente está concluída, e isso provavelmente precisará de libemscripten
para fornecer E / S específica do emscripten, mas acho que pode haver empecilhos suficientes no caminho que vale a pena deixar o problema aberto para (ainda é um projeto interessante!)
@alexcrichton : Não será possível fornecer a simultaneidade da biblioteca padrão e o suporte de E / S para emscripten. Na melhor das hipóteses, ele pode enviar saída para o console para stdout / stderr. Não consigo pensar em nada na biblioteca padrão que seja uma boa ideia para um destino emscripten, mas não independente, além de uma implementação de alocador padrão.
Atualização de status:
@alexcrichton Refatorou a biblioteca padrão em um monte de bibliotecas menores com dependências mais compreensíveis. Deve ser quase trivial obter as bibliotecas core, aloc, rand e coleções para compilar na web agora.
Aqui está como eu sugeriria lidar com isso:
É um bom começo!
Ok, então tentei com os primeiros passos e obviamente tive problemas logo de cara.
Compilei libcore
para o código de bits com --emit bc
e, ao tentar compilá-lo com emcc -O0
, obtive:
/Users/arcnor/emscripten-fastcomp/build/bin/llvm-nm: /tmp/tmpfTkmfj/core_0.o: Invalid CMPXCHG record.
/Users/arcnor/emscripten-fastcomp/build/bin/opt: /tmp/tmpfTkmfj/core.bc: error: Invalid CMPXCHG record
Traceback (most recent call last):
File "/Users/arcnor/emscripten/emcc", line 1573, in <module>
shared.Building.llvm_opt(final, link_opts)
File "/Users/arcnor/emscripten/tools/shared.py", line 1335, in llvm_opt
assert os.path.exists(target), 'Failed to run llvm optimizations: ' + output
AssertionError: Failed to run llvm optimizations:
Não tenho certeza se posso fazer algo sobre isso, ou é porque não podemos usar a saída rustc --emit
para isso.
Desculpe se este não é o lugar para comentar sobre isso ...
Também tentei com libnum
, um mais simples, e bc
gera corretamente, mas recebo um aviso durante o processo emcc
sobre o uso do triplo errado e o resultante. js não tem nenhuma das funções dentro de libnum
, então acho que estou sendo muito ingênuo aqui :)
@Arcnor Você pode perguntar a alguns daqueles que já compilaram testes simples com emscripten sobre seu processo. Eu só tenho algumas idéias.
O erro ao tentar compilar libcore
parece estar relacionado a este problema de emscripten. Compilar libcore
para bytecode llvm gera instruções atômicas llvm, mas emscripten não suporta instruções atômicas.
Pode haver uma maneira de contornar isso do lado da ferrugem, mas com base nos comentários na edição do emscripten, acho que fazer mais sentido obter suporte para atômicos no emscripten.
Se o emscripten tiver sua própria plataforma, poderíamos talvez cfg-out de todos os atômicos para suas variantes single-threaded, mas eu concordo que seria melhor ter isso no emscripten upstream!
Se não me engano, o novo backend "fastcomp" do emscripten é um fork do LLVM (enquanto o backend anterior era apenas uma camada acima do LLVM), então a versão LLVM do fastcomp provavelmente é difícil de atualizar e não será atualizada freqüentemente.
Isso será problemático se precisar ser compatível com a saída do Rust. Por exemplo, agora a versão LLVM de fastcomp é 3.3, enquanto o LLVM usado por Rust é 3.4.
O antigo backend emscripten está obsoleto e não deve ser usado de acordo com os documentos oficiais, então provavelmente não é uma opção de usá-lo.
Parece que sou o único tentando compilar para o emscripten no momento.
Para registro, aqui estão as coisas que experimentei:
--llvm-root
apontado para fastcomp do emscripten; que não funcionou porque eles removeram o suporte para ARM / MIPS / etc. em seu fork (estou recebendo erros dos makefiles e durante a vinculação por causa disso)--llvm-root
apontou para um LLVM 3.3 pré-compilado (vindo do repositório oficial do Ubuntu); a obtenção de uma declaração falhou no final da compilação do stage1 e o binário rustc produzido não funciona.A menos que alguém tenha uma ideia, minha conclusão é que precisamos esperar a atualização do emscripten.
parece que está funcionando com rum , sorta; talvez isso ajude
Atualização secundária: emscripten-fastcomp foi atualizado para LLVM 3.4 e será atualizado para LLVM 3.5 posteriormente.
@tomaka , você já tentou fazer alguma coisa com a versão 3.4? Consegui compilar o exemplo do rum com ele, mas qualquer outra coisa falhou com erros ininteligíveis.
@ibdknox 3.4 é incompatível com 3.5
Mesmo um simples hello world produz uma afirmação falhada: LLVM ERROR: 0 && "some i64 thing we can't legalize yet"
Hm. Consegui pegar a saída de rustc --emit ir foo.rust
e executá-la por meio do emscripten-coming. A ferrugem está agora no LLVM 3.5?
Rust já usa o LLVM 3.5 há muito tempo. Você pode ter sorte e não gerar nada incompatível.
Por exemplo, isso compila perfeitamente:
#[start]
fn main(_: int, _: *const *const u8) -> int {}
Isso não acontece por causa de IR incompatível:
fn main() { println!("hello world"); }
@ibdknox http://www.reddit.com/r/rust_gamedev/comments/2n0x08/emscripten_experiments/
Parece que existem menos incompatibilidades do que eu pensava.
Como atualização, quando compilo hello world com emscripten que agora foi atualizado para 3.5, recebo o seguinte:
Value: %28 = call fastcc { i8, [0 x i8], [0 x i8] } @_ZN3fmt5write20h2c56fdda0b308d94DFAE({ i8*, void (i8*)** }* noalias nocapture dereferenceable(8) %arg.i, %"struct.core::fmt::Arguments[#3]"* noalias nocapture readonly dereferenceable(24) %__args31), !noalias !22
LLVM ERROR: Unrecognized struct value
Traceback (most recent call last):
File "/Users/chris/Downloads/emsdk_portable/emscripten/incoming/emcc", line 1259, in <module>
shared.Building.llvm_opt(final, link_opts)
File "/Users/chris/Downloads/emsdk_portable/emscripten/incoming/tools/shared.py", line 1401, in llvm_opt
assert os.path.exists(target), 'Failed to run llvm optimizations: ' + output
AssertionError: Failed to run llvm optimizations:
Aqui está como estou compilando:
rustc --target i686-apple-darwin -C lto --emit ir foo.rust
emcc -v foo.ll -o test.html
Coisas que não parecem trazer fmt geralmente parecem funcionar, no entanto.
Passei meu tempo livre na semana passada investigando isso. Eu li o livro do ferrugem entre o verão e agora e gostei muito da mecânica da linguagem, mas só recentemente comecei a implementar algo com ela. Tenho tanto conhecimento sobre o compilador de ferrugem quanto o que aprendi esta semana, mas espero poder contribuir.
Portanto, acho que a primeira coisa a notar do que aprendi (mas isso me levou algumas noites para perceber) é que Rust mudou para o LLVM 3.6 em julho. Portanto, as versões atuais de Rust e emscripten-fastcomp são incompatíveis.
Tentei compilar a ferrugem com --llvm-root
apontando para emscripten-fastcomp 1.29.2 e recebi este erro:
rustc: x86_64-apple-darwin/stage2/lib/rustlib/x86_64-apple-darwin/lib/libcore
error: internal compiler error: unexpected panic
note: the compiler unexpectedly panicked. this is a bug.
note: we would appreciate a bug report: http://doc.rust-lang.org/complement-bugreport.html
note: run with `RUST_BACKTRACE=1` for a backtrace
thread 'rustc' panicked at 'assertion failed: self.raw.hash != self.hashes_end', /Users/zen/Code/rust/src/libstd/collections/hash/table.rs:776
make: *** [x86_64-apple-darwin/stage2/lib/rustlib/x86_64-apple-darwin/lib/stamp.core] Error 101
Para obter este erro, configurei e construí emscripten-fastcomp com
../configure --enable-optimized --disable-assertions --enable-targets=host,js,arm,aarch64,mips
Em vez do guia do emscripten recomendado
../configure --enable-optimized --disable-assertions --enable-targets=host,js
Embora o Rust não precise ser construído para todos os destinos, atualmente ele sempre se vincula ao LLVM com suporte de CPU compilado para todos os destinos. Esta é uma solução alternativa para um problema que pode ser corrigido no futuro, portanto, nem sempre precisamos compilar o emscripten-fastcomp com essa configuração.
Assim que descobri que o Rust havia mudado para o LLVM 3.6, pesquisei o último branch em rust-lang / llvm que era o LLVM 3.5. https://github.com/rust-lang/llvm/tree/rust-llvm-2014-07-24 Compilei contra isso em vez de emscripten-fastcomp, curioso para ver o que aconteceria. Eu obtive exatamente o mesmo erro ao compilar em relação à mudança recente do emscripton-fastcomp para o LLVM 3.5. Eu entendo que isso significa que Rust é de alguma forma incompatível com o LLVM 3.5 agora e eu realmente não esperaria o contrário.
Portanto, agora esperamos ou temos que obter emscripten-fastcomp para LLVM 3.6: wink:
Vale a pena mencionar que eu baixei uma cópia arquivada de 0,11 e fui capaz de produzir IR LLVM para hello world que emcc
entendeu, mas depois cheguei ao problema de vinculação. Foi muito empolgante ver isso ultrapassar a compreensão do código de bytes, mas realmente conseguir vinculá-lo vai precisar de trabalho na base do código ferrugem.
Dei uma olhada na fusão de rust-lang / llvm em emscripten-fastcomp. Na época, havia 117 seções conflitantes em 43 arquivos.
Mencionei obter Rust 0.11 e emcc 1.29.2 para chegar ao estágio de vinculação. Este é o resultado específico:
$ emcc -v hello.ll -o hello.js
INFO root: (Emscripten: Running sanity checks)
WARNING: Linking two modules of different data layouts: '/Users/zen/.emscripten_cache/libc.bc' is 'e-p:32:32-i64:64-v128:32:128-n32-S128' whereas '/tmp/tmpv_yB8E/hello_0.o' is 'e-p:32:32-f64:32:64-f80:128-n8:16:32'
WARNING: Linking two modules of different target triples: /Users/zen/.emscripten_cache/libc.bc' is 'asmjs-unknown-emscripten' whereas '/tmp/tmpv_yB8E/hello_0.o' is 'i686-apple-darwin'
warning: incorrect target triple 'i686-apple-darwin' (did you use emcc/em++ on all source files and not clang directly?)
warning: unresolved symbol: _ZN2io5stdio12println_args20h0caae70b0e2eb347Iol7v0_11_0E
warning: unresolved symbol: _ZN10lang_start20h70f93b7d0a75f99atre7v0_11_0E
Parece que emcc / fastcomp substitui pontos em símbolos por sublinhados, enquanto Rust espera prefixar com outro sublinhado, mas não tenho certeza sobre isso. O primeiro símbolo não resolvido aparece como __ZN2io5stdio12println_args20h0caae70b0e2eb347Iol7v0.11.0E
em libstd na compilação i686-apple-darwin. Mesmo que eu pudesse fazer com que o emcc soubesse como encontrar esse símbolo nas bibliotecas construídas, estou supondo que as libs contêm código de máquina, enquanto o emcc precisará de códigos de byte LLVM. Acho que me lembro de alguém mencionando a necessidade de compilar a biblioteca padrão para o emscripten. Isso seria parte da necessidade disso.
Portanto, aqui estão as próximas etapas que procuro experimentar e trabalhar se alguém quiser tentar por conta própria. (Ou pode me dizer se estou certo ou errado.)
IO também. Provavelmente outras partes que não conheço.
"Merge rust-lang / llvm em emscripten-fastcomp"
Você pode não querer fazer isso - Emscripten é baseado em pnacl-llvm / pnacl-clang, então você está criando uma bifurcação com patches em patches, o que provavelmente será doloroso. Se estiver interessado, você pode ver alguns detalhes da ramificação na investigação que fiz para a mesclagem do Emscripten de r33 -> r34 em https://github.com/kripken/emscripten-fastcomp/issues/51#issuecomment -62323164 .
Ouvi dizer que o pnacl está planejando rastrear o upstream um pouco mais perto do que antes, mas não consigo ver nenhum problema relevante no rastreador de problemas do pnacl para atualizar para o 3.6, então pode demorar (especialmente dado o 3.6 ramificado apenas 5 dias atrás!). ..Acho que você poderia criar um problema? Se você decidir contra seu próprio fork do Emscripten, vejo duas opções - aguardar pelo pnacl ou ajudar o Emscripten a sair do pnacl e colocá-lo no upstream.
Editar: corrigido 'agora' para 'não'. Uma diferença crucial.
Estou fazendo um grande esforço de triagem para nos preparar para o 1.0. Como parte disso, estou movendo coisas que são como uma lista de desejos para o repositório RFCs, já que é onde as coisas novas importantes devem ser discutidas / priorizadas.
Este problema foi movido para o repositório RFCs: rust-lang / rfcs # 604
Comentários muito úteis
Estou fazendo um grande esforço de triagem para nos preparar para o 1.0. Como parte disso, estou movendo coisas que são como uma lista de desejos para o repositório RFCs, já que é onde as coisas novas importantes devem ser discutidas / priorizadas.
Este problema foi movido para o repositório RFCs: rust-lang / rfcs # 604