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 otherwise em++ 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 entire xmldoc 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 of xmldoc 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.