Skip to content

Expand Build_and_Test_CppInterOp action to deal with Emscripten case #2909

Expand Build_and_Test_CppInterOp action to deal with Emscripten case

Expand Build_and_Test_CppInterOp action to deal with Emscripten case #2909

Workflow file for this run

name: Emscripten
on:
pull_request:
branches: [main]
push:
branches: [main]
release:
types: [published]
schedule:
- cron: '30 20 * * *' # Warning: Timezone dep - 20:00 is 1:00
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}
cancel-in-progress: true
jobs:
build_cache:
name: ${{ matrix.name }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
- name: ubu24-arm-clang-repl-20-emscripten
os: ubuntu-24.04-arm
clang-runtime: '20'
cling: Off
llvm_enable_projects: "clang;lld"
llvm_targets_to_build: "WebAssembly"
emsdk_ver: "4.0.9"
- name: osx26-arm-clang-repl-20-emscripten
os: macos-26
clang-runtime: '20'
cling: Off
llvm_enable_projects: "clang;lld"
llvm_targets_to_build: "WebAssembly"
emsdk_ver: "4.0.9"
- name: ubu24-x86-clang-repl-20-emscripten
os: ubuntu-24.04
clang-runtime: '20'
cling: Off
llvm_enable_projects: "clang;lld"
llvm_targets_to_build: "WebAssembly"
emsdk_ver: "4.0.9"
- name: win2025-x86-clang-repl-20-emscripten
os: windows-2025
clang-runtime: '20'
cling: Off
llvm_enable_projects: "clang;lld"
llvm_targets_to_build: "WebAssembly"
emsdk_ver: "4.0.9"
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: '3.11'
- name: Save PR Info
uses: ./.github/actions/Miscellaneous/Save_PR_Info
- name: Restore cached LLVM-${{ matrix.clang-runtime }} and ${{ matrix.cling == 'On' && 'Cling' || 'Clang-REPL' }} build (Unix like systems emscripten)
uses: actions/cache/restore@v4
id: cache
with:
path: |
llvm-project
${{ matrix.cling=='On' && 'cling' || '' }}
key: ${{ env.CLING_HASH }}-${{ runner.os }}-${{ matrix.os }}-clang-${{ matrix.clang-runtime }}.x-emscripten
lookup-only: true
- name: Setup emsdk
if: ${{ steps.cache.outputs.cache-hit != 'true' }}
run: |
git clone --depth=1 https://github.com/emscripten-core/emsdk.git
cd emsdk
./emsdk install ${{ matrix.emsdk_ver }}
- name: Setup default Build Type
uses: ./.github/actions/Miscellaneous/Select_Default_Build_Type
- name: Install deps on Windows
if: ${{ runner.os == 'windows' && steps.cache.outputs.cache-hit != 'true' }}
run: |
choco install findutils ninja
$env:PATH="C:\Program Files (x86)\GnuWin32\bin;$env:PATH"
$env:PATH="C:\Program Files (x86)\Ninja\bin;$env:PATH"
- name: Install deps on MacOS
if: ${{ runner.os == 'macOS' && steps.cache.outputs.cache-hit != 'true' }}
run: |
brew update
export ARCHITECHURE=$(uname -m)
if [[ "$ARCHITECHURE" != "x86_64" ]]; then
brew remove unxip
fi
# workaround for https://github.com/actions/setup-python/issues/577
for pkg in $(brew list | grep '^python@'); do
brew unlink "$pkg"
brew link --overwrite "$pkg"
done
brew install ninja
- name: Install deps on Linux
if: ${{ runner.os == 'Linux' && steps.cache.outputs.cache-hit != 'true' }}
run: |
# Install deps
sudo apt-get update
sudo apt-get install ninja-build
sudo apt-get autoremove
sudo apt-get clean
- name: Build LLVM/Cling on Unix systems if the cache is invalid (emscripten)
if: ${{ runner.os != 'windows' && steps.cache.outputs.cache-hit != 'true' }}
run: |
./emsdk/emsdk activate ${{matrix.emsdk_ver}}
source ./emsdk/emsdk_env.sh
cling_on=$(echo "${{ matrix.cling }}" | tr '[:lower:]' '[:upper:]')
if [[ "${cling_on}" == "ON" ]]; then
git clone https://github.com/root-project/cling.git
cd ./cling
git checkout tags/v${{ matrix.cling-version }}
git apply -v ../patches/llvm/cling1.2-LookupHelper.patch
cd ..
git clone --depth=1 -b cling-llvm${{ matrix.clang-runtime }} https://github.com/root-project/llvm-project.git
else # repl
git clone --depth=1 -b release/${{ matrix.clang-runtime }}.x https://github.com/llvm/llvm-project.git
fi
cd llvm-project
# Build
mkdir native_build
cd native_build
cmake -DLLVM_ENABLE_PROJECTS=clang -DLLVM_TARGETS_TO_BUILD=host -DCMAKE_BUILD_TYPE=Release ../llvm/
cmake --build . --target llvm-tblgen clang-tblgen --parallel $(nproc --all)
export NATIVE_DIR=$PWD/bin/
cd ..
mkdir build
if [[ "${cling_on}" == "ON" ]]; then
cd build
emcmake cmake -DLLVM_EXTERNAL_PROJECTS=cling \
-DLLVM_EXTERNAL_CLING_SOURCE_DIR=../../cling \
-DCMAKE_BUILD_TYPE=Release \
-DLLVM_HOST_TRIPLE=wasm32-unknown-emscripten \
-DLLVM_TARGETS_TO_BUILD="${{ matrix.llvm_targets_to_build }}" \
-DLLVM_ENABLE_LIBEDIT=OFF \
-DLLVM_ENABLE_PROJECTS="${{ matrix.llvm_enable_projects }}" \
-DLLVM_ENABLE_ZSTD=OFF \
-DLLVM_ENABLE_LIBXML2=OFF \
-DCLANG_ENABLE_STATIC_ANALYZER=OFF \
-DCLANG_ENABLE_ARCMT=OFF \
-DCLANG_ENABLE_BOOTSTRAP=OFF \
-DCMAKE_CXX_FLAGS="-Dwait4=__syscall_wait4" \
-DLLVM_INCLUDE_BENCHMARKS=OFF \
-DLLVM_INCLUDE_EXAMPLES=OFF \
-DLLVM_INCLUDE_TESTS=OFF \
-DLLVM_ENABLE_THREADS=OFF \
-G Ninja \
-DLLVM_BUILD_TOOLS=OFF \
-DLLVM_ENABLE_LIBPFM=OFF \
-DCLANG_BUILD_TOOLS=OFF \
-DLLVM_NATIVE_TOOL_DIR=$NATIVE_DIR \
-DCMAKE_C_FLAGS_RELEASE="-Oz -g0 -DNDEBUG" \
-DCMAKE_CXX_FLAGS_RELEASE="-Oz -g0 -DNDEBUG" \
-DLLVM_ENABLE_LTO=Full \
../llvm
emmake ninja clang cling lld gtest_main
else
# Apply patches
llvm_vers=$(echo "${{ matrix.clang-runtime }}" | tr '[:lower:]' '[:upper:]')
if [[ "${llvm_vers}" == "19" || "${llvm_vers}" == "20" ]]; then
git apply -v ../patches/llvm/emscripten-clang${{ matrix.clang-runtime }}-*.patch
echo "Apply emscripten-clang${{ matrix.clang-runtime }}-*.patch patches:"
fi
cd build
emcmake cmake -DCMAKE_BUILD_TYPE=Release \
-DLLVM_HOST_TRIPLE=wasm32-unknown-emscripten \
-DLLVM_TARGETS_TO_BUILD="${{ matrix.llvm_targets_to_build }}" \
-DLLVM_ENABLE_LIBEDIT=OFF \
-DLLVM_ENABLE_PROJECTS="${{ matrix.llvm_enable_projects }}" \
-DLLVM_ENABLE_ZSTD=OFF \
-DLLVM_ENABLE_LIBXML2=OFF \
-DCLANG_ENABLE_STATIC_ANALYZER=OFF \
-DCLANG_ENABLE_ARCMT=OFF \
-DCLANG_ENABLE_BOOTSTRAP=OFF \
-DCMAKE_CXX_FLAGS="-Dwait4=__syscall_wait4" \
-DLLVM_INCLUDE_BENCHMARKS=OFF \
-DLLVM_INCLUDE_EXAMPLES=OFF \
-DLLVM_INCLUDE_TESTS=OFF \
-DLLVM_ENABLE_THREADS=OFF \
-DLLVM_BUILD_TOOLS=OFF \
-DLLVM_ENABLE_LIBPFM=OFF \
-DCLANG_BUILD_TOOLS=OFF \
-G Ninja \
-DLLVM_NATIVE_TOOL_DIR=$NATIVE_DIR \
-DCMAKE_C_FLAGS_RELEASE="-Oz -g0 -DNDEBUG" \
-DCMAKE_CXX_FLAGS_RELEASE="-Oz -g0 -DNDEBUG" \
-DLLVM_ENABLE_LTO=Full \
../llvm
emmake ninja libclang clangInterpreter clangStaticAnalyzerCore lldWasm
fi
cd ../
rm -rf $(find . -maxdepth 1 ! -name "build" ! -name "llvm" ! -name "clang" ! -name ".")
if [[ "${cling_on}" == "ON" ]]; then
cd ./llvm/
rm -rf $(find . -maxdepth 1 ! -name "include" ! -name "lib" ! -name "cmake" ! -name "utils" ! -name ".")
cd ../clang/
rm -rf $(find . -maxdepth 1 ! -name "include" ! -name "lib" ! -name "cmake" ! -name "utils" ! -name ".")
cd ../..
else # repl
cd ./llvm/
rm -rf $(find . -maxdepth 1 ! -name "include" ! -name "lib" ! -name "cmake" ! -name ".")
cd ../clang/
rm -rf $(find . -maxdepth 1 ! -name "include" ! -name "lib" ! -name "cmake" ! -name ".")
cd ../..
fi
- name: Build LLVM/Cling on Windows systems if the cache is invalid (emscripten)
if: ${{ runner.os == 'windows' && steps.cache.outputs.cache-hit != 'true' }}
run: |
.\emsdk\emsdk activate ${{matrix.emsdk_ver}}
.\emsdk\emsdk_env.ps1
if ( "${{ matrix.cling }}" -imatch "On" )
{
git clone https://github.com/root-project/cling.git
cd ./cling
git checkout tags/v${{ matrix.cling-version }}
git apply -v ../patches/llvm/cling1.2-LookupHelper.patch
cd ..
git clone --depth=1 -b cling-llvm${{ matrix.clang-runtime }} https://github.com/root-project/llvm-project.git
$env:PWD_DIR= $PWD.Path
$env:CLING_DIR="$env:PWD_DIR\cling"
echo "CLING_DIR=$env:CLING_DIR"
}
else
{
git clone --depth=1 -b release/${{ matrix.clang-runtime }}.x https://github.com/llvm/llvm-project.git
}
cd llvm-project
# Build
mkdir native_build
cd native_build
cmake -DLLVM_ENABLE_PROJECTS=clang -DLLVM_TARGETS_TO_BUILD=host -DCMAKE_BUILD_TYPE=Release -G Ninja ../llvm/
cmake --build . --target llvm-tblgen clang-tblgen --parallel $(nproc --all)
$env:PWD_DIR= $PWD.Path
$env:NATIVE_DIR="$env:PWD_DIR/bin/"
cd ..
mkdir build
if ( "${{ matrix.cling }}" -imatch "On" )
{
cd build
emcmake cmake -DLLVM_EXTERNAL_PROJECTS=cling `
-DLLVM_EXTERNAL_CLING_SOURCE_DIR=../../cling `
-DCMAKE_BUILD_TYPE=Release `
-DLLVM_HOST_TRIPLE=wasm32-unknown-emscripten `
-DLLVM_TARGETS_TO_BUILD="${{ matrix.llvm_targets_to_build }}" `
-DLLVM_ENABLE_LIBEDIT=OFF `
-DLLVM_ENABLE_PROJECTS="${{ matrix.llvm_enable_projects }}" `
-DLLVM_ENABLE_ZSTD=OFF `
-DLLVM_ENABLE_LIBXML2=OFF `
-DCLANG_ENABLE_STATIC_ANALYZER=OFF `
-DCLANG_ENABLE_ARCMT=OFF `
-DCLANG_ENABLE_BOOTSTRAP=OFF `
-DCMAKE_CXX_FLAGS="-Dwait4=__syscall_wait4" `
-DLLVM_INCLUDE_BENCHMARKS=OFF `
-DLLVM_INCLUDE_EXAMPLES=OFF `
-DLLVM_INCLUDE_TESTS=OFF `
-DLLVM_ENABLE_THREADS=OFF `
-G Ninja `
-DLLVM_BUILD_TOOLS=OFF `
-DLLVM_ENABLE_LIBPFM=OFF `
-DCLANG_BUILD_TOOLS=OFF `
-DCMAKE_C_FLAGS_RELEASE="-Oz -g0 -DNDEBUG" `
-DCMAKE_CXX_FLAGS_RELEASE="-Oz -g0 -DNDEBUG" `
-DLLVM_ENABLE_LTO=Full `
-DLLVM_NATIVE_TOOL_DIR="$env:NATIVE_DIR" `
..\llvm
emmake make clang cling lld gtest_main
}
else
{
cp -r ..\patches\llvm\emscripten-clang${{ matrix.clang-runtime }}*
#FIXME: Apply patches without hardcoding
if ( "${{ matrix.clang-runtime }}" -imatch "19" )
{
git apply -v emscripten-clang19-2-shift-temporary-files-to-tmp-dir.patch
git apply -v emscripten-clang19-3-remove-zdefs.patch
git apply -v emscripten-clang19-4-enable_exception_handling.patch
}
elseif ( "${{ matrix.clang-runtime }}" -imatch "20" )
{
git apply -v emscripten-clang20-2-shift-temporary-files-to-tmp-dir.patch
git apply -v emscripten-clang20-3-enable_exception_handling.patch
}
cd build
echo "Apply clang${{ matrix.clang-runtime }}-*.patch patches:"
emcmake cmake -DCMAKE_BUILD_TYPE=Release `
-DLLVM_HOST_TRIPLE=wasm32-unknown-emscripten `
-DLLVM_TARGETS_TO_BUILD="${{ matrix.llvm_targets_to_build }}" `
-DLLVM_ENABLE_LIBEDIT=OFF `
-DLLVM_ENABLE_PROJECTS="${{ matrix.llvm_enable_projects }}" `
-DLLVM_ENABLE_ZSTD=OFF `
-DLLVM_ENABLE_LIBXML2=OFF `
-DCLANG_ENABLE_STATIC_ANALYZER=OFF `
-DCLANG_ENABLE_ARCMT=OFF `
-DCLANG_ENABLE_BOOTSTRAP=OFF `
-DCMAKE_CXX_FLAGS="-Dwait4=__syscall_wait4" `
-DLLVM_INCLUDE_BENCHMARKS=OFF `
-DLLVM_INCLUDE_EXAMPLES=OFF `
-DLLVM_INCLUDE_TESTS=OFF `
-DLLVM_ENABLE_THREADS=OFF `
-DLLVM_BUILD_TOOLS=OFF `
-DLLVM_ENABLE_LIBPFM=OFF `
-DCLANG_BUILD_TOOLS=OFF `
-DCMAKE_C_FLAGS_RELEASE="-Oz -g0 -DNDEBUG" `
-DCMAKE_CXX_FLAGS_RELEASE="-Oz -g0 -DNDEBUG" `
-DLLVM_ENABLE_LTO=Full `
-G Ninja `
-DLLVM_NATIVE_TOOL_DIR="$env:NATIVE_DIR" `
..\llvm
emmake ninja libclang clangInterpreter clangStaticAnalyzerCore lldWasm
}
cd ..\
rm -r -force $(find.exe . -maxdepth 1 ! -name "build" ! -name "llvm" ! -name "clang" ! -name ".")
if ( "${{ matrix.cling }}" -imatch "On" )
{
cd .\llvm\
rm -r -force $(find.exe . -maxdepth 1 ! -name "include" ! -name "lib" ! -name "cmake" ! -name "utils" ! -name ".")
cd ..\clang\
rm -r -force $(find.exe . -maxdepth 1 ! -name "include" ! -name "lib" ! -name "cmake" ! -name "utils" ! -name ".")
cd ..\..
}
else
{
cd .\llvm\
rm -r -force $(find.exe . -maxdepth 1 ! -name "include" ! -name "lib" ! -name "cmake" ! -name ".")
cd ..\clang\
rm -r -force $(find.exe . -maxdepth 1 ! -name "include" ! -name "lib" ! -name "cmake" ! -name ".")
cd ..\..
}
- name: Cache LLVM-${{ matrix.clang-runtime }} and ${{ matrix.cling == 'On' && 'Cling' || 'Clang-REPL' }} build
uses: actions/cache/save@v4
if: ${{ steps.cache.outputs.cache-hit != 'true' }}
with:
path: |
llvm-project
${{ matrix.cling=='On' && 'cling' || '' }}
key: ${{ steps.cache.outputs.cache-primary-key }}
emscripten_wasm_CppInterOp_and_xeus_cpp:
needs: [build_cache]
name: ${{ matrix.name }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
- name: ubu24-x86-clang-repl-20-emscripten
os: ubuntu-24.04
clang-runtime: '20'
cling: Off
micromamba_shell_init: bash
emsdk_ver: "4.0.9"
build_static_library: On
- name: osx26-arm-clang-repl-20-emscripten
os: macos-26
clang-runtime: '20'
cling: Off
micromamba_shell_init: bash
emsdk_ver: "4.0.9"
build_static_library: On
- name: ubu24-arm-clang-repl-20-emscripten
os: ubuntu-24.04-arm
clang-runtime: '20'
cling: Off
micromamba_shell_init: bash
emsdk_ver: "4.0.9"
build_static_library: On
- name: win2025-x86-clang-repl-20-emscripten
os: windows-2025
clang-runtime: '20'
cling: Off
micromamba_shell_init: powershell
emsdk_ver: "4.0.9"
build_static_library: On
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Save PR Info
uses: ./.github/actions/Miscellaneous/Save_PR_Info
- name: Setup default Build Type
uses: ./.github/actions/Miscellaneous/Select_Default_Build_Type
- name: Setup default Build Type
uses: ./.github/actions/Miscellaneous/Select_Default_Build_Type
- name: install mamba
uses: mamba-org/setup-micromamba@main
with:
init-shell: >-
${{ matrix.micromamba_shell_init }}
- name: Setup emsdk
shell: bash -l {0}
run: |
git clone --depth=1 https://github.com/emscripten-core/emsdk.git
cd emsdk
./emsdk install ${{ matrix.emsdk_ver }}
- name: Restore cached LLVM-${{ matrix.clang-runtime }} and ${{ matrix.cling == 'On' && 'Cling' || 'Clang-REPL' }} build
uses: actions/cache/restore@v4
id: cache
with:
path: |
llvm-project
${{ matrix.cling=='On' && 'cling' || '' }}
key: ${{ env.CLING_HASH }}-${{ runner.os }}-${{ matrix.os }}-clang-${{ matrix.clang-runtime }}.x-emscripten
- name: micromamba shell hook
if: runner.os == 'Windows'
shell: powershell
run: |
micromamba shell hook -s cmd.exe --root-prefix C:\Users\runneradmin\micromamba-root
- name: Build and test CppInterOp
uses: ./.github/actions/Build_and_Test_CppInterOp
- name: Build xeus-cpp on Unix Systems
if: ${{ runner.os != 'windows' }}
shell: bash -l {0}
run: |
./emsdk/emsdk activate ${{matrix.emsdk_ver}}
source ./emsdk/emsdk_env.sh
micromamba activate CppInterOp-wasm
git clone --depth=1 https://github.com/compiler-research/xeus-cpp.git
cd ./xeus-cpp
mkdir build
pushd build
export CMAKE_PREFIX_PATH=${{ env.PREFIX }}
export CMAKE_SYSTEM_PREFIX_PATH=${{ env.PREFIX }}
emcmake cmake \
-DCMAKE_BUILD_TYPE=${{ env.BUILD_TYPE }} \
-DCMAKE_PREFIX_PATH=${{ env.PREFIX }} \
-DCMAKE_INSTALL_PREFIX=${{ env.PREFIX }} \
-DXEUS_CPP_EMSCRIPTEN_WASM_BUILD=ON \
-DCMAKE_FIND_ROOT_PATH_MODE_PACKAGE=ON \
-DXEUS_CPP_RESOURCE_DIR=${{ env.LLVM_BUILD_DIR }}/lib/clang/${{ matrix.clang-runtime }} \
-DSYSROOT_PATH=${{ env.SYSROOT_PATH }} \
..
emmake make -j ${{ env.ncpus }} install
- name: Build xeus-cpp on Windows systems
if: ${{ runner.os == 'windows' }}
shell: powershell
run: |
.\emsdk\emsdk activate ${{matrix.emsdk_ver}}
.\emsdk\emsdk_env.ps1
micromamba activate CppInterOp-wasm
git clone --depth=1 https://github.com/compiler-research/xeus-cpp.git
cd .\xeus-cpp
mkdir build
pushd build
$env:CMAKE_PREFIX_PATH="${{ env.PREFIX }}"
$env:CMAKE_SYSTEM_PREFIX_PATH="${{ env.PREFIX }}"
emcmake cmake `
-DCMAKE_BUILD_TYPE=${{ env.BUILD_TYPE }} `
-DCMAKE_PREFIX_PATH=${{ env.PREFIX }} `
-DCMAKE_INSTALL_PREFIX=${{ env.PREFIX }} `
-DXEUS_CPP_EMSCRIPTEN_WASM_BUILD=ON `
-DCMAKE_FIND_ROOT_PATH_MODE_PACKAGE=ON `
-DXEUS_CPP_RESOURCE_DIR=${{ env.LLVM_BUILD_DIR }}\lib\clang\${{ matrix.clang-runtime }} `
-DSYSROOT_PATH=${{ env.SYSROOT_PATH }} `
..
emmake make -j ${{ env.ncpus }} install
- name: Test xeus-cpp C++ Emscripten on Unix Systems
if: ${{ runner.os != 'windows' }}
shell: bash -l {0}
run: |
set -e
micromamba activate CppInterOp-wasm
cd ./xeus-cpp/build/test
node test_xeus_cpp.js
- name: Test xeus-cpp C++ Emscripten on Windows Systems
if: ${{ runner.os == 'windows' }}
shell: powershell
run: |
function Error-OnFailure {
param (
[Parameter(Mandatory)]
[ScriptBlock]$Command
)
& $Command
if ($LASTEXITCODE -ne 0) {
exit $LASTEXITCODE
}
}
micromamba activate CppInterOp-wasm
cd .\xeus-cpp\build\test
node test_xeus_cpp.js
echo "Running test_xeus_cpp in Firefox"
Error-OnFailure { emrun.bat --browser="firefox.exe" --kill_exit --timeout 60 --browser-args="--headless" test_xeus_cpp.html }
echo "Running test_xeus_cpp in Chromium"
Error-OnFailure { emrun.bat --browser="chrome.exe" --kill_exit --timeout 60 --browser-args="--headless --no-sandbox" test_xeus_cpp.html }
- name: Jupyter Lite integration
if: ${{ runner.os != 'windows' }}
shell: bash -l {0}
run: |
cd ./xeus-cpp/
micromamba create -n xeus-lite-host jupyterlite-core=0.6 jupyterlite-xeus jupyter_server jupyterlab notebook python-libarchive-c -c conda-forge
micromamba activate xeus-lite-host
jupyter lite build --XeusAddon.prefix=${{ env.PREFIX }} --contents notebooks/xeus-cpp-lite-demo.ipynb --contents notebooks/images/marie.png --contents notebooks/audio/audio.wav --output-dir dist
- name: Jupyter Lite integration
if: ${{ runner.os == 'windows' }}
shell: powershell
run: |
cd .\xeus-cpp\
micromamba create -n xeus-lite-host jupyterlite-core=0.6 jupyterlite-xeus jupyter_server jupyterlab notebook python-libarchive-c -c conda-forge
micromamba activate xeus-lite-host
jupyter lite build --XeusAddon.prefix=${{ env.PREFIX }} --contents notebooks/xeus-cpp-lite-demo.ipynb --contents notebooks/images/marie.png --contents notebooks/audio/audio.wav --output-dir dist