Draft: Compile LFortran itself to WASM
Current status: everything compiles (without LLVM) and few simple things disabled.
Steps to compile:
-
Install emscripten using: https://emscripten.org/docs/getting_started/downloads.html, it should work on all platforms. I tested on Apple M1. No root required.
-
./build0.sh
(as usual) -
Load emscripten using
source ./emsdk_env.sh
(per the downloads manual) and:
emcmake cmake \
-DCMAKE_BUILD_TYPE=Debug \
-DWITH_LLVM=no \
-DLFORTRAN_BUILD_ALL=yes \
-DWITH_STACKTRACE=no \
-DCMAKE_PREFIX_PATH="$CMAKE_PREFIX_PATH_LFORTRAN;$CONDA_PREFIX" \
-DCMAKE_INSTALL_PREFIX=`pwd`/inst \
.
cmake --build . -j16 --target install
Everything will compile. It fails while compiling the Fortran part of the runtime library because the lfortran
executable does not exist. It creates lfortran.js
and lfortran.wasm
.
To run, this currently fails:
$ node src/bin/lfortran.js -- -h
/Users/certik/repos/lfortran/lfortran/src/bin/lfortran.js:141
throw ex;
^
5555320 - Exception catching is disabled, this exception cannot be caught. Compile with -s NO_DISABLE_EXCEPTION_CATCHING or -s EXCEPTION_CATCHING_ALLOWED=[..] to catch.
(Use `node --trace-uncaught ...` to show where the exception was thrown)
Not sure if it is supposed to work.
The main step now is to figure out how to actually run it, first locally and then in the browser.
Given that we skipped LLVM, we might need to write our own WASM backend in LFortran.
Exceptions I think don't work, but we don't need exceptions at this point. They are only used to report compiler errors and only locally and we can rework it not to need them at all.
Merge request reports
Activity
mentioned in merge request !1385 (closed)
I just had to enable exceptions. Now it works:
$ node src/lfortran/tests/test_lfortran.js [doctest] doctest version is "2.3.4" [doctest] run with "--help" for options =============================================================================== /Users/certik/repos/lfortran/lfortran/src/lfortran/tests/test_serialization.cpp:194: TEST CASE: ASR Tests /Users/certik/repos/lfortran/lfortran/src/lfortran/tests/test_serialization.cpp:194: ERROR: test case THREW exception: Cannot determine executable path. =============================================================================== [doctest] test cases: 45 | 44 passed | 1 failed | 0 skipped [doctest] assertions: 450 | 450 passed | 0 failed | [doctest] Status: FAILURE!
The executable path does not work because I disabled it in this MR.
It seems that everything actually works! One can see the test results with:
$ node src/lfortran/tests/test_lfortran.js -s [...] /Users/certik/repos/lfortran/lfortran/src/lfortran/tests/test_serialization.cpp:114: SUCCESS: CHECK( LFortran::pickle(*asr) == LFortran::pickle(*asr2) ) is correct! values: CHECK( (TranslationUnit (SymbolTable 16 {a: (Module (SymbolTable 17 {b: (Subroutine (SymbolTable 18 {}) b [] [(Print () [(ConstantString "b()" (Character 1 3 () []))])] Source Public Implementation ())}) a [] .false.)}) []) == (TranslationUnit (SymbolTable 16 {a: (Module (SymbolTable 17 {b: (Subroutine (SymbolTable 18 {}) b [] [(Print () [(ConstantString "b()" (Character 1 3 () []))])] Source Public Implementation ())}) a [] .false.)}) []) ) [...]
Everything looks good.
Now tests pass:
$ node src/lfortran/tests/test_lfortran.js [doctest] doctest version is "2.3.4" [doctest] run with "--help" for options =============================================================================== [doctest] test cases: 45 | 45 passed | 0 failed | 0 skipped [doctest] assertions: 454 | 454 passed | 0 failed | [doctest] Status: SUCCESS!
We should now set this up at a CI, and then slowly integrate all the fixes into master and add the CI test into master.
The main thing missing is the Fortran runtime library. Emscripten allows to embed files, I think we should just do that.
Then we should write a webapp that allows to paste code and then to show AST and ASR out of it. Then we can test how fast it is and that everything works.
Then we need to either get LLVM working or write our own webassembly backend, assuming one can generate WASM on the fly from the browser and then execute. Otherwise we need to interpret the ASR in some way, so that one can create a XEUS kernel.
added 11 commits
- bbb3a137 - This reduces the WASM size from 19MB to 1.1MB
- 326af8df - Export a function
- e1fa1df1 - Turn off -Oz for now
- dea005fc - Export to C
- e2fcbf51 - Add a JS driver
- 5a06f63b - Use the minimal shell
- 656655a5 - Add an example with an argument
- 3c13ade9 - Pass strings
- b91f71b2 - Return a string
- 3cd92609 - Make it work with cwrap
- 9d25bad3 - Call LFortran
Toggle commit listI pushed the generated files into https://gitlab.com/certik/lfortran/-/commits/wasm_online and they serve at:
mentioned in issue #583
mentioned in merge request !1705 (closed)
mentioned in merge request !1796 (merged)
This has been merged as part of !1796 (merged).