1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
|
A short guide on how I compiled BART to WebAssembler:
1. Download (tested versions.):
- emscripten (3.1.41)
- OpenBLAS source (0.3.23)
- libfftw3 source (3.3.10)
- BlocksRuntime source (from git)
- bart source
2. Prepare:
- use emsdk to install and activate latest emscripten.
3. Compile OpenBLAS:
- compiling this is a bit troublesome, for me it only works on a linux system and not on windows with wsl.
- a few month ago OpenBLAS got support for emscripten so just use this make command to compile:
make CC=emcc HOSTCC=gcc TARGET=RISCV64_GENERIC NOFORTRAN=1 USE_THREAD=0
- install the results outside of the standard places in /usr/ ! e.g. somewhere in your home directory
make CC=emcc HOSTCC=gcc TARGET=RISCV64_GENERIC NOFORTRAN=1 USE_THREAD=0 PREFIX=$HOME/openblas install
4. Compile libfftw3
- again: set install prefix outside of /usr/ !
- enable float and disable fortran
emconfigure ./configure --prefix=$HOME/fftw/ --disable-fortran --enable-float
emmake make
make install
5. Compile BlocksRuntime
CC=emcc AR=emar RANLIB=emranlib ./buildlib
- run the install script with sudo or:
- open ./installlib in a texteditor and delete the lines 85 to 89. then run it without sudo
sudo prefix=$HOME/blocksruntime ./installlib
6. Compile bart
- create a Makefile.local in folder Makefiles
- content should be this:
"""
FFTW_BASE=$HOME/fftw
BLAS_BASE=$HOME/openblas
CC=emcc
CFLAGS+=-fblocks
OPENBLAS=1
FORTRAN=0
FFTWTHREADS=0
USE_THREAD=1
SHARED=1
PNG=0
OMP=0
TENSORFLOW=0
DEBUG=0
MKL=0
ACML=0
CUDA=0
CUDNN=0
ISMRMRD=0
"""
- don't add libBlocksRuntime.a to LDFLAGS! clang will crash.
- then compile, no need for emmake just make:
make
- Troubleshoot: the compilation will fail if /usr/include is included (-I/usr//include).
- Check if you have set all base directories outside of /usr or disabled them (e.g. ACML)
6. Include into your WebAssembler project
- copy the bart.o file to where you want it
- add it to the emcc call as an input file e.g.:
emcc -O3 -Wall bart.o -s EXPORTED_FUNCTIONS="['__Block_object_dispose','_malloc','_free', \
'_calc_phantom', '_calc_bart', '_calc_circ', '_fftc','_ifftc', '_num_init', '_pha_opts_defaults', \
'_memcfl_create', '_load_cfl', '_main_ecalib', '_main_pics', '_main_phantom', '_main_fft']" \
-s ALLOW_MEMORY_GROWTH=1 -s MAXIMUM_MEMORY=4GB -o ./web/wwwroot/bart.js /home/ich/fftw/lib/libfftw3f.a \
/home/ich/openblas/lib/libopenblas.a /home/ich/blocksruntime/libBlocksRuntime.a
- the script build_webasm.sh builds the files needed for the included web examples
- important to include all libfftw3.a, libopenblas.a and also libBlocksRuntime.a (here clang doesn't crash)
- all functions, variables you want to access in the js files have to be exported.
- you definitely have to include '__Block_Object_dispose' even if you don't call this function in your js code!
- to allocate and free memory include '_malloc', '_free'
- In the example, given above, all functions needed for the small web example are exported,
the second line contains names to call the bart functions directly, the third line uses the command line functions.
- The "_" in front of the name is mandatory. The c function calc_phantom is called "_calc_phantom" in JS
- MAXIMUM_MEMORY=4GB raises the amount of ram the browser is allowed to use, ALLOW_MEMORY_GROWTH=1 allows dynamic allocation.
- if you want to call a js Function from c use -s EXPORTED_RUNTIME_METHODS="['addFunction', 'removeFunction']" -s RESERVED_FUNCTION_POINTERS=2
- Module.addFunction adds a callback and returns the c pointer.
- set the reserved function pointers to the number of functions u need at the same time.
- Results in two files: a.out.js and a.out.wasm (can be changed to anything with -o filename.js but the .js at the end is important)
- Both have to be in the same directory on the web server
|