diff --git a/.github/workflows/emscripten.yml b/.github/workflows/emscripten.yml index 5522b91a3..1e6e354f7 100644 --- a/.github/workflows/emscripten.yml +++ b/.github/workflows/emscripten.yml @@ -460,7 +460,7 @@ jobs: ${{ matrix.cling=='On' && 'cling' || '' }} key: ${{ env.CLING_HASH }}-${{ runner.os }}-${{ matrix.os }}-clang-${{ matrix.clang-runtime }}.x-emscripten - - name: Emscripten build of CppInterOp on Unix systems + - name: Emscripten build of CppInterOp on Unix systems (shared library) if: ${{ runner.os != 'windows' }} shell: bash -l {0} run: | @@ -609,6 +609,118 @@ jobs: emmake make -j ${{ env.ncpus }} install cd .. + echo "PATH=$PATH" >> $GITHUB_ENV + echo "SYSROOT_PATH=$SYSROOT_PATH" >> $GITHUB_ENV + echo "CB_PYTHON_DIR=$CB_PYTHON_DIR" >> $GITHUB_ENV + echo "CPPINTEROP_DIR=$CPPINTEROP_DIR" >> $GITHUB_ENV + echo "LLVM_BUILD_DIR=$LLVM_BUILD_DIR" >> $GITHUB_ENV + echo "CPLUS_INCLUDE_PATH=$CPLUS_INCLUDE_PATH" >> $GITHUB_ENV + echo "PREFIX=$PREFIX" >> $GITHUB_ENV + + - name: Emscripten build of CppInterOp on Unix systems (static library) + if: runner.os != 'Windows' && !(startsWith(matrix.os, 'ubuntu') && matrix.clang-runtime == '19' && endsWith(matrix.os, 'arm') ) + shell: bash -l {0} + run: | + # FIXME: Static library builds, but tests fail to build on Github runner for Ubuntu arm llvm 19 case + # Disabled build for now + set -e + ./emsdk/emsdk activate ${{matrix.emsdk_ver}} + source ./emsdk/emsdk_env.sh + 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 + + LLVM_DIR="$(pwd)/llvm-project" + LLVM_BUILD_DIR="$(pwd)/llvm-project/build" + cling_on=$(echo "${{ matrix.cling }}" | tr '[:lower:]' '[:upper:]') + if [[ "${cling_on}" == "ON" ]]; then + CLING_DIR="$(pwd)/cling" + CLING_BUILD_DIR="$(pwd)/cling/build" + CPLUS_INCLUDE_PATH="${CLING_DIR}/tools/cling/include:${CLING_BUILD_DIR}/include:${LLVM_DIR}/llvm/include:${LLVM_DIR}/clang/include:${LLVM_BUILD_DIR}/include:${LLVM_BUILD_DIR}/tools/clang/include:$PWD/include" + else + CPLUS_INCLUDE_PATH="${LLVM_DIR}/llvm/include:${LLVM_DIR}/clang/include:${LLVM_BUILD_DIR}/include:${LLVM_BUILD_DIR}/tools/clang/include:$PWD/include" + fi + + # Build CppInterOp next to cling and llvm-project. + mkdir build_static + cd build_static + if [[ "${cling_on}" == "ON" ]]; then + emcmake cmake -DCMAKE_BUILD_TYPE=${{ env.BUILD_TYPE }} \ + -DCPPINTEROP_USE_CLING=ON \ + -DCPPINTEROP_USE_REPL=OFF \ + -DCMAKE_PREFIX_PATH=$PREFIX \ + -DCling_DIR=$LLVM_BUILD_DIR/tools/cling \ + -DLLVM_DIR=$LLVM_BUILD_DIR/lib/cmake/llvm \ + -DLLD_DIR=$LLVM_BUILD_DIR/lib/cmake/lld \ + -DClang_DIR=$LLVM_BUILD_DIR/lib/cmake/clang \ + -DCODE_COVERAGE=${{ env.CODE_COVERAGE }} \ + -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 }} \ + -DCMAKE_PREFIX_PATH=$PREFIX \ + -DLLVM_DIR=$LLVM_BUILD_DIR/lib/cmake/llvm \ + -DLLD_DIR=$LLVM_BUILD_DIR/lib/cmake/lld \ + -DClang_DIR=$LLVM_BUILD_DIR/lib/cmake/clang \ + -DCODE_COVERAGE=${{ env.CODE_COVERAGE }} \ + -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 }} check-cppinterop + cd ./unittests/CppInterOp/ + # Explaination of options for emrun + # --browser (name of browser on path) + # --kill_exit makes it so that when emrun finishes, + # that the headless browser we create is killed along with it + # --timeout 60 is such that emrun is killed after 60 seconds if + # still running. emrun should have finished long before then, + # so if it is still running, something went wrong (such as a test + # which crashed the html file). This will cause the ci to fail, + # as a non 0 value of will be returned. + # In the case of Chrome we have the extra --no-sandbox flag, as on + # Ubuntu Chrome will refuse to run otherwise, as it expects to have + # been installed with admin privileges. This flag allows it to run + # in userspace. + os="${{ matrix.os }}" + if [[ "${os}" == "macos"* ]]; then + # Run tests in browsers + echo "Running CppInterOpTests in Firefox" + emrun --browser="firefox" --kill_exit --timeout 60 --browser-args="--headless" CppInterOpTests.html + echo "Running DynamicLibraryManagerTests in Firefox" + emrun --browser="firefox" --kill_exit --timeout 60 --browser-args="--headless" DynamicLibraryManagerTests.html + echo "Running CppInterOpTests in Google Chrome" + emrun --browser="Google Chrome" --kill_exit --timeout 60 --browser-args="--headless --no-sandbox" CppInterOpTests.html + echo "Running DynamicLibraryManagerTests in Google Chrome" + emrun --browser="Google Chrome" --kill_exit --timeout 60 --browser-args="--headless --no-sandbox" DynamicLibraryManagerTests.html + else + export ARCHITECHURE=$(uname -m) + if [[ "$ARCHITECHURE" != "aarch64" ]]; then + # Run tests in browsers + echo "Running CppInterOpTests in Firefox" + emrun --browser="firefox" --kill_exit --timeout 60 --browser-args="--headless" CppInterOpTests.html + echo "Running DynamicLibraryManagerTests in Firefox" + emrun --browser="firefox" --kill_exit --timeout 60 --browser-args="--headless" DynamicLibraryManagerTests.html + echo "Running CppInterOpTests in Google Chrome" + emrun --browser="google-chrome" --kill_exit --timeout 60 --browser-args="--headless --no-sandbox" CppInterOpTests.html + echo "Running DynamicLibraryManagerTests in Google Chrome" + emrun --browser="google-chrome" --kill_exit --timeout 60 --browser-args="--headless --no-sandbox" DynamicLibraryManagerTests.html + else + # Run tests in browsers + echo "Running CppInterOpTests in Firefox" + emrun --browser="firefox" --kill_exit --timeout 60 --browser-args="--headless" CppInterOpTests.html + echo "Running DynamicLibraryManagerTests in Firefox" + emrun --browser="firefox" --kill_exit --timeout 60 --browser-args="--headless" DynamicLibraryManagerTests.html + fi + fi + cd ../../.. + echo "SYSROOT_PATH=$SYSROOT_PATH" >> $GITHUB_ENV echo "CB_PYTHON_DIR=$CB_PYTHON_DIR" >> $GITHUB_ENV echo "CPPINTEROP_DIR=$CPPINTEROP_DIR" >> $GITHUB_ENV @@ -622,7 +734,7 @@ jobs: run: | micromamba shell hook -s cmd.exe --root-prefix C:\Users\runneradmin\micromamba-root - - name: Build and Test/Install CppInterOp on Windows systems + - name: Build and Test/Install CppInterOp on Windows systems (shared library) continue-on-error: true if: ${{ runner.os == 'windows' }} shell: powershell @@ -707,7 +819,88 @@ jobs: } emmake make -j ${{ env.ncpus }} check-cppinterop emmake make -j ${{ env.ncpus }} install + + - name: Build and Test/Install CppInterOp on Windows systems (static library) + continue-on-error: true + if: ${{ runner.os == 'windows' }} + shell: powershell + run: | + $ErrorActionPreference = "Stop" + .\emsdk\emsdk activate ${{matrix.emsdk_ver}} + .\emsdk\emsdk_env.ps1 + $env:PWD_DIR= $PWD.Path + $env:SYSROOT_PATH="$env:EMSDK/upstream/emscripten/cache/sysroot" + $env:PREFIX="%CONDA_PREFIX%/envs/CppInterOp-wasm" + $env:CMAKE_PREFIX_PATH=$env:PREFIX + $env:CMAKE_SYSTEM_PREFIX_PATH=$env:PREFIX + $env:LLVM_DIR="$env:PWD_DIR\llvm-project" + echo "LLVM_DIR=$env:LLVM_DIR" + echo "LLVM_DIR=$env:LLVM_DIR" >> $env:GITHUB_ENV + + $env:LLVM_BUILD_DIR="$env:PWD_DIR\llvm-project\build" + echo "LLVM_BUILD_DIR=$env:LLVM_BUILD_DIR" + echo "LLVM_BUILD_DIR=$env:LLVM_BUILD_DIR" >> $env:GITHUB_ENV + + if ( "${{ matrix.cling }}" -imatch "On" ) + { + $env:CLING_DIR="$env:PWD_DIR\cling" + echo "CLING_DIR=$env:CLING_DIR" + echo "CLING_DIR=$env:CLING_DIR" >> $env:GITHUB_ENV + + $env:CLING_BUILD_DIR="$env:PWD_DIR\cling\build" + echo "CLING_BUILD_DIR=$env:CLING_BUILD_DIR" + echo "CLING_BUILD_DIR=$env:CLING_BUILD_DIR" >> $env:GITHUB_ENV + + $env:CPLUS_INCLUDE_PATH="$env:CLING_DIR\tools\cling\include;$env:CLING_BUILD_DIR\include;$env:LLVM_DIR\llvm\include;$env:LLVM_DIR\clang\include;$env:LLVM_BUILD_DIR\include;$env:LLVM_BUILD_DIR\tools\clang\include;$env:PWD_DIR\include;" + echo "CPLUS_INCLUDE_PATH=$env:CPLUS_INCLUDE_PATH" + echo "CPLUS_INCLUDE_PATH=$env:CPLUS_INCLUDE_PATH" >> $env:GITHUB_ENV + } + else + { + $env:CPLUS_INCLUDE_PATH="$env:LLVM_DIR\llvm\include;$env:LLVM_DIR\clang\include;$env:LLVM_BUILD_DIR\include;$env:LLVM_BUILD_DIR\tools\clang\include;$env:PWD_DIR\include;" + echo "CPLUS_INCLUDE_PATH=$env:CPLUS_INCLUDE_PATH" + echo "CPLUS_INCLUDE_PATH=$env:CPLUS_INCLUDE_PATH" >> $env:GITHUB_ENV + } + + # Build CppInterOp next to cling and llvm-project. + mkdir build_static + cd build_static + $env:CPPINTEROP_BUILD_DIR="$env:PWD_DIR" + echo "CPPINTEROP_BUILD_DIR=$env:CPPINTEROP_BUILD_DIR" + echo "CPPINTEROP_BUILD_DIR=$env:CPPINTEROP_BUILD_DIR" >> $env:GITHUB_ENV + if ( "${{ matrix.cling }}" -imatch "On" ) + { + emcmake cmake -DCMAKE_BUILD_TYPE=${{ env.BUILD_TYPE }} ` + -DCPPINTEROP_USE_CLING=ON ` + -DCPPINTEROP_USE_REPL=OFF ` + -DCMAKE_PREFIX_PATH="$env:PREFIX" ` + -DCling_DIR="$env:LLVM_BUILD_DIR\tools\cling" ` + -DLLVM_DIR="$env:LLVM_BUILD_DIR\lib\cmake\llvm" ` + -DLLD_DIR="$env:LLVM_BUILD_DIR\lib\cmake\lld" ` + -DClang_DIR="$env:LLVM_BUILD_DIR\lib\cmake\clang" ` + -DCODE_COVERAGE=${{ env.CODE_COVERAGE }} ` + -DCMAKE_INSTALL_PREFIX="$env:PREFIX" ` + -DCMAKE_FIND_ROOT_PATH_MODE_PACKAGE=ON ` + -DLLVM_ENABLE_WERROR=On ` + -DSYSROOT_PATH="$env:SYSROOT_PATH" ` + ..\ + } + else + { + emcmake cmake -DCMAKE_BUILD_TYPE=${{ env.BUILD_TYPE }} ` + -DCMAKE_PREFIX_PATH="$env:PREFIX" ` + -DLLVM_DIR="$env:LLVM_BUILD_DIR\lib\cmake\llvm" ` + -DLLD_DIR="$env:LLVM_BUILD_DIR\lib\cmake\lld" ` + -DClang_DIR="$env:LLVM_BUILD_DIR\lib\cmake\clang" ` + -DCODE_COVERAGE=${{ env.CODE_COVERAGE }} ` + -DCMAKE_INSTALL_PREFIX="$env:PREFIX" ` + -DCMAKE_FIND_ROOT_PATH_MODE_PACKAGE=ON ` + -DLLVM_ENABLE_WERROR=On ` + -DSYSROOT_PATH="$env:SYSROOT_PATH" ` + ..\ + } + emmake make -j ${{ env.ncpus }} check-cppinterop - name: Build xeus-cpp if: ${{ runner.os != 'windows' }} diff --git a/Emscripten-build-instructions.md b/Emscripten-build-instructions.md index 3bc3b444d..e41912bcc 100644 --- a/Emscripten-build-instructions.md +++ b/Emscripten-build-instructions.md @@ -173,6 +173,7 @@ $env:CMAKE_SYSTEM_PREFIX_PATH=$env:PREFIX ``` on Windows. Now to build and test your Emscripten build of CppInterOp using node on Linux and osx execute the following +(BUILD_SHARED_LIBS=ON is only needed if building xeus-cpp, as CppInterOp can be built as an Emscripten static library) ```bash mkdir build @@ -190,6 +191,7 @@ emmake make -j $(nproc --all) check-cppinterop ``` To build and test your Emscripten build of CppInterOp on using node Windows execute the following +(BUILD_SHARED_LIBS=ON is only needed if building xeus-cpp, as CppInterOp can be built as an Emscripten static library) ```powershell emcmake cmake -DCMAKE_BUILD_TYPE=Release ` diff --git a/docs/Emscripten-build-instructions.rst b/docs/Emscripten-build-instructions.rst index 94403e836..573627382 100644 --- a/docs/Emscripten-build-instructions.rst +++ b/docs/Emscripten-build-instructions.rst @@ -197,6 +197,7 @@ and $env:CMAKE_SYSTEM_PREFIX_PATH=$env:PREFIX on Windows. Now to build and test your Emscripten build of CppInterOp on Linux and osx execute the following +(BUILD_SHARED_LIBS=ON is only needed if building xeus-cpp, as CppInterOp can be built as an Emscripten static library) .. code:: bash @@ -214,6 +215,7 @@ on Windows. Now to build and test your Emscripten build of CppInterOp on Linux a emmake make -j $(nproc --all) check-cppinterop To build and test your Emscripten build of CppInterOp on Windows execute the following +(BUILD_SHARED_LIBS=ON is only needed if building xeus-cpp, as CppInterOp can be built as an Emscripten static library) .. code:: powershell diff --git a/lib/CppInterOp/CMakeLists.txt b/lib/CppInterOp/CMakeLists.txt index 8835511b4..142d4d5d9 100644 --- a/lib/CppInterOp/CMakeLists.txt +++ b/lib/CppInterOp/CMakeLists.txt @@ -114,6 +114,7 @@ endif() if(EMSCRIPTEN) + if(BUILD_SHARED_LIBS) # 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 @@ -131,8 +132,13 @@ if(EMSCRIPTEN) PRIVATE "SHELL: -s SIDE_MODULE=1" PRIVATE "SHELL: ${SYMBOLS_LIST}" ) +else() + target_link_options(clangCppInterOp + PRIVATE "SHELL: -s WASM_BIGINT" + ) +endif() if (CPPINTEROP_ENABLE_TESTING) - # When compiling Emscripten tests the shared library it links to is expected to be in the same folder as the compiled Javascript + # When compiling Emscripten tests the CppInterOp 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 $ ${CMAKE_BINARY_DIR}/unittests/CppInterOp/ ) diff --git a/unittests/CppInterOp/CMakeLists.txt b/unittests/CppInterOp/CMakeLists.txt index 3372dd147..8cc63038a 100644 --- a/unittests/CppInterOp/CMakeLists.txt +++ b/unittests/CppInterOp/CMakeLists.txt @@ -112,6 +112,16 @@ if(EMSCRIPTEN) ) endif() +if (EMSCRIPTEN) + if (BUILD_SHARED_LIBS) + target_compile_definitions(CppInterOpTests PRIVATE "EMSCRIPTEN_SHARED_LIBRARY") + target_compile_definitions(DynamicLibraryManagerTests PRIVATE "EMSCRIPTEN_SHARED_LIBRARY") + else() + target_compile_definitions(CppInterOpTests PRIVATE "EMSCRIPTEN_STATIC_LIBRARY") + target_compile_definitions(DynamicLibraryManagerTests PRIVATE "EMSCRIPTEN_STATIC_LIBRARY") + endif() +endif() + set_output_directory(DynamicLibraryManagerTests BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/${EXTRA_PATH_TEST_BINARIES} LIBRARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/${EXTRA_PATH_TEST_BINARIES} diff --git a/unittests/CppInterOp/FunctionReflectionTest.cpp b/unittests/CppInterOp/FunctionReflectionTest.cpp index 4252c86b0..28a64252f 100644 --- a/unittests/CppInterOp/FunctionReflectionTest.cpp +++ b/unittests/CppInterOp/FunctionReflectionTest.cpp @@ -2485,8 +2485,8 @@ TEST(FunctionReflectionTest, FailingTest1) { #ifdef _WIN32 GTEST_SKIP() << "Disabled on Windows. Needs fixing."; #endif -#ifdef EMSCRIPTEN - GTEST_SKIP() << "Test fails for Emscipten builds"; +#ifdef EMSCRIPTEN_SHARED_LIBRARY + GTEST_SKIP() << "Test fails for Emscipten shared library builds"; #endif Cpp::CreateInterpreter(); EXPECT_FALSE(Cpp::Declare(R"( diff --git a/unittests/CppInterOp/InterpreterTest.cpp b/unittests/CppInterOp/InterpreterTest.cpp index 841913c54..4ef046f92 100644 --- a/unittests/CppInterOp/InterpreterTest.cpp +++ b/unittests/CppInterOp/InterpreterTest.cpp @@ -99,6 +99,9 @@ TEST(InterpreterTest, DeleteInterpreter) { } TEST(InterpreterTest, ActivateInterpreter) { +#ifdef EMSCRIPTEN_STATIC_LIBRARY + GTEST_SKIP() << "Test fails for Emscipten static library build"; +#endif EXPECT_FALSE(Cpp::ActivateInterpreter(nullptr)); auto* Cpp14 = Cpp::CreateInterpreter({"-std=c++14"}); auto* Cpp17 = Cpp::CreateInterpreter({"-std=c++17"}); @@ -122,6 +125,9 @@ TEST(InterpreterTest, ActivateInterpreter) { } TEST(InterpreterTest, Process) { +#ifdef EMSCRIPTEN_STATIC_LIBRARY + GTEST_SKIP() << "Test fails for Emscipten static library build"; +#endif #ifdef _WIN32 GTEST_SKIP() << "Disabled on Windows. Needs fixing."; #endif