Skip to content

Add SimpleITK (and libitk dependency) for emscripten-wasm32#5448

Draft
Copilot wants to merge 8 commits intomainfrom
copilot/add-recipe-for-simpleitk
Draft

Add SimpleITK (and libitk dependency) for emscripten-wasm32#5448
Copilot wants to merge 8 commits intomainfrom
copilot/add-recipe-for-simpleitk

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 27, 2026

Adds recipes to build SimpleITK (Python image analysis toolkit) and its ITK C++ dependency for the emscripten-wasm32 platform.

Template A: Checklist for adding a package

Pre-submission Checks

  • Package requires building for emscripten-wasm32 platform (not a noarch package), in other words, the package requires compilation.

Recipe Structure

libitk (ITK 5.4.6 — C++ static library)

Added recipes/recipes_emscripten/libitk/recipe.yaml:

  • context section with version
  • package section with name and version
  • source section with verified SHA256 (cf28bc7220c57c24ebcbabbd3b2544ea7ab65f0aad430a99f8e157738ed812b7)
  • build section — uses emcmake cmake + ninja via build.sh; build number 0
  • requirements: build (gcc, gxx, cmake, ninja), host (expat, libjpeg-turbo, libpng, libtiff, eigen, zlib)
  • tests: package_contents checks for key headers/libs
  • about section with license and homepage

Key build flags: ITK_DEFAULT_THREADER=Platform (single-threaded fallback, no pthreads/OpenMP/TBB), BUILD_SHARED_LIBS=OFF, ITK_FORBID_DOWNLOADS=ON (no remote modules), entire HDF5 dependency chain disabled, system libs used for expat/jpeg/png/tiff/zlib/eigen.


simpleitk (SimpleITK 2.5.3 — Python wrapper)

Added recipes/recipes_emscripten/simpleitk/recipe.yaml:

  • context section with version
  • package section with name and version
  • source section with verified SHA256 (1ef3642b0695c8eb0a0193fefe7677c57bce94a86d6b01f48f58b2291b4ca935)
  • build section — two-stage build.sh; build number 0
  • requirements: build (gcc, gxx, cmake, ninja, swig >=4.0.0, cross-python_emscripten-wasm32, python), host (python, pip, libitk), run (python)
  • tests: test_import_simpleitk.py via pytester
  • about section with license and homepage

Build uses two stages: (1) build SimpleITK C++ static library (WRAP_DEFAULT=OFF), install to $PREFIX; (2) build SWIG Python wrapper from Wrapping/Python against the installed library, then pip install. overwriteProp.cmake enables shared lib creation for the .so Python extension module.


PR Formatting

  • PR title follows format: Add [package-name]
  • PR description includes version and build notes

Package Details

  • Package Name: libitk, simpleitk
  • Version: ITK 5.4.6, SimpleITK 2.5.3

Build Notes

  • ITK uses ITK_DEFAULT_THREADER=PlatformSequential is not a valid enum value in ITK 5.4.x's MultiThreaderBaseEnums::Threader. The Platform threader runs single-threaded on platforms without OS thread support (i.e. WASM). All threading APIs are explicitly disabled: ITK_USE_PTHREADS=OFF, ITK_USE_OPENMP=OFF, Module_ITKTBB=OFF, Module_ITKTBBImageToImageFilter=OFF.
  • HDF5 support is fully disabled to avoid build failures under the emscripten toolchain. The entire dependency chain is cut: Module_ITKHDF5=OFF (bundled third-party HDF5 library), Module_ITKIOHDF5=OFF (HDF5 image IO), Module_ITKIOTransformHDF5=OFF (HDF5 transform IO), and Module_ITKIOTransformFactory=OFF (the transform IO factory module that has ITKIOTransformHDF5 as a required dependency, which was forcing the bundled HDF5 to be compiled despite the per-module disables). hdf5 is not a host dependency.
  • Remote ITK modules (SimpleITKFilters, GenericLabelInterpolator, etc.) are disabled via ITK_FORBID_DOWNLOADS=ON to ensure reproducible offline builds.
  • -DCMAKE_FIND_ROOT_PATH=$PREFIX is passed to cmake so that find_package() calls (ZLIB, JPEG, PNG, TIFF, Expat, Eigen) correctly resolve to conda packages in $PREFIX. The emscripten toolchain restricts CMake's library/include search to CMAKE_FIND_ROOT_PATH using ONLY mode, which otherwise prevents discovery of host packages.
  • SimpleITK Python extension requires overwriteProp.cmake to set TARGET_SUPPORTS_SHARED_LIBS TRUE and WASM SIDE_MODULE flags so cmake can create the .so extension.
  • cross-python_emscripten-wasm32 activation sets CMAKE_ARGS with correct Python headers/paths and LDFLAGS with SIDE_MODULE=1 for the extension link step.
  • GDCM (DICOM support) and OpenJPEG are bundled internally by ITK — no separate system deps needed.

Copilot AI linked an issue Apr 27, 2026 that may be closed by this pull request
Copilot AI changed the title [WIP] Add recipe for SimpleITK installation Add SimpleITK (and libitk dependency) for emscripten-wasm32 Apr 27, 2026
Copilot AI requested a review from martinRenou April 27, 2026 09:27
@martinRenou
Copy link
Copy Markdown
Member

@copilot CI is failing to build libitk with

-- Performing Test ITK_PRIVATE_DYNAMIC_CAST - Failed
CMake Error at $BUILD_PREFIX/share/cmake-3.29/Modules/FindPackageHandleStandardArgs.cmake:230 (message):
  Could NOT find ZLIB (missing: ZLIB_LIBRARY ZLIB_INCLUDE_DIR)
Call Stack (most recent call first):
  $BUILD_PREFIX/share/cmake-3.29/Modules/FindPackageHandleStandardArgs.cmake:600 (_FPHSA_FAILURE_MESSAGE)
  $BUILD_PREFIX/share/cmake-3.29/Modules/FindZLIB.cmake:199 (FIND_PACKAGE_HANDLE_STANDARD_ARGS)
  Modules/ThirdParty/ZLIB/CMakeLists.txt:8 (find_package)

Copy link
Copy Markdown
Contributor Author

Copilot AI commented Apr 27, 2026

@copilot CI is failing to build libitk with

...

The issue was that the emscripten toolchain file sets CMAKE_FIND_ROOT_PATH to the emscripten sysroot and uses ONLY mode for library/include searches — so find_package(ZLIB) was looking inside the emscripten sysroot, not in $PREFIX.

Fixed in commit 190ca7b by switching from system libraries (ITK_USE_SYSTEM_*=ON) to ITK's bundled third-party copies (OFF). ITK's source tarball includes bundled versions of ZLIB, JPEG, PNG, TIFF, Expat, HDF5, and Eigen, which avoids the path lookup issue entirely. The host dependencies for those libraries were also removed from the recipe.

@martinRenou
Copy link
Copy Markdown
Member

Fixed in commit 190ca7b by switching from system libraries (ITK_USE_SYSTEM_*=ON) to ITK's bundled third-party copies (OFF). ITK's source tarball includes bundled versions of ZLIB, JPEG, PNG, TIFF, Expat, HDF5, and Eigen, which avoids the path lookup issue entirely. The host dependencies for those libraries were also removed from the recipe

@copilot Can you instead make sure it finds the libraries correctly? Compiling the bundled versions of the dependencies will most likely not work

… with emscripten toolchain

Agent-Logs-Url: https://github.com/emscripten-forge/recipes/sessions/c35ae874-8943-489b-aa3e-e49a140b28f4

Co-authored-by: martinRenou <21197331+martinRenou@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Apr 27, 2026

Fixed in commit 190ca7b by switching from system libraries (ITK_USE_SYSTEM_*=ON) to ITK's bundled third-party copies (OFF). ITK's source tarball includes bundled versions of ZLIB, JPEG, PNG, TIFF, E...

Done in commit f2a05a6. Added -DCMAKE_FIND_ROOT_PATH=$PREFIX to the cmake invocation — this is the standard pattern used throughout this repo (libheif, xeus, sparrow, etc.) to let CMake find conda packages in $PREFIX when the emscripten toolchain restricts searches to the root path. The system libraries (ITK_USE_SYSTEM_*=ON) and their host dependencies in recipe.yaml are restored.

@martinRenou
Copy link
Copy Markdown
Member

@copilot it now fails with

FAILED: [code=1] Modules/Core/Common/src/CMakeFiles/ITKCommon.dir/itkMultiThreaderBase.cxx.o 
$BUILD_PREFIX/opt/emsdk/upstream/emscripten/em++  -I$SRC_DIR/Modules/ThirdParty/DoubleConversion/src -I$SRC_DIR/build/Modules/ThirdParty/DoubleConversion/src/double-conversion -I$SRC_DIR/build/Modules/ThirdParty/Eigen3/src -I$SRC_DIR/build/Modules/ThirdParty/KWSys/src -I$SRC_DIR/Modules/ThirdParty/VNL/src/vxl/v3p/netlib -I$SRC_DIR/Modules/ThirdParty/VNL/src/vxl/vcl -I$SRC_DIR/Modules/ThirdParty/VNL/src/vxl/core -I$SRC_DIR/build/Modules/ThirdParty/VNL/src/vxl/v3p/netlib -I$SRC_DIR/build/Modules/ThirdParty/VNL/src/vxl/vcl -I$SRC_DIR/build/Modules/ThirdParty/VNL/src/vxl/core -I$SRC_DIR/build/Modules/Core/Common -I$SRC_DIR/Modules/Core/Common/include -I$SRC_DIR/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo -I$SRC_DIR/Modules/ThirdParty/VNL/src/vxl/core/vnl -I$SRC_DIR/build/Modules/ThirdParty/VNL/src/vxl/core/vnl -isystem $PREFIX/include/eigen3 -Wall -Wcast-align -Wdisabled-optimization -Wextra -Wformat=2 -Winvalid-pch -Wno-format-nonliteral -Wpointer-arith -Wshadow -Wunused -Wwrite-strings -Wno-strict-overflow -Wno-deprecated -Wno-invalid-offsetof -Wno-undefined-var-template -Woverloaded-virtual -Wctad-maybe-unsupported  -O3 -DNDEBUG -std=c++17 -fPIC -MD -MT Modules/Core/Common/src/CMakeFiles/ITKCommon.dir/itkMultiThreaderBase.cxx.o -MF Modules/Core/Common/src/CMakeFiles/ITKCommon.dir/itkMultiThreaderBase.cxx.o.d -o Modules/Core/Common/src/CMakeFiles/ITKCommon.dir/itkMultiThreaderBase.cxx.o -c $SRC_DIR/Modules/Core/Common/src/itkMultiThreaderBase.cxx
$SRC_DIR/Modules/Core/Common/src/itkMultiThreaderBase.cxx:79:93: error: no member named 'Sequential' in 'itk::MultiThreaderBaseEnums::Threader'
   79 |   MultiThreaderBase::ThreaderEnum m_GlobalDefaultThreader{ MultiThreaderBase::ThreaderEnum::ITK_DEFAULT_THREADER };
      |                                                                                             ^~~~~~~~~~~~~~~~~~~~
$SRC_DIR/build/Modules/Core/Common/itkConfigure.h:164:30: note: expanded from macro 'ITK_DEFAULT_THREADER'
  164 | #define ITK_DEFAULT_THREADER Sequential

you need to disable any threading APIs if you can

…ds/OpenMP for emscripten

Agent-Logs-Url: https://github.com/emscripten-forge/recipes/sessions/531c46f8-9c43-433a-8b2a-fe62eb57cfa1

Co-authored-by: martinRenou <21197331+martinRenou@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Apr 27, 2026

@copilot it now fails with

...

Fixed in commit 3756a82. Sequential is not a valid enum member in ITK 5.4's MultiThreaderBaseEnums::Threader — replaced it with Platform (which runs single-threaded when no OS threading is available) and added -DITK_USE_PTHREADS=OFF -DITK_USE_OPENMP=OFF -DModule_ITKTBB=OFF -DModule_ITKTBBImageToImageFilter=OFF to explicitly disable all threading APIs.

@martinRenou
Copy link
Copy Markdown
Member

@copilot It now fails with, if we really need and if possible, we could disable HDF5 features for now

$BUILD_PREFIX/opt/emsdk/upstream/emscripten/em++  -I$SRC_DIR/build/Modules/ThirdParty/ZLIB/src -I$PREFIX/include -I$SRC_DIR/build/Modules/ThirdParty/HDF5/src -I$SRC_DIR/build/Modules/ThirdParty/Eigen3/src -I$SRC_DIR/build/Modules/ThirdParty/KWSys/src -I$SRC_DIR/Modules/ThirdParty/VNL/src/vxl/v3p/netlib -I$SRC_DIR/Modules/ThirdParty/VNL/src/vxl/vcl -I$SRC_DIR/Modules/ThirdParty/VNL/src/vxl/core -I$SRC_DIR/build/Modules/ThirdParty/VNL/src/vxl/v3p/netlib -I$SRC_DIR/build/Modules/ThirdParty/VNL/src/vxl/vcl -I$SRC_DIR/build/Modules/ThirdParty/VNL/src/vxl/core -I$SRC_DIR/build/Modules/Core/Common -I$SRC_DIR/Modules/Core/Common/include -I$SRC_DIR/Modules/Core/ImageAdaptors/include -I$SRC_DIR/build/Modules/ThirdParty/Netlib -I$SRC_DIR/Modules/Numerics/Statistics/include -I$SRC_DIR/Modules/Filtering/ImageFilterBase/include -I$SRC_DIR/Modules/Core/Transform/include -I$SRC_DIR/Modules/Core/ImageFunction/include -I$SRC_DIR/Modules/Filtering/ImageGrid/include -I$SRC_DIR/Modules/Filtering/ImageCompose/include -I$SRC_DIR/build/Modules/ThirdParty/MetaIO/src/MetaIO/src -I$SRC_DIR/Modules/ThirdParty/MetaIO/src/MetaIO/src -I$SRC_DIR/Modules/Core/SpatialObjects/include -I$SRC_DIR/Modules/Filtering/ImageStatistics/include -I$SRC_DIR/Modules/Filtering/Path/include -I$SRC_DIR/Modules/Filtering/ImageIntensity/include -I$SRC_DIR/Modules/Filtering/FFT/include -I$SRC_DIR/Modules/Filtering/Thresholding/include -I$SRC_DIR/Modules/Filtering/Convolution/include -I$SRC_DIR/Modules/Filtering/ImageSources/include -I$SRC_DIR/Modules/Filtering/Smoothing/include -I$SRC_DIR/Modules/Filtering/DisplacementField/include -I$SRC_DIR/Modules/IO/TransformFactory/include -I$SRC_DIR/Modules/IO/TransformBase/include -I$SRC_DIR/Modules/IO/TransformHDF5/include -I$SRC_DIR/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo -I$SRC_DIR/Modules/ThirdParty/VNL/src/vxl/core/vnl -I$SRC_DIR/build/Modules/ThirdParty/VNL/src/vxl/core/vnl -isystem $PREFIX/include/eigen3 -Wall -Wcast-align -Wdisabled-optimization -Wextra -Wformat=2 -Winvalid-pch -Wno-format-nonliteral -Wpointer-arith -Wshadow -Wunused -Wwrite-strings -Wno-strict-overflow -Wno-deprecated -Wno-invalid-offsetof -Wno-undefined-var-template -Woverloaded-virtual -Wctad-maybe-unsupported  -O3 -DNDEBUG -std=c++17 -fPIC -MD -MT Modules/IO/TransformHDF5/src/CMakeFiles/ITKIOTransformHDF5.dir/itkHDF5TransformIO.cxx.o -MF Modules/IO/TransformHDF5/src/CMakeFiles/ITKIOTransformHDF5.dir/itkHDF5TransformIO.cxx.o.d -o Modules/IO/TransformHDF5/src/CMakeFiles/ITKIOTransformHDF5.dir/itkHDF5TransformIO.cxx.o -c $SRC_DIR/Modules/IO/TransformHDF5/src/itkHDF5TransformIO.cxx
In file included from $SRC_DIR/Modules/IO/TransformHDF5/src/itkHDF5TransformIO.cxx:21:
$SRC_DIR/build/Modules/ThirdParty/HDF5/src/itk_H5Cpp.h:25:11: fatal error: 'H5Cpp.h' file not found
   25 | # include <H5Cpp.h>

Copy link
Copy Markdown
Contributor Author

Copilot AI commented Apr 27, 2026

@copilot It now fails with, if we really need and if possible, we could disable HDF5 features for now

...

Done in commit 92f0ad5. Disabled -DModule_ITKIOHDF5=OFF -DModule_ITKIOTransformHDF5=OFF to skip the HDF5-dependent IO modules, and removed hdf5 from the host requirements in recipe.yaml.

@martinRenou
Copy link
Copy Markdown
Member

@copilot it's still trying to compile third party hdf5, make it not do that

…DF5 dependency chain

Agent-Logs-Url: https://github.com/emscripten-forge/recipes/sessions/8558dea2-8be7-4ab9-bb1c-a65720f64d23

Co-authored-by: martinRenou <21197331+martinRenou@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Apr 27, 2026

@copilot it's still trying to compile third party hdf5, make it not do that

Done in commit 39b314a. The root cause was that ITKIOTransformFactory (a default-enabled module) has ITKIOTransformHDF5 as a required dependency, which forced HDF5 to be compiled despite the earlier module-level disables. Added -DModule_ITKIOTransformFactory=OFF and -DModule_ITKHDF5=OFF to cut the entire dependency chain.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Recipe for SimpleITK

2 participants