diff --git a/.github/workflows/deploy-pages.yml b/.github/workflows/deploy-pages.yml index ee6c61ed5..6673f6fe9 100644 --- a/.github/workflows/deploy-pages.yml +++ b/.github/workflows/deploy-pages.yml @@ -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 @@ -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 }} \ @@ -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 @@ -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 @@ -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 diff --git a/.github/workflows/emscripten.yml b/.github/workflows/emscripten.yml index e37bbfd0b..7444d37df 100644 --- a/.github/workflows/emscripten.yml +++ b/.github/workflows/emscripten.yml @@ -548,10 +548,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 @@ -585,6 +586,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 }} \ @@ -597,13 +599,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 @@ -616,7 +620,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 @@ -631,6 +634,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 diff --git a/CMakeLists.txt b/CMakeLists.txt index aae32a058..c5b8f48cc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -361,7 +361,7 @@ 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") @@ -451,11 +451,6 @@ 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") - set(CPPINTEROP_ENABLE_TESTING OFF) -endif() - if(MSVC) set(MSVC_EXPORTLIST diff --git a/Emscripten-build-instructions.md b/Emscripten-build-instructions.md index 662643db3..943062f07 100644 --- a/Emscripten-build-instructions.md +++ b/Emscripten-build-instructions.md @@ -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 @@ -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 @@ -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 ``` @@ -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 diff --git a/cmake/modules/GoogleTest.cmake b/cmake/modules/GoogleTest.cmake index a753c1c94..18a1bc81c 100644 --- a/cmake/modules/GoogleTest.cmake +++ b/cmake/modules/GoogleTest.cmake @@ -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 --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 $) +endif() + ExternalProject_Add( googletest GIT_REPOSITORY https://github.com/google/googletest.git @@ -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=$ -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER} -DCMAKE_C_FLAGS=${CMAKE_C_FLAGS} @@ -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} diff --git a/docs/Emscripten-build-instructions.rst b/docs/Emscripten-build-instructions.rst index aa0254c3f..f849f64bf 100644 --- a/docs/Emscripten-build-instructions.rst +++ b/docs/Emscripten-build-instructions.rst @@ -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 @@ -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 @@ -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 @@ -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 diff --git a/include/clang/Interpreter/CppInterOp.h b/include/clang/Interpreter/CppInterOp.h index c0cb234aa..76b5f973f 100644 --- a/include/clang/Interpreter/CppInterOp.h +++ b/include/clang/Interpreter/CppInterOp.h @@ -563,12 +563,12 @@ namespace Cpp { TCppIndex_t param_index); ///\returns arity of the operator or kNone - OperatorArity GetOperatorArity(TCppFunction_t op); + CPPINTEROP_API OperatorArity GetOperatorArity(TCppFunction_t op); ///\returns list of operator overloads - void GetOperator(TCppScope_t scope, Operator op, - std::vector& operators, - OperatorArity kind = kBoth); + CPPINTEROP_API void GetOperator(TCppScope_t scope, Operator op, + std::vector& operators, + OperatorArity kind = kBoth); /// Creates an instance of the interpreter we need for the various interop /// services. diff --git a/lib/Interpreter/CMakeLists.txt b/lib/Interpreter/CMakeLists.txt index a9f8fcaa6..cd2f46571 100644 --- a/lib/Interpreter/CMakeLists.txt +++ b/lib/Interpreter/CMakeLists.txt @@ -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} @@ -44,7 +18,7 @@ else() if ("LLVMOrcDebugging" IN_LIST LLVM_AVAILABLE_LIBS) list(APPEND LLVM_LINK_COMPONENTS OrcDebugging) endif() - +endif() set(DLM DynamicLibraryManager.cpp DynamicLibraryManagerSymbol.cpp @@ -65,6 +39,11 @@ else() set(cling_clang_interp clangInterpreter) endif() +if(EMSCRIPTEN) + set(link_libs + ${cling_clang_interp} + ) +else() set(link_libs ${cling_clang_interp} clangAST @@ -73,8 +52,9 @@ else() clangLex clangSema ) +endif() - if(NOT WIN32) + if(NOT WIN32 AND NOT EMSCRIPTEN) list(APPEND link_libs dl) endif() @@ -124,7 +104,6 @@ else() clangStaticAnalyzerCore ) endif(LLVM_LINK_LLVM_DYLIB) - add_llvm_library(clangCppInterOp DISABLE_LLVM_LINK_LLVM_DYLIB CppInterOp.cpp @@ -134,9 +113,37 @@ else() ${link_libs} ) - target_compile_definitions(clangCppInterOp PUBLIC "_CINDEX_LIB_") # workaround for the use of `CINDEX_LINKAGE` + +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 + LINK_FLAGS "-s WASM_BIGINT -s SIDE_MODULE=1 ${SYMBOLS_LIST}" + ) + 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 + add_custom_command(TARGET clangCppInterOp POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy $ ${CMAKE_BINARY_DIR}/unittests/CppInterOp/ + ) + endif(CPPINTEROP_ENABLE_TESTING) + endif() +target_compile_definitions(clangCppInterOp PUBLIC "_CINDEX_LIB_") # workaround for the use of `CINDEX_LINKAGE` + string(REPLACE ";" "\;" _VER CPPINTEROP_VERSION) set_source_files_properties(CppInterOp.cpp PROPERTIES COMPILE_DEFINITIONS "LLVM_BINARY_DIR=\"${LLVM_BINARY_DIR}\";CPPINTEROP_VERSION=\"${_VAR}\"" diff --git a/lib/Interpreter/exports.ld b/lib/Interpreter/exports.ld new file mode 100644 index 000000000..2e913dec1 --- /dev/null +++ b/lib/Interpreter/exports.ld @@ -0,0 +1,39 @@ +-Wl,--export=_ZN4llvm11raw_ostream14flush_nonemptyEv +-Wl,--export=_ZN4llvm11raw_ostream16SetBufferAndModeEPcmNS0_10BufferKindE +-Wl,--export=_ZN4llvm11raw_ostream5writeEPKcm +-Wl,--export=_ZN4llvm11raw_ostreamD2Ev +-Wl,--export=_ZN4llvm15SmallVectorBaseIjE8grow_podEPvmm +-Wl,--export=_ZN4llvm15allocate_bufferEmm +-Wl,--export=_ZN4llvm21logAllUnhandledErrorsENS_5ErrorERNS_11raw_ostreamENS_5TwineE +-Wl,--export=_ZN4llvm25llvm_unreachable_internalEPKcS1_j +-Wl,--export=_ZN4llvm3sys17RunningOnValgrindEv +-Wl,--export=_ZN4llvm4dbgsEv +-Wl,--export=_ZN4llvm4errsEv +-Wl,--export=_ZN4llvm5APIntC1EjNS_8ArrayRefIyEE +-Wl,--export=_ZN5clang10ASTContext19createMangleContextEPKNS_10TargetInfoE +-Wl,--export=_ZN5clang11DeclContext7classofEPKNS_4DeclE +-Wl,--export=_ZN5clang11Interpreter19getCompilerInstanceEv +-Wl,--export=_ZN5clang11Interpreter5ParseEN4llvm9StringRefE +-Wl,--export=_ZN5clang11Interpreter6createENSt3__210unique_ptrINS_16CompilerInstanceENS1_14default_deleteIS3_EEEE +-Wl,--export=_ZN5clang11Interpreter7ExecuteERNS_22PartialTranslationUnitE +-Wl,--export=_ZN5clang13MangleContext10mangleNameENS_10GlobalDeclERN4llvm11raw_ostreamE +-Wl,--export=_ZN5clang13MangleContext20shouldMangleDeclNameEPKNS_9NamedDeclE +-Wl,--export=_ZN5clang26IncrementalCompilerBuilder9CreateCppEv +-Wl,--export=_ZN5clang4Decl17castToDeclContextEPKS0_ +-Wl,--export=_ZNK4llvm5APInt13compareSignedERKS0_ +-Wl,--export=_ZNK4llvm5APInt4sextEj +-Wl,--export=_ZNK4llvm5APInt4zextEj +-Wl,--export=_ZNK4llvm5APInt7compareERKS0_ +-Wl,--export=_ZNK4llvm5Error19fatalUncheckedErrorEv +-Wl,--export=_ZNK5clang10ASTContext22getLValueReferenceTypeENS_8QualTypeEb +-Wl,--export=_ZNK5clang11DeclContext11decls_beginEv +-Wl,--export=_ZNK5clang12FunctionDecl29getTemplateSpecializationArgsEv +-Wl,--export=_ZNK5clang12FunctionDecl31getTemplateInstantiationPatternEb +-Wl,--export=_ZNK5clang29VarTemplateSpecializationDecl22getSpecializedTemplateEv +-Wl,--export=_ZNK5clang4Decl13getASTContextEv +-Wl,--export=_ZNK5clang4Decl15hasDefiningAttrEv +-Wl,--export=_ZNK5clang4Decl8getAttrsEv +-Wl,--export=_ZNK5clang4Type27getUnqualifiedDesugaredTypeEv +-Wl,--export=_ZNK5clang7TagType7getDeclEv +-Wl,--export=_ZNK5clang7VarDecl28isThisDeclarationADefinitionERNS_10ASTContextE +-Wl,--export=_ZTVN4llvm18raw_string_ostreamE diff --git a/unittests/CMakeLists.txt b/unittests/CMakeLists.txt index 972b1e475..dddb1aaf7 100644 --- a/unittests/CMakeLists.txt +++ b/unittests/CMakeLists.txt @@ -7,10 +7,15 @@ if (NOT TARGET gtest) include(GoogleTest) endif() -set(gtest_libs gtest gtest_main) -# Clang prior than clang13 (I think) merges both gmock into gtest. -if (TARGET gmock) - list(APPEND gtest_libs gmock gmock_main) +if(EMSCRIPTEN) + set(gtest_libs gtest gmock) +else() + set(gtest_libs gtest gtest_main) + # Clang prior than clang13 (I think) merges both gmock into gtest. + if (TARGET gmock) + list(APPEND gtest_libs gmock gmock_main) + endif() + set(link_pthreads_lib pthread) endif() add_custom_target(CppInterOpUnitTests) @@ -23,12 +28,11 @@ function(add_cppinterop_unittest name) add_dependencies(CppInterOpUnitTests ${name}) target_include_directories(${name} PUBLIC ${CMAKE_CURRENT_BINARY_DIR} ${GTEST_INCLUDE_DIR}) set_property(TARGET ${name} PROPERTY RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) - if(WIN32) target_link_libraries(${name} PUBLIC ${ARG_LIBRARIES} ${gtest_libs}) set_property(TARGET ${name} APPEND_STRING PROPERTY LINK_FLAGS "${MSVC_EXPORTS}") else() - target_link_libraries(${name} PUBLIC ${ARG_LIBRARIES} ${gtest_libs} pthread) + target_link_libraries(${name} PRIVATE ${ARG_LIBRARIES} ${gtest_libs} ${link_pthreads_lib}) endif() add_test(NAME cppinterop-${name} COMMAND ${name}) set_tests_properties(cppinterop-${name} PROPERTIES diff --git a/unittests/CppInterOp/CMakeLists.txt b/unittests/CppInterOp/CMakeLists.txt index 25f59b394..da02dbcef 100644 --- a/unittests/CppInterOp/CMakeLists.txt +++ b/unittests/CppInterOp/CMakeLists.txt @@ -1,9 +1,18 @@ set(LLVM_LINK_COMPONENTS Support ) +if (EMSCRIPTEN) + # Omitting CUDATest.cpp since Emscripten build currently has no GPU support + # For Emscripten builds linking to gtest_main will not suffice for gtest to run + # the tests and an explictly main.cpp is needed + set(EXTRA_TEST_SOURCE_FILES main.cpp) +else() + # Do not need main.cpp for native builds, but we do have GPU support for native builds + set(EXTRA_TEST_SOURCE_FILES CUDATest.cpp) + set(EXTRA_PATH_TEST_BINARIES /CppInterOpTests/unittests/bin/$/) +endif() add_cppinterop_unittest(CppInterOpTests - CUDATest.cpp EnumReflectionTest.cpp FunctionReflectionTest.cpp InterpreterTest.cpp @@ -12,16 +21,31 @@ add_cppinterop_unittest(CppInterOpTests TypeReflectionTest.cpp Utils.cpp VariableReflectionTest.cpp + ${EXTRA_TEST_SOURCE_FILES} ) +if(EMSCRIPTEN) + # Explaination of compile and link flags + # To dynamically link to a shared library for Emscripten builds you must use the MAIN_MODULE flag (see both https://github.com/emscripten-core/emscripten/issues/23543#issuecomment-2625334414 + # and https://emscripten.org/docs/compiling/Dynamic-Linking.html) + # Without WASM_BIGINT flag then you get fatal errors when trying to run compiled Javascript about trying to convert between BigInt and non BigInt types + # EXPORTED_RUNTIME_METHODS='[\"FS\",\"PATH\",\"LDSO\",\"loadDynamicLibrary\",\"ERRNO_CODES\"]' and --preload-file ${SYSROOT_PATH}/include@/include are not allow the Javascript that is + # compiled to have access to the standard library headers (approach taken from xeus-cpp) + # Without ALLOW_MEMORY_GROWTH=1 tests will fail with aborted(OOM). Approach to fix taken from answers to + # https://stackoverflow.com/questions/67222200/runtimeerror-abortoom-build-with-s-assertions-1-for-more-info + set_target_properties(CppInterOpTests PROPERTIES + LINK_FLAGS "-s MAIN_MODULE=1 -s WASM_BIGINT -s EXPORTED_RUNTIME_METHODS='[\"FS\",\"PATH\",\"LDSO\",\"loadDynamicLibrary\",\"ERRNO_CODES\"]' --preload-file ${SYSROOT_PATH}/include@/include -s ALLOW_MEMORY_GROWTH=1" + ) +endif() + target_link_libraries(CppInterOpTests PRIVATE clangCppInterOp ) set_output_directory(CppInterOpTests - BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/CppInterOpTests/unittests/bin/$/ - LIBRARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/CppInterOpTests/unittests/bin/$/ + BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/${EXTRA_PATH_TEST_BINARIES} + LIBRARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/${EXTRA_PATH_TEST_BINARIES} ) if(NOT WIN32) @@ -37,16 +61,37 @@ export_executable_symbols(CppInterOpTests) unset(LLVM_LINK_COMPONENTS) -add_cppinterop_unittest(DynamicLibraryManagerTests DynamicLibraryManagerTest.cpp) +add_cppinterop_unittest(DynamicLibraryManagerTests DynamicLibraryManagerTest.cpp ${EXTRA_TEST_SOURCE_FILES}) + target_link_libraries(DynamicLibraryManagerTests PRIVATE clangCppInterOp ) +if(EMSCRIPTEN) + # Explaination of compile and link flags + # To dynamically link to a shared library for Emscripten builds you must use the MAIN_MODULE flag (see both https://github.com/emscripten-core/emscripten/issues/23543#issuecomment-2625334414 + # and https://emscripten.org/docs/compiling/Dynamic-Linking.html) + # Without WASM_BIGINT flag then you get fatal errors when trying to run compiled Javascript about trying to convert between BigInt and non BigInt types + # EXPORTED_RUNTIME_METHODS='[\"FS\",\"PATH\",\"LDSO\",\"loadDynamicLibrary\",\"ERRNO_CODES\"]' and --preload-file ${SYSROOT_PATH}/include@/include are not allow the Javascript that is + # compiled to have access to the standard library headers (approach taken from xeus-cpp) + # Without ALLOW_MEMORY_GROWTH=1 tests will fail with aborted(OOM). Approach to fix taken from answers to + # https://stackoverflow.com/questions/67222200/runtimeerror-abortoom-build-with-s-assertions-1-for-more-info + set_target_properties(DynamicLibraryManagerTests PROPERTIES + LINK_FLAGS "-s MAIN_MODULE=1 -s WASM_BIGINT -s EXPORTED_RUNTIME_METHODS='[\"FS\",\"PATH\",\"LDSO\",\"loadDynamicLibrary\",\"ERRNO_CODES\"]' --preload-file ${SYSROOT_PATH}/include@/include -s ALLOW_MEMORY_GROWTH=1" + ) +endif() + + if (NOT EMSCRIPTEN) + set(EXTRA_PATH_TEST_BINARIES /TestSharedLib/unittests/bin/$/) +endif() + set_output_directory(DynamicLibraryManagerTests - BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/TestSharedLib/unittests/bin/$/ - LIBRARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/TestSharedLib/unittests/bin/$/ + BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/${EXTRA_PATH_TEST_BINARIES} + LIBRARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/${EXTRA_PATH_TEST_BINARIES} ) + add_dependencies(DynamicLibraryManagerTests TestSharedLib) + #export_executable_symbols_for_plugins(TestSharedLib) add_subdirectory(TestSharedLib) diff --git a/unittests/CppInterOp/DynamicLibraryManagerTest.cpp b/unittests/CppInterOp/DynamicLibraryManagerTest.cpp index 01624ef78..c881d9fdd 100644 --- a/unittests/CppInterOp/DynamicLibraryManagerTest.cpp +++ b/unittests/CppInterOp/DynamicLibraryManagerTest.cpp @@ -18,6 +18,9 @@ std::string GetExecutablePath(const char* Argv0) { } TEST(DynamicLibraryManagerTest, Sanity) { +#ifdef EMSCRIPTEN + GTEST_SKIP() << "Test fails for Emscipten builds"; +#endif EXPECT_TRUE(Cpp::CreateInterpreter()); EXPECT_FALSE(Cpp::GetFunctionAddress("ret_zero")); diff --git a/unittests/CppInterOp/FunctionReflectionTest.cpp b/unittests/CppInterOp/FunctionReflectionTest.cpp index feb028cea..055115fd0 100644 --- a/unittests/CppInterOp/FunctionReflectionTest.cpp +++ b/unittests/CppInterOp/FunctionReflectionTest.cpp @@ -547,6 +547,9 @@ TEST(FunctionReflectionTest, ExistsFunctionTemplate) { } TEST(FunctionReflectionTest, InstantiateTemplateFunctionFromString) { +#ifdef EMSCRIPTEN + GTEST_SKIP() << "Test crashes gtest on Emscipten"; +#endif if (llvm::sys::RunningOnValgrind()) GTEST_SKIP() << "XFAIL due to Valgrind report"; Cpp::CreateInterpreter(); @@ -1049,6 +1052,9 @@ TEST(FunctionReflectionTest, IsStaticMethod) { } TEST(FunctionReflectionTest, GetFunctionAddress) { +#ifdef EMSCRIPTEN + GTEST_SKIP() << "Test crashes gtest on Emscipten"; +#endif if (llvm::sys::RunningOnValgrind()) GTEST_SKIP() << "XFAIL due to Valgrind report"; #ifdef _WIN32 @@ -1093,6 +1099,9 @@ TEST(FunctionReflectionTest, IsVirtualMethod) { } TEST(FunctionReflectionTest, JitCallAdvanced) { +#ifdef EMSCRIPTEN + GTEST_SKIP() << "Test crashes gtest on Emscipten"; +#endif if (llvm::sys::RunningOnValgrind()) GTEST_SKIP() << "XFAIL due to Valgrind report"; std::vector Decls; @@ -1117,6 +1126,9 @@ TEST(FunctionReflectionTest, JitCallAdvanced) { TEST(FunctionReflectionTest, GetFunctionCallWrapper) { +#ifdef EMSCRIPTEN + GTEST_SKIP() << "Test crashes gtest on Emscipten"; +#endif if (llvm::sys::RunningOnValgrind()) GTEST_SKIP() << "XFAIL due to Valgrind report"; #if defined(CPPINTEROP_USE_CLING) && defined(_WIN32) @@ -1424,6 +1436,9 @@ TEST(FunctionReflectionTest, GetFunctionArgDefault) { } TEST(FunctionReflectionTest, Construct) { +#ifdef EMSCRIPTEN + GTEST_SKIP() << "Test fails for Emscipten builds"; +#endif if (llvm::sys::RunningOnValgrind()) GTEST_SKIP() << "XFAIL due to Valgrind report"; #ifdef _WIN32 @@ -1464,6 +1479,9 @@ TEST(FunctionReflectionTest, Construct) { } TEST(FunctionReflectionTest, Destruct) { +#ifdef EMSCRIPTEN + GTEST_SKIP() << "Test fails for Emscipten builds"; +#endif if (llvm::sys::RunningOnValgrind()) GTEST_SKIP() << "XFAIL due to Valgrind report"; diff --git a/unittests/CppInterOp/InterpreterTest.cpp b/unittests/CppInterOp/InterpreterTest.cpp index a0a0d1b3a..19ce70e13 100644 --- a/unittests/CppInterOp/InterpreterTest.cpp +++ b/unittests/CppInterOp/InterpreterTest.cpp @@ -58,6 +58,9 @@ TEST(InterpreterTest, DebugFlag) { } TEST(InterpreterTest, Evaluate) { +#ifdef EMSCRIPTEN + GTEST_SKIP() << "Test fails for Emscipten builds"; +#endif #ifdef _WIN32 GTEST_SKIP() << "Disabled on Windows. Needs fixing."; #endif @@ -126,6 +129,9 @@ TEST(InterpreterTest, CreateInterpreter) { #ifdef LLVM_BINARY_DIR TEST(InterpreterTest, DetectResourceDir) { +#ifdef EMSCRIPTEN + GTEST_SKIP() << "Test fails for Emscipten builds"; +#endif #else TEST(InterpreterTest, DISABLED_DetectResourceDir) { #endif // LLVM_BINARY_DIR @@ -145,6 +151,9 @@ TEST(InterpreterTest, DISABLED_DetectResourceDir) { } TEST(InterpreterTest, DetectSystemCompilerIncludePaths) { +#ifdef EMSCRIPTEN + GTEST_SKIP() << "Test fails for Emscipten builds"; +#endif #ifdef _WIN32 GTEST_SKIP() << "Disabled on Windows. Needs fixing."; #endif diff --git a/unittests/CppInterOp/JitTest.cpp b/unittests/CppInterOp/JitTest.cpp index 310f87efe..b9c2a75c2 100644 --- a/unittests/CppInterOp/JitTest.cpp +++ b/unittests/CppInterOp/JitTest.cpp @@ -12,6 +12,9 @@ static int printf_jit(const char* format, ...) { } TEST(JitTest, InsertOrReplaceJitSymbol) { +#ifdef EMSCRIPTEN + GTEST_SKIP() << "Test fails for Emscipten builds"; +#endif if (llvm::sys::RunningOnValgrind()) GTEST_SKIP() << "XFAIL due to Valgrind report"; #ifdef _WIN32 diff --git a/unittests/CppInterOp/ScopeReflectionTest.cpp b/unittests/CppInterOp/ScopeReflectionTest.cpp index b3edf5b00..f8b4a27cb 100644 --- a/unittests/CppInterOp/ScopeReflectionTest.cpp +++ b/unittests/CppInterOp/ScopeReflectionTest.cpp @@ -161,6 +161,9 @@ TEST(ScopeReflectionTest, SizeOf) { TEST(ScopeReflectionTest, IsBuiltin) { +#ifdef EMSCRIPTEN + GTEST_SKIP() << "Test crashes gtest on Emscipten"; +#endif // static std::set g_builtins = // {"bool", "char", "signed char", "unsigned char", "wchar_t", "short", "unsigned short", // "int", "unsigned int", "long", "unsigned long", "long long", "unsigned long long", @@ -491,6 +494,9 @@ TEST(ScopeReflectionTest, GetScopefromCompleteName) { } TEST(ScopeReflectionTest, GetNamed) { +#ifdef EMSCRIPTEN + GTEST_SKIP() << "Test crashes gtest on Emscipten"; +#endif std::string code = R"(namespace N1 { namespace N2 { class C { @@ -876,6 +882,9 @@ template T TrivialFnTemplate() { return T(); } } TEST(ScopeReflectionTest, InstantiateTemplateFunctionFromString) { +#ifdef EMSCRIPTEN + GTEST_SKIP() << "Test crashes gtest on Emscipten"; +#endif if (llvm::sys::RunningOnValgrind()) GTEST_SKIP() << "XFAIL due to Valgrind report"; Cpp::CreateInterpreter(); @@ -1016,6 +1025,9 @@ TEST(ScopeReflectionTest, GetClassTemplateInstantiationArgs) { TEST(ScopeReflectionTest, IncludeVector) { +#ifdef EMSCRIPTEN + GTEST_SKIP() << "Test crashes gtest on Emscipten"; +#endif if (llvm::sys::RunningOnValgrind()) GTEST_SKIP() << "XFAIL due to Valgrind report"; std::string code = R"( diff --git a/unittests/CppInterOp/TestSharedLib/CMakeLists.txt b/unittests/CppInterOp/TestSharedLib/CMakeLists.txt index 05f1afb3f..cb209edac 100644 --- a/unittests/CppInterOp/TestSharedLib/CMakeLists.txt +++ b/unittests/CppInterOp/TestSharedLib/CMakeLists.txt @@ -8,4 +8,13 @@ set_output_directory(TestSharedLib BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/unittests/bin/$/ LIBRARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/unittests/bin/$/ ) + + +if (EMSCRIPTEN) + set_target_properties(TestSharedLib PROPERTIES + NO_SONAME 1 + LINK_FLAGS "-s WASM_BIGINT -s SIDE_MODULE=1" + ) +endif() + set_target_properties(TestSharedLib PROPERTIES FOLDER "Tests") diff --git a/unittests/CppInterOp/TypeReflectionTest.cpp b/unittests/CppInterOp/TypeReflectionTest.cpp index 4f47c0229..7f9b0977f 100644 --- a/unittests/CppInterOp/TypeReflectionTest.cpp +++ b/unittests/CppInterOp/TypeReflectionTest.cpp @@ -546,6 +546,9 @@ TEST(TypeReflectionTest, IsPODType) { } TEST(TypeReflectionTest, IsSmartPtrType) { +#ifdef EMSCRIPTEN + GTEST_SKIP() << "Test crashes gtest on Emscipten"; +#endif if (llvm::sys::RunningOnValgrind()) GTEST_SKIP() << "XFAIL due to Valgrind report"; Cpp::CreateInterpreter(); diff --git a/unittests/CppInterOp/VariableReflectionTest.cpp b/unittests/CppInterOp/VariableReflectionTest.cpp index 8b76e7f5c..b58931a51 100644 --- a/unittests/CppInterOp/VariableReflectionTest.cpp +++ b/unittests/CppInterOp/VariableReflectionTest.cpp @@ -263,6 +263,9 @@ TEST(VariableReflectionTest, GetVariableType) { CODE TEST(VariableReflectionTest, GetVariableOffset) { +#ifdef EMSCRIPTEN + GTEST_SKIP() << "Test crashes gtest on Emscipten"; +#endif std::vector Decls; #define Stringify(s) Stringifyx(s) #define Stringifyx(...) #__VA_ARGS__ @@ -328,6 +331,9 @@ TEST(VariableReflectionTest, GetVariableOffset) { CODE TEST(VariableReflectionTest, VariableOffsetsWithInheritance) { +#ifdef EMSCRIPTEN + GTEST_SKIP() << "Test crashes gtest on Emscipten"; +#endif if (llvm::sys::RunningOnValgrind()) GTEST_SKIP() << "XFAIL due to Valgrind report"; diff --git a/unittests/CppInterOp/main.cpp b/unittests/CppInterOp/main.cpp new file mode 100644 index 000000000..09799f80a --- /dev/null +++ b/unittests/CppInterOp/main.cpp @@ -0,0 +1,6 @@ +#include + +int main(int argc, char** argv) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} \ No newline at end of file