Compiling PYTHIA to WebAssembly
During the community bonding period, I’ll be compiling some physics simulation libraries using Emscripten, and running examples provided in their source code. I’ll be focusing on examples that need access to data files containing various physical parameters. This will be useful later on to test the CernVM-FS Emscripten backend I’ll be implementing.
I’ll be starting off with PYTHIA, which is a C++ library used for the simulation of high-energy physics events. You can download its source code from here. I used version 8.235.
Compiling
This is the simplest part. From the PYTHIA source code directory, run
$ emconfigure ./configure
$ emmake make
and you’re done!
This will fill up the tmp
directory with *.o
files. But these aren’t your usual ELF files.
$ file tmp/Analysis.o
tmp/Analysis.o: LLVM IR bitcode
The Emscripten compiler produced LLVM IR bitcode files, and packaged them up into a lib/libpythia8.a
archive file.
Running an example
Let’s run example 3, which is main03.cc
in the examples
directory. This program expects to find a main03.cmnd
input command file in it’s current directory when run, and also the directory of data files at <pythia-dir>/share/Pythia8/xmldoc
in the same location.
So from the examples
directory, run
$ emmake make main03
em++ main03.cc -o main03 -I../include -O2 -pedantic -W -Wall -Wshadow -fPIC -L../lib -Wl,-rpath,../lib -lpythia8 -ldl
$ file main03
main03: LLVM IR bitcode
We generated LLVM IR bitcode again. To produce the final target for the browser, run
$ mv main03 main03.bc
$ em++ main03.bc -o main03.html -O2 \
-s WASM=1 \
--preload-file main03.cmnd \
--preload-file ../share/Pythia8/xmldoc@<pythia-dir>/share/Pythia8/xmldoc \
-s TOTAL_MEMORY=50MB
Let’s break this down
- We had to rename
main03
because otherwiseem++
won’t recognise what type of file it is. -s WASM=1
will produce WASM instead of asm.js, which is the default.--preload-file main03.cmnd
will load this file into memory when it is accessed by the C++ program, and it will appear to be stored in the root directory for the program (which is also its current directory when it starts executing).--preload-file ../share/Pythia8/xmldoc@<pythia-dir>/share/Pythia8/xmldoc
is similar to the above, it loads the entirexmldoc
directory, but instead of it appearing at the root it will appear at the path specified after the@
, which is where the program expects to find it.-s TOTAL_MEMORY=50MB
sets the highest memory limit for the program, which is an increase from the default. I got this value by starting with the size ofxmldoc
directory, and doing a bit of trial and error. It can probably be reduced further.
By default, Emscripten uses 64-bit doubles for all floating point values, which can cause different rounding errors in WASM code compared to native code. If this is an issue, you can pass -s PRECISE_F32=1
, which instructs Emscripten to use 32-bit floating point values wherever float
is used in C/C++ code.
The final output files will now be: main03.html
, main03.js
, main03.wasm
, and main03.data
(the preloaded files).
To run this program on a browser, execute
$ emrun main03.html
The benefit of using emrun
instead of just opening main03.html
is that emrun
will serve all the output files through a local web server, which avoids some CORS issues related to serving them from the filesystem.
The program won’t show any output until it finishes executing, which could take several seconds, depending on your browser/computer.
I’ve also hosted the example here, if you want to see a demo right away.