Skip to content

Commit

Permalink
Add automated tests for Emscripten builds
Browse files Browse the repository at this point in the history
  • Loading branch information
mcbarton committed Feb 13, 2025
1 parent b797dbb commit 9f02e74
Show file tree
Hide file tree
Showing 20 changed files with 300 additions and 72 deletions.
13 changes: 8 additions & 5 deletions .github/workflows/deploy-pages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -93,10 +93,11 @@ jobs:
if: ${{ runner.os != 'windows' }}
shell: bash -l {0}
run: |
set -e
./emsdk/emsdk activate ${{matrix.emsdk_ver}}
source ./emsdk/emsdk_env.sh
micromamba create -f environment-wasm.yml --platform=emscripten-wasm32
export SYSROOT_PATH=$PWD/emsdk/upstream/emscripten/cache/sysroot
export PREFIX=$MAMBA_ROOT_PREFIX/envs/CppInterOp-wasm
export CMAKE_PREFIX_PATH=$PREFIX
export CMAKE_SYSTEM_PREFIX_PATH=$PREFIX
Expand Down Expand Up @@ -130,6 +131,7 @@ jobs:
-DCODE_COVERAGE=${{ env.CODE_COVERAGE }} \
-DCMAKE_INSTALL_PREFIX=$PREFIX \
-DCMAKE_FIND_ROOT_PATH_MODE_PACKAGE=ON \
-DSYSROOT_PATH=$SYSROOT_PATH \
../
else
emcmake cmake -DCMAKE_BUILD_TYPE=${{ env.BUILD_TYPE }} \
Expand All @@ -141,13 +143,15 @@ jobs:
-DCODE_COVERAGE=${{ env.CODE_COVERAGE }} \
-DCMAKE_INSTALL_PREFIX=$PREFIX \
-DCMAKE_FIND_ROOT_PATH_MODE_PACKAGE=ON \
-DSYSROOT_PATH=$SYSROOT_PATH \
../
fi
emmake make -j ${{ env.ncpus }} check-cppinterop
emmake make -j ${{ env.ncpus }} install
cd ..
echo "SYSROOT_PATH=$SYSROOT_PATH" >> $GITHUB_ENV
echo "CB_PYTHON_DIR=$CB_PYTHON_DIR" >> $GITHUB_ENV
echo "CPPINTEROP_BUILD_DIR=$CPPINTEROP_BUILD_DIR" >> $GITHUB_ENV
echo "CPPINTEROP_DIR=$CPPINTEROP_DIR" >> $GITHUB_ENV
Expand All @@ -160,7 +164,6 @@ jobs:
run: |
./emsdk/emsdk activate ${{matrix.emsdk_ver}}
source ./emsdk/emsdk_env.sh
export SYSROOT_PATH=$PWD/emsdk/upstream/emscripten/cache/sysroot
micromamba activate CppInterOp-wasm
git clone --depth=1 https://github.com/compiler-research/xeus-cpp.git
cd ./xeus-cpp
Expand All @@ -175,7 +178,7 @@ jobs:
-DXEUS_CPP_EMSCRIPTEN_WASM_BUILD=ON \
-DCMAKE_FIND_ROOT_PATH_MODE_PACKAGE=ON \
-DCppInterOp_DIR="${{ env.CPPINTEROP_BUILD_DIR }}/lib/cmake/CppInterOp" \
-DSYSROOT_PATH=$SYSROOT_PATH \
-DSYSROOT_PATH=${{ env.SYSROOT_PATH }} \
..
emmake make -j ${{ env.ncpus }} install
Expand Down
15 changes: 9 additions & 6 deletions .github/workflows/emscripten.yml
Original file line number Diff line number Diff line change
Expand Up @@ -550,10 +550,11 @@ jobs:
if: ${{ runner.os != 'windows' }}
shell: bash -l {0}
run: |
set -e
./emsdk/emsdk activate ${{matrix.emsdk_ver}}
source ./emsdk/emsdk_env.sh
micromamba create -f environment-wasm.yml --platform=emscripten-wasm32
export SYSROOT_PATH=$PWD/emsdk/upstream/emscripten/cache/sysroot
export PREFIX=$MAMBA_ROOT_PREFIX/envs/CppInterOp-wasm
export CMAKE_PREFIX_PATH=$PREFIX
export CMAKE_SYSTEM_PREFIX_PATH=$PREFIX
Expand Down Expand Up @@ -587,6 +588,7 @@ jobs:
-DCMAKE_INSTALL_PREFIX=$PREFIX \
-DCMAKE_FIND_ROOT_PATH_MODE_PACKAGE=ON \
-DLLVM_ENABLE_WERROR=On \
-DSYSROOT_PATH=$SYSROOT_PATH \
../
else
emcmake cmake -DCMAKE_BUILD_TYPE=${{ env.BUILD_TYPE }} \
Expand All @@ -599,13 +601,15 @@ jobs:
-DCMAKE_INSTALL_PREFIX=$PREFIX \
-DCMAKE_FIND_ROOT_PATH_MODE_PACKAGE=ON \
-DLLVM_ENABLE_WERROR=On \
-DSYSROOT_PATH=$SYSROOT_PATH \
../
fi
emmake make -j ${{ env.ncpus }} install
emmake make -j ${{ env.ncpus }} check-cppinterop
emmake make -j ${{ env.ncpus }} install
cd ..
echo "SYSROOT_PATH=$SYSROOT_PATH" >> $GITHUB_ENV
echo "CB_PYTHON_DIR=$CB_PYTHON_DIR" >> $GITHUB_ENV
echo "CPPINTEROP_BUILD_DIR=$CPPINTEROP_BUILD_DIR" >> $GITHUB_ENV
echo "CPPINTEROP_DIR=$CPPINTEROP_DIR" >> $GITHUB_ENV
Expand All @@ -618,7 +622,6 @@ jobs:
run: |
./emsdk/emsdk activate ${{matrix.emsdk_ver}}
source ./emsdk/emsdk_env.sh
export SYSROOT_PATH=$PWD/emsdk/upstream/emscripten/cache/sysroot
micromamba activate CppInterOp-wasm
git clone --depth=1 https://github.com/compiler-research/xeus-cpp.git
cd ./xeus-cpp
Expand All @@ -633,6 +636,6 @@ jobs:
-DXEUS_CPP_EMSCRIPTEN_WASM_BUILD=ON \
-DCMAKE_FIND_ROOT_PATH_MODE_PACKAGE=ON \
-DCppInterOp_DIR="${{ env.CPPINTEROP_BUILD_DIR }}/lib/cmake/CppInterOp" \
-DSYSROOT_PATH=$SYSROOT_PATH \
-DSYSROOT_PATH=${{ env.SYSROOT_PATH }} \
..
emmake make -j ${{ env.ncpus }} install
14 changes: 6 additions & 8 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -361,11 +361,15 @@ endif()

# Add appropriate flags for GCC
if (LLVM_COMPILER_IS_GCC_COMPATIBLE)
if (APPLE)
if (APPLE OR EMSCRIPTEN)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-common -Woverloaded-virtual -Wcast-qual -fno-strict-aliasing -Wno-long-long -Wall -W -Wno-unused-parameter -Wwrite-strings")
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-common -Woverloaded-virtual -Wcast-qual -fno-strict-aliasing -pedantic -Wno-long-long -Wall -W -Wno-unused-parameter -Wwrite-strings")
endif ()
# Needed due to an error which occurs when you compile gtest on emscripten
if (EMSCRIPTEN)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-sign-compare")
endif()
endif ()

# Fixes "C++ exception handler used, but unwind semantics are not enabled" warning Windows
Expand Down Expand Up @@ -451,13 +455,7 @@ option(CPPINTEROP_ENABLE_DOXYGEN "Use doxygen to generate CppInterOp interal API
option(CPPINTEROP_ENABLE_SPHINX "Use sphinx to generage CppInterOp user documentation")


if(EMSCRIPTEN)
message("Build with emscripten")
option(CPPINTEROP_ENABLE_TESTING "Enables the testing infrastructure." OFF)
else()
message("Build with cmake")
option(CPPINTEROP_ENABLE_TESTING "Enables the testing infrastructure." ON)
endif()
option(CPPINTEROP_ENABLE_TESTING "Enables the testing infrastructure." ON)

if(MSVC)

Expand Down
13 changes: 10 additions & 3 deletions Emscripten-build-instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,12 @@ git clone https://github.com/emscripten-core/emsdk.git
./emsdk/emsdk install 3.1.73
```

and activate the emsdk environment
and activate the emsdk environment (we are defining SYSROOT_PATH for use later)

```bash
./emsdk/emsdk activate 3.1.73
source ./emsdk/emsdk_env.sh
export SYSROOT_PATH=$PWD/emsdk/upstream/emscripten/cache/sysroot
```

Now clone the 19.x release of the LLVM project repository and CppInterOp (the building of the emscripten version of llvm can be
Expand Down Expand Up @@ -97,7 +98,7 @@ export CMAKE_PREFIX_PATH=$PREFIX
export CMAKE_SYSTEM_PREFIX_PATH=$PREFIX
```

Now to build CppInterOp execute the following
Now to build and test your Emscripten build of CppInterOp by executing the following

```bash
mkdir build
Expand All @@ -109,7 +110,14 @@ emcmake cmake -DCMAKE_BUILD_TYPE=Release \
-DBUILD_SHARED_LIBS=ON \
-DCMAKE_FIND_ROOT_PATH_MODE_PACKAGE=ON \
-DCMAKE_INSTALL_PREFIX=$PREFIX \
-DSYSROOT_PATH=$SYSROOT_PATH \
../
emmake make -j $(nproc --all) check-cppinterop
```

Assuming it passes all test you can install by executing the following

```bash
emmake make -j $(nproc --all) install
```

Expand All @@ -126,7 +134,6 @@ the CppInterOp build folder, you can build the wasm version of xeus-cpp by execu

```bash
cd ../..
export SYSROOT_PATH=$PWD/emsdk/upstream/emscripten/cache/sysroot
git clone --depth=1 https://github.com/compiler-research/xeus-cpp.git
cd ./xeus-cpp
mkdir build
Expand Down
6 changes: 5 additions & 1 deletion cmake/CppInterOp/CppInterOpConfig.cmake.in
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,11 @@ endif()

### build/install workaround
if (@BUILD_SHARED_LIBS@)
set(_lib_suffix ${CMAKE_SHARED_LIBRARY_SUFFIX})
if(EMSCRIPTEN)
set(_lib_suffix ".wasm")
else()
set(_lib_suffix ${CMAKE_SHARED_LIBRARY_SUFFIX})
endif()
set(_lib_prefix ${CMAKE_SHARED_LIBRARY_PREFIX})
else()
set(_lib_suffix ${CMAKE_STATIC_LIBRARY_SUFFIX})
Expand Down
16 changes: 13 additions & 3 deletions cmake/modules/GoogleTest.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,20 @@ if(WIN32)
-DCMAKE_ARCHIVE_OUTPUT_DIRECTORY_MINSIZEREL:PATH=${_gtest_byproduct_binary_dir}/lib/
-DCMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELEASE:PATH=${_gtest_byproduct_binary_dir}/lib/
-DCMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELWITHDEBINFO:PATH=${_gtest_byproduct_binary_dir}/lib/
-Dgtest_force_shared_crt=ON
BUILD_COMMAND ${CMAKE_COMMAND} --build <BINARY_DIR> --config $<CONFIG>)
-Dgtest_force_shared_crt=ON)
elseif(APPLE)
set(EXTRA_GTEST_OPTS -DCMAKE_OSX_SYSROOT=${CMAKE_OSX_SYSROOT})
endif()

include(ExternalProject)
if (EMSCRIPTEN)
set(config_cmd emcmake cmake)
set(build_cmd emmake make)
else()
set(config_cmd ${CMAKE_COMMAND})
set(build_cmd ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR}/unittests/googletest-prefix/src/googletest-build/ --config $<CONFIG>)
endif()

ExternalProject_Add(
googletest
GIT_REPOSITORY https://github.com/google/googletest.git
Expand All @@ -31,7 +38,9 @@ ExternalProject_Add(
# CMAKE_ARGS -DCMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG:PATH=DebugLibs
# -DCMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELEASE:PATH=ReleaseLibs
# -Dgtest_force_shared_crt=ON
CMAKE_ARGS -G ${CMAKE_GENERATOR}
CONFIGURE_COMMAND ${config_cmd} -G ${CMAKE_GENERATOR}
-S ${CMAKE_BINARY_DIR}/unittests/googletest-prefix/src/googletest/
-B ${CMAKE_BINARY_DIR}/unittests/googletest-prefix/src/googletest-build/
-DCMAKE_BUILD_TYPE=$<CONFIG>
-DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}
-DCMAKE_C_FLAGS=${CMAKE_C_FLAGS}
Expand All @@ -40,6 +49,7 @@ ExternalProject_Add(
-DCMAKE_AR=${CMAKE_AR}
-DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX}
${EXTRA_GTEST_OPTS}
BUILD_COMMAND ${build_cmd}
# Disable install step
INSTALL_COMMAND ""
BUILD_BYPRODUCTS ${_gtest_byproducts}
Expand Down
13 changes: 10 additions & 3 deletions docs/Emscripten-build-instructions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,13 @@ This can be installed by executing (we only currently support version
git clone https://github.com/emscripten-core/emsdk.git
./emsdk/emsdk install 3.1.73
and activate the emsdk environment
and activate the emsdk environment (we are defining SYSROOT_PATH for use later)

.. code:: bash
./emsdk/emsdk activate 3.1.73
source ./emsdk/emsdk_env.sh
export SYSROOT_PATH=$PWD/emsdk/upstream/emscripten/cache/sysroot
Now clone the 19.x release of the LLVM project repository and CppInterOp
(the building of the emscripten version of llvm can be avoided by
Expand Down Expand Up @@ -115,7 +116,7 @@ You will also want to set a few environment variables
export CMAKE_PREFIX_PATH=$PREFIX
export CMAKE_SYSTEM_PREFIX_PATH=$PREFIX
Now to build CppInterOp execute the following
Now to build and test your Emscripten build of CppInterOp by executing the following

.. code:: bash
Expand All @@ -128,7 +129,14 @@ Now to build CppInterOp execute the following
-DBUILD_SHARED_LIBS=ON \
-DCMAKE_FIND_ROOT_PATH_MODE_PACKAGE=ON \
-DCMAKE_INSTALL_PREFIX=$PREFIX \
-DSYSROOT_PATH=$SYSROOT_PATH \
../
emmake make -j $(nproc --all) check-cppinterop
Assuming it passes all test you can install by executing the following.

.. code:: bash
emmake make -j $(nproc --all) install
Once this finishes building we need to take note of where we built
Expand All @@ -147,7 +155,6 @@ build folder, you can build the wasm version of xeus-cpp by executing
.. code:: bash
cd ../..
export SYSROOT_PATH=$PWD/emsdk/upstream/emscripten/cache/sysroot
git clone --depth=1 https://github.com/compiler-research/xeus-cpp.git
cd ./xeus-cpp
mkdir build
Expand Down
62 changes: 34 additions & 28 deletions lib/Interpreter/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,33 +1,7 @@
if(EMSCRIPTEN)
set_property(GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS TRUE)
set(CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS "-s SIDE_MODULE=1")
set(CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS "-s SIDE_MODULE=1")
set(CMAKE_STRIP FALSE)

add_llvm_library(clangCppInterOp
SHARED

CppInterOp.cpp
CXCppInterOp.cpp
DynamicLibraryManager.cpp
DynamicLibraryManagerSymbol.cpp
Paths.cpp

# Additional libraries from Clang and LLD
LINK_LIBS
clangInterpreter
)
#FIXME: Setting no_soname=1 is needed until https://github.com/emscripten-core/emscripten/blob/ac676d5e437525d15df5fd46bc2c208ec6d376a3/cmake/Modules/Platform/Emscripten.cmake#L36
# is patched out of emsdk, as --soname is not recognised by emscripten. A PR to do this has been done here https://github.com/emscripten-core/emscripten/pull/23453
#FIXME: A patch is needed to llvm to remove -Wl,-z,defs since it is now recognised on emscripten. What needs to be removed is here
# https://github.com/llvm/llvm-project/blob/128e2e446e90c3b1827cfc7d4d19e3c0976beff3/llvm/cmake/modules/HandleLLVMOptions.cmake#L318 . The PR to do try to do this is here
# https://github.com/llvm/llvm-project/pull/123396
set_target_properties(clangCppInterOp
PROPERTIES NO_SONAME 1
)
target_link_options(clangCppInterOp PRIVATE
PUBLIC "SHELL: -s WASM_BIGINT"
)
set(LLVM_LINK_COMPONENTS "")
else()
set(LLVM_LINK_COMPONENTS
${LLVM_TARGETS_TO_BUILD}
Expand All @@ -41,6 +15,7 @@ else()
if ("LLVMFrontendDriver" IN_LIST LLVM_AVAILABLE_LIBS)
list(APPEND LLVM_LINK_COMPONENTS FrontendDriver)
endif()
endif()
if ("LLVMOrcDebugging" IN_LIST LLVM_AVAILABLE_LIBS)
list(APPEND LLVM_LINK_COMPONENTS OrcDebugging)
endif()
Expand All @@ -65,6 +40,11 @@ else()
set(cling_clang_interp clangInterpreter)
endif()

if(EMSCRIPTEN)
set(link_libs
${cling_clang_interp}
)
else()
set(link_libs
${cling_clang_interp}
clangAST
Expand All @@ -73,6 +53,7 @@ else()
clangLex
clangSema
)
endif()

if(NOT WIN32)
list(APPEND link_libs dl)
Expand Down Expand Up @@ -124,7 +105,6 @@ else()
clangStaticAnalyzerCore
)
endif(LLVM_LINK_LLVM_DYLIB)

add_llvm_library(clangCppInterOp
DISABLE_LLVM_LINK_LLVM_DYLIB
CppInterOp.cpp
Expand All @@ -133,6 +113,32 @@ else()
LINK_LIBS
${link_libs}
)

if(EMSCRIPTEN)
# FIXME: When dynamically linking the Emscripten shared library to the
# unit tests main_module you get errors due to undefined symbols. The reading of the file
# below into a SYMBOLS_LIST variable is a temporary workaround that exports the undefined
# symbols from the shared library, until it can be determined why they are not being exported already.
file(READ "${CMAKE_SOURCE_DIR}/lib/Interpreter/exports.ld" SYMBOLS_LIST)

# Replace newlines with spaces
string(REPLACE "\n" " " SYMBOLS_LIST "${SYMBOLS_LIST}")

#FIXME: Setting no_soname=1 is needed until https://github.com/emscripten-core/emscripten/blob/ac676d5e437525d15df5fd46bc2c208ec6d376a3/cmake/Modules/Platform/Emscripten.cmake#L36
# is patched out of emsdk, as --soname is not recognised by emscripten. A PR to do this has been done here https://github.com/emscripten-core/emscripten/pull/23453
#FIXME: A patch is needed to llvm to remove -Wl,-z,defs since it is now recognised on emscripten. What needs to be removed is here
# https://github.com/llvm/llvm-project/blob/128e2e446e90c3b1827cfc7d4d19e3c0976beff3/llvm/cmake/modules/HandleLLVMOptions.cmake#L318 . The PR to do try to do this is here
# https://github.com/llvm/llvm-project/pull/123396
set_target_properties(clangCppInterOp PROPERTIES
NO_SONAME 1
COMPILE_FLAGS "-s SIDE_MODULE=1"
LINK_FLAGS "-s WASM_BIGINT -s SIDE_MODULE=1 ${SYMBOLS_LIST}"
SUFFIX ".wasm"
)
# When compiling Emscripten tests the shared library it links to is expected to be in the same folder as the compiled Javascript
add_custom_command(TARGET clangCppInterOp POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:clangCppInterOp> ${CMAKE_BINARY_DIR}/unittests/CppInterOp/
)
endif()

string(REPLACE ";" "\;" _VER CPPINTEROP_VERSION)
Expand Down
Loading

0 comments on commit 9f02e74

Please sign in to comment.