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 (standalone from git)
    - bart source

2. Prepare:
    - use emsdk to install and activate latest emscripten.
    - create a folder for the webasm libraries: e.g. mkdir $HOME/wasm_libs

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/wasm_libs install

4. Compile libfftw3
    - again: set install prefix outside of /usr/ !
    - enable float and disable fortran
    emconfigure ./configure --prefix=$HOME/wasm_libs --disable-fortran --enable-float
    emmake make
    make install

5. Compile BlocksRuntime
    CC=emcc AR=emar RANLIB=emranlib ./buildlib
    env DESTDIR=$HOME/wasm_libs ./installlib

6. Compile bart
    - create a Makefile.local in folder Makefiles
    - content should be this:
"""
FFTW_BASE=$(HOME)/wasm_libs
BLAS_BASE=$(HOME)/wasm_libs
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/wasm_libs/lib/libfftw3f.a \
       $HOME/wasm_libs/lib/libopenblas.a $HOME/wasm_libs/usr/local/lib/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

======

Embedding in JupyterLite:

- Install JupyterLite CLI: python -m pip install jupyterlite-core
- Install Pyodide kernel: jupyterlite-pyodide-kernel
- Create folder, e.g.: mkdir lite
- jupyter lite init --output-dir demo --port 8000

- Add a folder for python packages: mkdir lite/pypi
- Build BART python package: from bart/pkg/python,  python3 -m build --wheel
- Copy wheel: e.g. cp bart/pkg/python/dist/bart-0.0.1-py3-none-any.whl lite/pypi

- Build bart wasm: bart/build_webasm_main.sh
- Copy files to web: cp bart/web/wwwroot/bart_main.{js,wasm} /bart/web/wwwroot/bart_{base,worker}.js lite/demo/extensions/@jupyterlite/pyodide-kernel-extension/static/

- jupyter lite build

Plain pyodide repl works similar

======

Further Notes:

- Several BART features are controlled via environment variables. However, webasm code running under node.js can not read the 'normal' environment
  of the node process. To work around: echo "Module.preRun = () => {ENV.LANG = undefined};" > src/pre.js, and add "--pre-js src/pre.js" to LDFLAGS.
