Rust: Заставьте Rust работать с emscripten

Созданный на 18 апр. 2012  ·  30Комментарии  ·  Источник: rust-lang/rust

Я потратил некоторое время, пытаясь решить эту проблему, и теперь rustc генерирует код, который может переводить emscripten, но скомпилированный javascript дает сбой, когда попадает в функцию времени выполнения. Следующим шагом является создание среды выполнения с использованием emcc в качестве компилятора. Уберите все, что не работает, за EMSCRIPTEN ifdefs.

Emscripten добавляет способ обработки встроенной сборки как javascript, поэтому все части среды выполнения, которые не создаются с помощью emscripten, могут быть реализованы встроенно с помощью javascript.

В качестве альтернативы мы могли бы повторно реализовать среду выполнения по частям в javascript и вообще не беспокоиться о ее компиляции из C ++. Такой подход не рекомендуется.

A-runtime E-hard

Самый полезный комментарий

Я прилагаю огромные усилия по сортировке, чтобы подготовить нас к версии 1.0. В рамках этого я перемещаю вещи, похожие на списки желаний, в репозиторий RFC, так как именно здесь следует обсуждать / расставлять приоритеты по основным новым вещам.

Этот вопрос был перемещен в репозиторий RFC: rust-lang / rfcs # 604.

Все 30 Комментарий

См. Также №3608.

Все равно было бы хорошо; не на каком-либо этапе зрелости.

Все равно было бы неплохо, но это не очень важно. Это должно стать проще, поскольку большая часть среды выполнения переписывается в ржавчине.

Теперь, когда среда выполнения написана на Rust, как это меняет перспективы для этой ошибки? Насколько сложно было бы запустить Hello World без времени выполнения через emscripten?

Теперь не должно быть особенно сложно добавить действительно хорошую поддержку для emscripten. Он уже в значительной степени работает с rust-core. В компиляторе нам нужно добавить поддержку правильной целевой тройки, правильно настроить различные целевые атрибуты, а затем отгородить несколько частей среды выполнения, которые в настоящее время не могут работать в js, потоковой передаче и переключении контекста.

Когда режим планирования 1: 1 станет немного более зрелым, мы сможем даже добавить поддержку задач через веб-воркеров, хотя в настоящее время для этого потребуется другое решение для передачи сообщений. В зависимости от того, какая поддержка параллелизма будет добавлена ​​в js / emscripten, в конечном итоге мы сможем точно поддерживать семантику передачи сообщений rust.

@brson : Я думаю, что # 10780 будет самым большим блокировщиком на данный момент. Rust будет выводить посадочные площадки с вызовами для обновления размера, используемого для обеспечения безопасности стека, с помощью поддержки сегментированного стека LLVM.

Благодаря -Z no-landing-pads теперь все работает нормально! Добавление явной поддержки этого в стандартную библиотеку возможно, но большинство из них все равно не будет работать (файлы, tcp, udp и т. Д.), Поэтому я не думаю, что это необходимо. Если и когда стандартная библиотека получит автономную поддержку, она начнет работать, и мы сможем открыть больше проблем в зависимости от функциональности, которую мы можем сопоставить с JavaScript.

Если все в порядке, я бы хотел пока оставить это открытым. Я думаю, что это будет хорошим шагом вперед к тому, чтобы стандартная библиотека была расширяемой и могла работать на любом количестве платформ.

Я согласен с тем, что большая часть работы, вероятно, уже сделана, и для этого, вероятно, потребуется libemscripten для обеспечения ввода-вывода, специфичного для emscripten, но я думаю, что на этом пути может возникнуть достаточно проблем, поэтому от этого стоит отказаться вопрос открыт (это все еще интересный проект!)

@alexcrichton : невозможно обеспечить параллелизм и поддержку ввода-вывода стандартной библиотеки для emscripten. В лучшем случае он мог выводить на консоль для stdout / stderr. Я не могу придумать в стандартной библиотеке ничего, что было бы хорошей идеей для цели emscripten, но не автономной, помимо реализации распределителя по умолчанию.

Обновление статуса:

@alexcrichton Реорганизовал стандартную библиотеку в кучу меньших библиотек с более понятными зависимостями. Теперь должно быть почти тривиально скомпилировать библиотеки core, alloc, rand и collections в Интернет.

Вот как я бы посоветовал решить эту проблему:

  • Проведите несколько экспериментов с инструментами rust и LLVM, чтобы понять, как работает кодогенератор для кросс-компиляции в asm.js.
  • Создайте libcore с помощью emscripten вручную и докажите, что он работает в Интернете.
  • Измените rustc и mk / platform.mk, чтобы понять целевую тройку, специфичную для emscripten, создать цепочку инструментов кросс-компиляции, которая не содержит ничего, кроме libcore.rlib.
  • Решите проблему liballoc, разрешив ему работать с системным (в данном случае предоставленным emscripten) malloc, а затем с другими ящиками, не требующими выполнения.

Хорошее начало!

Хорошо, я попробовал с первых шагов, и, очевидно, сразу же возникли проблемы.

Я скомпилировал libcore в битовый код с помощью --emit bc , и при попытке скомпилировать его с помощью emcc -O0 я получаю:

/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:

Не уверен, что могу что-нибудь с этим сделать, или это потому, что мы не можем использовать для этого вывод rustc --emit .

Извините, если это не место, чтобы комментировать это ...

Я также пробовал с libnum , более простым, и bc генерируется правильно, но во время процесса emcc я получаю предупреждение об использовании неправильной тройки и полученного результата. js не имеет никаких функций внутри libnum , поэтому я думаю, что я здесь слишком наивен :)

@Arcnor Вы можете спросить некоторых из тех, кто ранее компилировал простые тесты с помощью emscripten, об их процессе. У меня есть только несколько идей.

  • Битовый код LLVM меняется от версии к версии, и версия, которую использует Rust, не всегда совпадает с emscripten. Получение их обоих с использованием относительно похожей версии LLVM может улучшить совместимость.
  • Судя по вашему сообщению об ошибке, вы используете новый серверный модуль fastcomp от emscripten. Это может быть менее протестировано на рабочих нагрузках Rusty, чем их старый бэкэнд. Включение старого серверного интерфейса вручную может по крайней мере привести к другим результатам.
  • Emscripten обычно использует свою собственную тройку целей, поэтому, возможно, придется добиваться ее использования в rustc.

Ошибка при попытке скомпилировать libcore похоже, связана с этой проблемой emscripten. Компиляция libcore в байт-код llvm генерирует атомарные инструкции llvm, но emscripten не поддерживает атомарные инструкции.

Возможно, есть способ обойти это со стороны ржавчины, но, основываясь на комментариях в проблеме emscripten, я думаю, что поддержка атомики в emscripten имеет наибольший смысл.

Если у emscripten есть своя собственная платформа, мы могли бы, возможно, исключить все атомики для их однопоточных вариантов, но я согласен, что было бы лучше иметь это в восходящем потоке emscripten!

Если я не ошибаюсь, новый backend emscripten "fastcomp" является форком LLVM (в то время как предыдущий backend был просто уровнем выше LLVM), поэтому LLVM-версию fastcomp, вероятно, сложно обновить, и она не будет обновлена. часто.

Это будет проблематично, если потребуется совместимость с выходными данными Rust. Например, сейчас версия fastcomp для LLVM - 3.3, а LLVM, используемая Rust, - 3.4.

Старый серверный модуль emscripten устарел и не должен использоваться в соответствии с официальной документацией, поэтому, вероятно, его нельзя использовать.

Кажется, на данный момент я единственный, кто пытается скомпилировать для emscripten.

Для справки, вот что я пробовал:

  • Компиляция в байт-код (сгенерированный Rust LLVM 3.4) и передача его в fastcomp (форк LLVM 3.3); вызывает сбой fastcomp
  • Компиляция в IR, редактирование вручную до совместимости с LLVM 3.3 и передача в fastcomp; слишком сложно, слишком много вещей, которые нужно изменить для любого нетривиального кода
  • Компиляция Rust stage1 с указанием --llvm-root на fastcomp от emscripten; это не сработало, потому что они удалили поддержку ARM / MIPS / и т. д. в их вилке (из-за этого я получаю ошибки из make-файлов и во время компоновки)
  • Измените подмодуль LLVM git в исходном коде Rust, чтобы он указывал на старую фиксацию эпохи 3.3; получение в какой-то момент segfault в LLVM
  • Компиляция Rust с указанием --llvm-root на предварительно скомпилированный LLVM 3.3 (взятый из официального репозитория ubuntu); получение подтверждения не удалось в конце компиляции stage1, и созданный двоичный файл rustc не работает.

Если у кого-то нет идеи, я пришел к выводу, что нам нужно дождаться обновления emscripten.

ром вроде как работает; возможно это поможет

Незначительное обновление: emscripten-fastcomp обновлен до LLVM 3.4 и будет обновлен до LLVM 3.5 позже.

@tomaka вы пробовали что-нибудь делать с версией 3.4? Мне удалось получить пример рома, скомпилированного с ним, но что-то еще не удалось с непонятными ошибками.

@ibdknox 3.4 несовместим с 3.5
Даже простой привет мир дает ошибочное утверждение: LLVM ERROR: 0 && "some i64 thing we can't legalize yet"

Хм. Мне удалось взять вывод из rustc --emit ir foo.rust и запустить его через emscripten-incoming. На LLVM 3.5 теперь есть ржавчина?

Rust давно использует LLVM 3.5. Вам может повезти, и вы не получите ничего несовместимого.
Например, это прекрасно компилируется:

#[start]
fn main(_: int, _: *const *const u8) -> int {}

Это не из-за несовместимого IR:

fn main() { println!("hello world"); }

@ibdknox http://www.reddit.com/r/rust_gamedev/comments/2n0x08/emscripten_experiments/
Похоже, несовместимости меньше, чем я думал.

В качестве обновления, когда я компилирую hello world с emscripten, который теперь обновлен до версии 3.5, я получаю следующее:

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:

Вот как я компилирую:

rustc --target i686-apple-darwin -C lto --emit ir foo.rust
emcc -v foo.ll -o test.html

Вещи, которые, кажется, не приносят результатов, обычно работают.

На прошлой неделе я проводил свободное время, изучая это. Я читал книгу Руста где-то между летом и сейчас, и мне очень понравилась механика языка, но только недавно я начал что-то с ней реализовывать. Я осведомлен о компиляторе ржавчины ровно настолько, насколько я узнал на этой неделе, но надеюсь, что смогу внести свой вклад.

Итак, я думаю, первое, что нужно отметить из того, что я узнал (но на это у меня ушло несколько вечеров), это то, что Rust перешел на LLVM 3.6 в июле. Таким образом, текущие версии Rust и emscripten-fastcomp несовместимы.

Я попытался скомпилировать ржавчину с помощью --llvm-root указывающего на emscripten-fastcomp 1.29.2, и получил эту ошибку:

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

Чтобы добраться до этой ошибки, я настроил и построил emscripten-fastcomp с

../configure --enable-optimized --disable-assertions --enable-targets=host,js,arm,aarch64,mips

Вместо рекомендованного руководства emscripten

../configure --enable-optimized --disable-assertions --enable-targets=host,js

Хотя Rust не нужно собирать для всех целей, в настоящее время он всегда связывается с LLVM с поддержкой ЦП, скомпилированной для всех целей. Это обходной путь для проблемы, которая может быть исправлена ​​в будущем, поэтому нам, возможно, не нужно всегда компилировать emscripten-fastcomp с этой конфигурацией.

Как только я обнаружил, что Rust перешел на LLVM 3.6, я нашел последнюю ветку на rust-lang / llvm, которая была LLVM 3.5. https://github.com/rust-lang/llvm/tree/rust-llvm-2014-07-24 Я скомпилировал это вместо emscripten-fastcomp, любопытно посмотреть, что получится. Я получил ту же самую ошибку при компиляции против emscripton-fastcomp недавнего перехода на LLVM 3.5. Я считаю, что это означает, что Rust сейчас в некотором роде несовместим с LLVM 3.5, и я не ожидал бы иного.

Итак, теперь мы ждем или нам нужно получить emscripten-fastcomp для LLVM 3.6: wink:

Стоит упомянуть, что я загрузил заархивированную копию 0.11 и смог создать LLVM IR для hello world, который emcc понял, но затем столкнулся с проблемой связывания. Было довольно интересно увидеть, как он ушел из понимания байтового кода, но для того, чтобы на самом деле связать его, потребуется доработать базу кода ржавчины.

Я взглянул на слияние rust-lang / llvm с emscripten-fastcomp. На тот момент насчитывалось 117 конфликтующих разделов над 43 файлами.

Я уже упоминал о получении Rust 0.11 и emcc 1.29.2, чтобы перейти на этап компоновки. Это конкретный результат:

$ 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

Кажется, что emcc / fastcomp заменяет точки в символах символами подчеркивания, в то время как Rust ожидает префикса с другим подчеркиванием, но я не уверен в этом. Первый неразрешенный символ отображается как __ZN2io5stdio12println_args20h0caae70b0e2eb347Iol7v0.11.0E в libstd сборки i686-apple-darwin. Даже если бы я мог заставить emcc узнать, как найти этот символ во встроенных библиотеках, я предполагаю, что библиотеки содержат машинный код, а emcc потребуются байтовые коды LLVM. Я помню, как кто-то упоминал о необходимости скомпилировать стандартную библиотеку для emscripten. Это было бы частью потребности в этом.

Итак, вот следующие шаги, над которыми я хочу поработать, если кто-то захочет попробовать себя в этом. (Или можете сообщить, насколько я прав или нет.)

  • Слияние rust-lang / llvm с emscripten-fastcomp
  • Создайте ржавчину с помощью объединенного fastcomp без поддержки JS-сервера
    Надеюсь, это будет хорошей проверкой на разумность слияния.
  • Добавьте тройку emscripten в Rust и создайте ее
    Насколько я могу судить, есть ряд файлов, которые мне нужно изменить или добавить.

    • мк / cfg / asmjs-unknown-emscripten.mk

    • rt / arch / asmjs / {morestack.S, record_sp.S} (может быть пустым?)

      Эти файлы необходимы для создания morestack.a, чтобы Rust поддерживал сегментированный стек LLVM. Если я правильно помню, стек Emscripten также является головным. Он использует противоположный конец кучи в качестве стека, и поскольку для asmjs вы не можете изменить размер массива, создание новых сегментов стека невозможно. Я видел поле в TargetOption в целевых файлах librustc_back, которое, надеюсь, может отключить это.

    • librustc_trans / trans / cabi_asmjs.rs

    • librustc_trans / транс / cabi.rs

      Я не уверен, понадобятся ли они, пока только догадываюсь.

    • librustc_back / target / asmjs_unknown_emscripten.rs

    • librustc_back / asmjs.rs

    • librustc_syntax / abi.rs

    • librustc_back / назад / write.js configure_llvm ()

    • librustc_llvm / lib.rs static_link_hack_this_sucks ()

  • Реализовать отсутствующие системные интерфейсы
    Я видел, что в ноябре была удалена libgreen. Поскольку emscripten нужно дождаться какого-либо способа поделиться с рабочими в браузерах, если это когда-либо произойдет, потребуется восстановить что-то вроде libgreen или каким-то образом наклеить pthread специально для emscripten, например, как ржавчина строит для pthreads или api потоков Windows.

IO тоже. Возможно, другие части, о которых я не знаю.

"Слить rust-lang / llvm с emscripten-fastcomp"

Возможно, вы не захотите этого делать - Emscripten основан на pnacl-llvm / pnacl-clang, поэтому вы создаете вилку с патчами на патчах, что, вероятно, будет болезненным. Если вам интересно, вы можете увидеть некоторые детали ветвления в исследовании, которое я провел для слияния Emscripten с r33 -> r34 на https://github.com/kripken/emscripten-fastcomp/issues/51#issuecomment -62323164 .

Я слышал, что pnacl планирует отслеживать восходящий поток немного ближе, чем раньше, но я не вижу какой-либо соответствующей проблемы в системе отслеживания проблем pnacl для обновления до версии 3.6, так что это может занять некоторое время (особенно учитывая, что версия 3.6 была разветвлена ​​всего 5 дней назад!). .. Думаю, вы могли создать проблему? Если вы решите не использовать собственный форк Emscripten, я вижу два варианта - дождаться pnacl или помочь Emscripten выйти из pnacl и перейти на апстрим.

Изменить: исправлено «сейчас» на «нет». Решающая разница.

Я прилагаю огромные усилия по сортировке, чтобы подготовить нас к версии 1.0. В рамках этого я перемещаю вещи, похожие на списки желаний, в репозиторий RFC, так как именно здесь следует обсуждать / расставлять приоритеты по основным новым вещам.

Этот вопрос был перемещен в репозиторий RFC: rust-lang / rfcs # 604.

Была ли эта страница полезной?
0 / 5 - 0 рейтинги