Skip to content

Commit a4090f5

Browse files
committed
Add Emscripten static library build CppInterOp
1 parent bc728d3 commit a4090f5

File tree

5 files changed

+255
-5
lines changed

5 files changed

+255
-5
lines changed

.github/workflows/emscripten.yml

Lines changed: 235 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -460,7 +460,7 @@ jobs:
460460
${{ matrix.cling=='On' && 'cling' || '' }}
461461
key: ${{ env.CLING_HASH }}-${{ runner.os }}-${{ matrix.os }}-clang-${{ matrix.clang-runtime }}.x-emscripten
462462

463-
- name: Emscripten build of CppInterOp on Unix systems
463+
- name: Emscripten build of CppInterOp on Unix systems (shared library)
464464
if: ${{ runner.os != 'windows' }}
465465
shell: bash -l {0}
466466
run: |
@@ -615,14 +615,166 @@ jobs:
615615
echo "LLVM_BUILD_DIR=$LLVM_BUILD_DIR" >> $GITHUB_ENV
616616
echo "CPLUS_INCLUDE_PATH=$CPLUS_INCLUDE_PATH" >> $GITHUB_ENV
617617
echo "PREFIX=$PREFIX" >> $GITHUB_ENV
618+
619+
- name: Emscripten build of CppInterOp on Unix systems (static library)
620+
if: runner.os != 'Windows' && !(matrix.os == 'ubuntu'* && matrix.clang-runtime == '19')
621+
shell: bash -l {0}
622+
run: |
623+
# FIXME: Static library builds, but tests fail to build on Github runner for Ubuntu llvm 19 case
624+
# Disabled build for now
625+
set -e
626+
./emsdk/emsdk activate ${{matrix.emsdk_ver}}
627+
source ./emsdk/emsdk_env.sh
628+
export SYSROOT_PATH=$PWD/emsdk/upstream/emscripten/cache/sysroot
629+
export PREFIX=$MAMBA_ROOT_PREFIX/envs/CppInterOp-wasm
630+
export CMAKE_PREFIX_PATH=$PREFIX
631+
export CMAKE_SYSTEM_PREFIX_PATH=$PREFIX
632+
633+
LLVM_DIR="$(pwd)/llvm-project"
634+
LLVM_BUILD_DIR="$(pwd)/llvm-project/build"
635+
cling_on=$(echo "${{ matrix.cling }}" | tr '[:lower:]' '[:upper:]')
636+
if [[ "${cling_on}" == "ON" ]]; then
637+
CLING_DIR="$(pwd)/cling"
638+
CLING_BUILD_DIR="$(pwd)/cling/build"
639+
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"
640+
else
641+
CPLUS_INCLUDE_PATH="${LLVM_DIR}/llvm/include:${LLVM_DIR}/clang/include:${LLVM_BUILD_DIR}/include:${LLVM_BUILD_DIR}/tools/clang/include:$PWD/include"
642+
fi
643+
644+
# Build CppInterOp next to cling and llvm-project.
645+
mkdir build_static
646+
cd build_static
647+
if [[ "${cling_on}" == "ON" ]]; then
648+
emcmake cmake -DCMAKE_BUILD_TYPE=${{ env.BUILD_TYPE }} \
649+
-DCPPINTEROP_USE_CLING=ON \
650+
-DCPPINTEROP_USE_REPL=OFF \
651+
-DCMAKE_PREFIX_PATH=$PREFIX \
652+
-DCling_DIR=$LLVM_BUILD_DIR/tools/cling \
653+
-DLLVM_DIR=$LLVM_BUILD_DIR/lib/cmake/llvm \
654+
-DLLD_DIR=$LLVM_BUILD_DIR/lib/cmake/lld \
655+
-DClang_DIR=$LLVM_BUILD_DIR/lib/cmake/clang \
656+
-DCODE_COVERAGE=${{ env.CODE_COVERAGE }} \
657+
-DCMAKE_INSTALL_PREFIX=$PREFIX \
658+
-DCMAKE_FIND_ROOT_PATH_MODE_PACKAGE=ON \
659+
-DLLVM_ENABLE_WERROR=On \
660+
-DSYSROOT_PATH=$SYSROOT_PATH \
661+
../
662+
else
663+
emcmake cmake -DCMAKE_BUILD_TYPE=${{ env.BUILD_TYPE }} \
664+
-DCMAKE_PREFIX_PATH=$PREFIX \
665+
-DLLVM_DIR=$LLVM_BUILD_DIR/lib/cmake/llvm \
666+
-DLLD_DIR=$LLVM_BUILD_DIR/lib/cmake/lld \
667+
-DClang_DIR=$LLVM_BUILD_DIR/lib/cmake/clang \
668+
-DCODE_COVERAGE=${{ env.CODE_COVERAGE }} \
669+
-DCMAKE_INSTALL_PREFIX=$PREFIX \
670+
-DCMAKE_FIND_ROOT_PATH_MODE_PACKAGE=ON \
671+
-DLLVM_ENABLE_WERROR=On \
672+
-DSYSROOT_PATH=$SYSROOT_PATH \
673+
../
674+
fi
675+
emmake make -j ${{ env.ncpus }} check-cppinterop
676+
cd ./unittests/CppInterOp/
677+
# Fresh install browsers, and run Emscripten tests in them
678+
# This is to match the Emscripten build instructions, where
679+
# we run in a fresh browser, to stop any extra installed
680+
# stuff interferring with the running of the tests
681+
# Explaination of options for emrun
682+
# --browser (name of browser on path)
683+
# --kill_exit makes it so that when emrun finishes,
684+
# that the headless browser we create is killed along with it
685+
# --timeout 60 is such that emrun is killed after 60 seconds if
686+
# still running. emrun should have finished long before then,
687+
# so if it is still running, something went wrong (such as a test
688+
# which crashed the html file). This will cause the ci to fail,
689+
# as a non 0 value of will be returned.
690+
# In the case of Chrome we have the extra --no-sandbox flag, as on
691+
# Ubuntu Chrome will refuse to run otherwise, as it expects to have
692+
# been installed with admin privileges. This flag allows it to run
693+
# in userspace.
694+
os="${{ matrix.os }}"
695+
if [[ "${os}" == "macos"* ]]; then
696+
# Install Firefox
697+
wget "https://download.mozilla.org/?product=firefox-latest&os=osx&lang=en-US" -O Firefox-latest.dmg
698+
hdiutil attach Firefox-latest.dmg
699+
cp -r /Volumes/Firefox/Firefox.app $PWD
700+
hdiutil detach /Volumes/Firefox
701+
cd ./Firefox.app/Contents/MacOS/
702+
export PATH="$PWD:$PATH"
703+
cd -
704+
705+
# Install Google Chrome
706+
wget https://dl.google.com/chrome/mac/stable/accept_tos%3Dhttps%253A%252F%252Fwww.google.com%252Fintl%252Fen_ph%252Fchrome%252Fterms%252F%26_and_accept_tos%3Dhttps%253A%252F%252Fpolicies.google.com%252Fterms/googlechrome.pkg
707+
pkgutil --expand-full googlechrome.pkg google-chrome
708+
cd ./google-chrome/GoogleChrome.pkg/Payload/Google\ Chrome.app/Contents/MacOS/
709+
export PATH="$PWD:$PATH"
710+
cd -
711+
712+
# Run tests in browsers
713+
echo "Running CppInterOpTests in Firefox"
714+
emrun --browser="firefox" --kill_exit --timeout 60 --browser-args="--headless" CppInterOpTests.html
715+
echo "Running DynamicLibraryManagerTests in Firefox"
716+
emrun --browser="firefox" --kill_exit --timeout 60 --browser-args="--headless" DynamicLibraryManagerTests.html
717+
echo "Running CppInterOpTests in Google Chrome"
718+
emrun --browser="Google Chrome" --kill_exit --timeout 60 --browser-args="--headless --no-sandbox" CppInterOpTests.html
719+
echo "Running DynamicLibraryManagerTests in Google Chrome"
720+
emrun --browser="Google Chrome" --kill_exit --timeout 60 --browser-args="--headless --no-sandbox" DynamicLibraryManagerTests.html
721+
else
722+
export ARCHITECHURE=$(uname -m)
723+
if [[ "$ARCHITECHURE" != "aarch64" ]]; then
724+
# Install Google Chrome
725+
wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
726+
dpkg-deb -x google-chrome-stable_current_amd64.deb $PWD/chrome
727+
cd ./chrome/opt/google/chrome/
728+
export PATH="$PWD:$PATH"
729+
cd -
730+
731+
# Install Firefox
732+
wget https://ftp.mozilla.org/pub/firefox/releases/138.0.1/linux-x86_64/en-GB/firefox-138.0.1.tar.xz
733+
tar -xJf firefox-138.0.1.tar.xz
734+
cd ./firefox
735+
export PATH="$PWD:$PATH"
736+
cd -
737+
738+
# Run tests in browsers
739+
echo "Running CppInterOpTests in Firefox"
740+
emrun --browser="firefox" --kill_exit --timeout 60 --browser-args="--headless" CppInterOpTests.html
741+
echo "Running DynamicLibraryManagerTests in Firefox"
742+
emrun --browser="firefox" --kill_exit --timeout 60 --browser-args="--headless" DynamicLibraryManagerTests.html
743+
echo "Running CppInterOpTests in Google Chrome"
744+
emrun --browser="google-chrome" --kill_exit --timeout 60 --browser-args="--headless --no-sandbox" CppInterOpTests.html
745+
echo "Running DynamicLibraryManagerTests in Google Chrome"
746+
emrun --browser="google-chrome" --kill_exit --timeout 60 --browser-args="--headless --no-sandbox" DynamicLibraryManagerTests.html
747+
else
748+
# Install Firefox
749+
wget https://ftp.mozilla.org/pub/firefox/releases/138.0.1/linux-aarch64/en-GB/firefox-138.0.1.tar.xz
750+
tar -xJf firefox-138.0.1.tar.xz
751+
cd ./firefox
752+
export PATH="$PWD:$PATH"
753+
cd -
754+
755+
# Run tests in browsers
756+
echo "Running CppInterOpTests in Firefox"
757+
emrun --browser="firefox" --kill_exit --timeout 60 --browser-args="--headless" CppInterOpTests.html
758+
echo "Running DynamicLibraryManagerTests in Firefox"
759+
emrun --browser="firefox" --kill_exit --timeout 60 --browser-args="--headless" DynamicLibraryManagerTests.html
760+
fi
761+
fi
762+
cd ../../..
763+
764+
echo "SYSROOT_PATH=$SYSROOT_PATH" >> $GITHUB_ENV
765+
echo "CB_PYTHON_DIR=$CB_PYTHON_DIR" >> $GITHUB_ENV
766+
echo "CPPINTEROP_DIR=$CPPINTEROP_DIR" >> $GITHUB_ENV
767+
echo "LLVM_BUILD_DIR=$LLVM_BUILD_DIR" >> $GITHUB_ENV
768+
echo "CPLUS_INCLUDE_PATH=$CPLUS_INCLUDE_PATH" >> $GITHUB_ENV
769+
echo "PREFIX=$PREFIX" >> $GITHUB_ENV
618770
619771
- name: micromamba shell hook
620772
if: ${{ runner.os == 'windows' }}
621773
shell: powershell
622774
run: |
623775
micromamba shell hook -s cmd.exe --root-prefix C:\Users\runneradmin\micromamba-root
624776
625-
- name: Build and Test/Install CppInterOp on Windows systems
777+
- name: Build and Test/Install CppInterOp on Windows systems (shared library)
626778
continue-on-error: true
627779
if: ${{ runner.os == 'windows' }}
628780
shell: powershell
@@ -707,7 +859,88 @@ jobs:
707859
}
708860
emmake make -j ${{ env.ncpus }} check-cppinterop
709861
emmake make -j ${{ env.ncpus }} install
862+
863+
- name: Build and Test/Install CppInterOp on Windows systems (static library)
864+
continue-on-error: true
865+
if: ${{ runner.os == 'windows' }}
866+
shell: powershell
867+
run: |
868+
$ErrorActionPreference = "Stop"
869+
.\emsdk\emsdk activate ${{matrix.emsdk_ver}}
870+
.\emsdk\emsdk_env.ps1
871+
$env:PWD_DIR= $PWD.Path
872+
$env:SYSROOT_PATH="$env:EMSDK/upstream/emscripten/cache/sysroot"
873+
$env:PREFIX="%CONDA_PREFIX%/envs/CppInterOp-wasm"
874+
$env:CMAKE_PREFIX_PATH=$env:PREFIX
875+
$env:CMAKE_SYSTEM_PREFIX_PATH=$env:PREFIX
710876
877+
$env:LLVM_DIR="$env:PWD_DIR\llvm-project"
878+
echo "LLVM_DIR=$env:LLVM_DIR"
879+
echo "LLVM_DIR=$env:LLVM_DIR" >> $env:GITHUB_ENV
880+
881+
$env:LLVM_BUILD_DIR="$env:PWD_DIR\llvm-project\build"
882+
echo "LLVM_BUILD_DIR=$env:LLVM_BUILD_DIR"
883+
echo "LLVM_BUILD_DIR=$env:LLVM_BUILD_DIR" >> $env:GITHUB_ENV
884+
885+
if ( "${{ matrix.cling }}" -imatch "On" )
886+
{
887+
$env:CLING_DIR="$env:PWD_DIR\cling"
888+
echo "CLING_DIR=$env:CLING_DIR"
889+
echo "CLING_DIR=$env:CLING_DIR" >> $env:GITHUB_ENV
890+
891+
$env:CLING_BUILD_DIR="$env:PWD_DIR\cling\build"
892+
echo "CLING_BUILD_DIR=$env:CLING_BUILD_DIR"
893+
echo "CLING_BUILD_DIR=$env:CLING_BUILD_DIR" >> $env:GITHUB_ENV
894+
895+
$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;"
896+
echo "CPLUS_INCLUDE_PATH=$env:CPLUS_INCLUDE_PATH"
897+
echo "CPLUS_INCLUDE_PATH=$env:CPLUS_INCLUDE_PATH" >> $env:GITHUB_ENV
898+
}
899+
else
900+
{
901+
$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;"
902+
echo "CPLUS_INCLUDE_PATH=$env:CPLUS_INCLUDE_PATH"
903+
echo "CPLUS_INCLUDE_PATH=$env:CPLUS_INCLUDE_PATH" >> $env:GITHUB_ENV
904+
}
905+
906+
# Build CppInterOp next to cling and llvm-project.
907+
mkdir build_static
908+
cd build_static
909+
$env:CPPINTEROP_BUILD_DIR="$env:PWD_DIR"
910+
echo "CPPINTEROP_BUILD_DIR=$env:CPPINTEROP_BUILD_DIR"
911+
echo "CPPINTEROP_BUILD_DIR=$env:CPPINTEROP_BUILD_DIR" >> $env:GITHUB_ENV
912+
if ( "${{ matrix.cling }}" -imatch "On" )
913+
{
914+
emcmake cmake -DCMAKE_BUILD_TYPE=${{ env.BUILD_TYPE }} `
915+
-DCPPINTEROP_USE_CLING=ON `
916+
-DCPPINTEROP_USE_REPL=OFF `
917+
-DCMAKE_PREFIX_PATH="$env:PREFIX" `
918+
-DCling_DIR="$env:LLVM_BUILD_DIR\tools\cling" `
919+
-DLLVM_DIR="$env:LLVM_BUILD_DIR\lib\cmake\llvm" `
920+
-DLLD_DIR="$env:LLVM_BUILD_DIR\lib\cmake\lld" `
921+
-DClang_DIR="$env:LLVM_BUILD_DIR\lib\cmake\clang" `
922+
-DCODE_COVERAGE=${{ env.CODE_COVERAGE }} `
923+
-DCMAKE_INSTALL_PREFIX="$env:PREFIX" `
924+
-DCMAKE_FIND_ROOT_PATH_MODE_PACKAGE=ON `
925+
-DLLVM_ENABLE_WERROR=On `
926+
-DSYSROOT_PATH="$env:SYSROOT_PATH" `
927+
..\
928+
}
929+
else
930+
{
931+
emcmake cmake -DCMAKE_BUILD_TYPE=${{ env.BUILD_TYPE }} `
932+
-DCMAKE_PREFIX_PATH="$env:PREFIX" `
933+
-DLLVM_DIR="$env:LLVM_BUILD_DIR\lib\cmake\llvm" `
934+
-DLLD_DIR="$env:LLVM_BUILD_DIR\lib\cmake\lld" `
935+
-DClang_DIR="$env:LLVM_BUILD_DIR\lib\cmake\clang" `
936+
-DCODE_COVERAGE=${{ env.CODE_COVERAGE }} `
937+
-DCMAKE_INSTALL_PREFIX="$env:PREFIX" `
938+
-DCMAKE_FIND_ROOT_PATH_MODE_PACKAGE=ON `
939+
-DLLVM_ENABLE_WERROR=On `
940+
-DSYSROOT_PATH="$env:SYSROOT_PATH" `
941+
..\
942+
}
943+
emmake make -j ${{ env.ncpus }} check-cppinterop
711944
712945
- name: Build xeus-cpp
713946
if: ${{ runner.os != 'windows' }}

CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,10 @@ else()
305305
message(FATAL_ERROR "We need either CPPINTEROP_USE_CLING or CPPINTEROP_USE_REPL")
306306
endif()
307307

308+
if (EMSCRIPTEN AND NOT BUILD_SHARED_LIBS)
309+
add_definitions(-DEMSCRIPTEN_STATIC_LIBRARY)
310+
endif()
311+
308312
include_directories(SYSTEM ${CLANG_INCLUDE_DIRS})
309313
include_directories(SYSTEM ${LLVM_INCLUDE_DIRS})
310314
separate_arguments(LLVM_DEFINITIONS_LIST NATIVE_COMMAND ${LLVM_DEFINITIONS})

lib/CppInterOp/CMakeLists.txt

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ if(EMSCRIPTEN)
122122

123123
# Replace newlines with spaces
124124
string(REPLACE "\n" " " SYMBOLS_LIST "${SYMBOLS_LIST}")
125-
125+
if(BUILD_SHARED_LIBS)
126126
set_target_properties(clangCppInterOp
127127
PROPERTIES NO_SONAME 1
128128
)
@@ -131,8 +131,13 @@ if(EMSCRIPTEN)
131131
PRIVATE "SHELL: -s SIDE_MODULE=1"
132132
PRIVATE "SHELL: ${SYMBOLS_LIST}"
133133
)
134+
else()
135+
target_link_options(clangCppInterOp
136+
PRIVATE "SHELL: -s WASM_BIGINT"
137+
)
138+
endif()
134139
if (CPPINTEROP_ENABLE_TESTING)
135-
# When compiling Emscripten tests the shared library it links to is expected to be in the same folder as the compiled Javascript
140+
# When compiling Emscripten tests the CppInterOp library it links to is expected to be in the same folder as the compiled Javascript
136141
add_custom_command(TARGET clangCppInterOp POST_BUILD
137142
COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:clangCppInterOp> ${CMAKE_BINARY_DIR}/unittests/CppInterOp/
138143
)

unittests/CppInterOp/FunctionReflectionTest.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2486,7 +2486,9 @@ TEST(FunctionReflectionTest, FailingTest1) {
24862486
GTEST_SKIP() << "Disabled on Windows. Needs fixing.";
24872487
#endif
24882488
#ifdef EMSCRIPTEN
2489-
GTEST_SKIP() << "Test fails for Emscipten builds";
2489+
#ifndef EMSCRIPTEN_STATIC_LIBRARY
2490+
GTEST_SKIP() << "Test fails for Emscipten shared library builds";
2491+
#endif
24902492
#endif
24912493
Cpp::CreateInterpreter();
24922494
EXPECT_FALSE(Cpp::Declare(R"(

unittests/CppInterOp/InterpreterTest.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,9 @@ TEST(InterpreterTest, DeleteInterpreter) {
9999
}
100100

101101
TEST(InterpreterTest, ActivateInterpreter) {
102+
#ifdef EMSCRIPTEN_STATIC_LIBRARY
103+
GTEST_SKIP() << "Test fails for Emscipten static library build";
104+
#endif // EMSCRIPTEN_STATIC_LIBRARY
102105
EXPECT_FALSE(Cpp::ActivateInterpreter(nullptr));
103106
auto* Cpp14 = Cpp::CreateInterpreter({"-std=c++14"});
104107
auto* Cpp17 = Cpp::CreateInterpreter({"-std=c++17"});
@@ -122,6 +125,9 @@ TEST(InterpreterTest, ActivateInterpreter) {
122125
}
123126

124127
TEST(InterpreterTest, Process) {
128+
#ifdef EMSCRIPTEN_STATIC_LIBRARY
129+
GTEST_SKIP() << "Test fails for Emscipten static library build";
130+
#endif // EMSCRIPTEN_STATIC_LIBRARY
125131
#ifdef _WIN32
126132
GTEST_SKIP() << "Disabled on Windows. Needs fixing.";
127133
#endif

0 commit comments

Comments
 (0)