Compile C/C++ into JavaScript with Emscripten and Docker
JavaScript continues its march towards its destiny as the universal programming language, largely due to its cross-platform portability. In previous blog posts, we demonstrated how to cross compile a large, scientific C++ library, ITK, by using cross-compilation capabilities of CMake for a number platforms,
In this post, we will go through the steps to cross-compile ITK to JavaScript and run its test suite. Over a decade of development by hundreds of top-notch research programmers is then immediately accessible to anyone with a web browser.
Edit 2016-10-10: The instructions below now use dockcross. Cross compile for other platforms by replacing dockcross/browser-asmjs with dockcross/linux-armv7, etc.
Edit 2021-07-22: For the browser cross-complilation case to WebAssembly / JavaScript, we now have a dedicated dockcross extension project: itk.js.
1) Get the cross-compiling toolchain
As with previous posts, we will use Docker to grab the toolchain:
docker pull dockcross/browser-asmjs docker run --rm dockcross/browser-asmjs > ./dockcross-browser-asmjs chmod +x ./dockcross-browser-asmjs
This Docker image contains of a recent version of CMake and Emscripten, along with Emscripten’s dependencies.
2) Obtain the source and create a build tree
If there is a source tree and build tree, e.g.
git clone https://itk.org/ITK.git cd ITK git checkout e19ddf0c830d cd .. mkdir -p ITK-build
3) Build and test
For the purposes of running the test suite, we will add flags for Emscripten that sacrifice run-time performance at the cost of functionality:
flags='-Wno-warn-absolute-paths --memory-init-file 0 -s DISABLE_EXCEPTION_CATCHING=0 -s ALLOW_MEMORY_GROWTH=1'
Inside the container, the environmental variable CMAKE_TOOLCHAIN_FILE has been configured to point to the toolchain file CMake uses to inform itself about the build environment. Pass this file to CMake during configuration.
./dockcross-browser-asmjs cmake -HITK -BITK-build \ -G Ninja \ "-DCMAKE_CXX_FLAGS=$flags" "-DCMAKE_C_FLAGS=$flags" ./dockcross-browser-asmjs ninja -CITK-build
The -G Ninja flag tells CMake to use our favorite generator, the Ninja generator.
Emscripten uses NodeJS as the CMAKE_CROSSCOMPILING_EMULATOR; with CMake 3.3 and later, this means NodeJS is used to also run the test suite. For NodeJS to access the file paths passed as command line arguments, the paths must be mounted to the NODEFS file system. ITK’s test driver is instrumented to mount the source tree and build tree when executed.
Start the Experimental dashboard build!
./dockcross-browser-asmjs bash -c 'cd ITK-build && ctest -D Experimental -j$(nproc)'
Enjoy ITK!
Hi,
Thank you for this very interesting series of posts using Docker. While I understand the interest of cross-compiling for several architectures and OSes to distribute my applications, I don’t really see a use case for the use on the browser. Could you (or someone else) give some examples of those?
Thank you.
J.
Hi Jordi,
Yes, please stay tuned for a following post that demonstrates the value of this functionality.
Thanks,
Matt
Hi Jordi,
An example using the technology to create interactive figures is presented here:
http://kitware.com/blog/home/post/942
Cheers,
Matt
Hello Matt,
I have set up emscripten in my system and I was able to compile ITK4.8 using ’emmake make’.
I am trying to build an external project that uses ITK. I’m having trouble in the linking stage. I have messages such as:
WARNING root: emcc: cannot find library “ITKCommon”
…
warning: unresolved symbol: _ZN3itk10DataObject13ResetPipelineEv
It seems that the liking rules are not passed to emmake.
Does any one know how to set up the compilation properly?
Any comments or suggestion will be greatly appreciated.
Cheers,
Juan
Hello Juan,
For both, just using emmake is likely insufficient. Try using the CMAKE_TOOLCHAIN_FILE as described above for both builds.
HTH,
Matt
I am using CMAKE_TOOLCHAIN_FILE but I still have those linking warnings.
The execution does not work because of it.
Juan
Hi Juan,
Please post your CMakeLists.txt for your project and the cmake command used to configure your project on the ITK mailing list, and we can follow-up there.
Thanks,
Matt
Hi! I’m new to docker and cross compiling as well. I was able to pull the cross compiler image from docker. However, I get stuck at step 2. It says something about a dockcross script and that I can’t run it manually. I pulled the linux-arm-v7 cross compiler,too. The problem, however, still persists. Could you suggest a solution? Thanks in advance for your time.
Hi Kevin! I’ve updated the post to use dockcross (it is much cleaner). Please give it a try.
Hi Matt,
I am new to dockcross and ITK, and I am running win10 and have installed WSL2 with Ubuntu 20.94, I run docker in that termial window. Now I meet a problem like below :
CMake Warning at CMake/itkExternal_Eigen3.cmake:59 (find_package):
By not providing “FindITKInternalEigen3.cmake” in CMAKE_MODULE_PATH this
project has asked CMake to find a package configuration file provided by
“ITKInternalEigen3”, but CMake did not find one.
Could not find a package configuration file provided by “ITKInternalEigen3”
with any of the following names:
Add the installation prefix of “ITKInternalEigen3” to CMAKE_PREFIX_PATH or
set “ITKInternalEigen3_DIR” to a directory containing one of the above
files. If “ITKInternalEigen3” provides a separate development package or
SDK, be sure it has been installed.
Call Stack (most recent call first):
CMakeLists.txt:534 (include)
CMake Error at CMake/itkExternal_Eigen3.cmake:61 (message):
ITKInternalEigen3 configuration faileed
REPORT:
— The C compiler identification is unknown
— The CXX compiler identification is unknown
— Check for working C compiler: /emsdk_portable/sdk/emcc
— Check for working C compiler: /emsdk_portable/sdk/emcc — broken
— Configuring incomplete, errors occurred!
See also
“/work/ITK-build/ITKInternalEigen3-build/CMakeFiles/CMakeOutput.log”.
See also
“/work/ITK-build/ITKInternalEigen3-build/CMakeFiles/CMakeError.log”.
CMake Error at /usr/share/cmake-3.13/Modules/CMakeTestCCompiler.cmake:52
(message):
I download the source code from itk website , it is InsightToolkit-5.2.0.zip
docker is running on systray but not container runs. The dockcross-browser-asmjs script said it is no intend to be run mannually.
So, what should I do , please ?
thanks in advance !
William
Hi William!
We now have an updated dockcross extension project that includes an image with recent ITK Git master and tooling to improve building and execution of numerically intensive WebAssembly, itk.js:
https://insightsoftwareconsortium.github.io/itk-js/