diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index c92aac1484..d24a897b9e 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -1402,3 +1402,7 @@ if (CMake_TEST_Renesas_TOOLCHAINS) add_RunCMake_test(Renesas -DCMake_TEST_Renesas_TOOLCHAINS=${CMake_TEST_Renesas_TOOLCHAINS}) set_property(TEST RunCMake.Renesas APPEND PROPERTY LABELS "Renesas") endif() +if(CMake_TEST_Emscripten_TOOLCHAINS) + add_RunCMake_test(Emscripten -DCMake_TEST_Emscripten_TOOLCHAINS=${CMake_TEST_Emscripten_TOOLCHAINS}) + set_property(TEST RunCMake.Emscripten APPEND PROPERTY LABELS "Emscripten") +endif() diff --git a/Tests/RunCMake/Emscripten/CMakeLists.txt b/Tests/RunCMake/Emscripten/CMakeLists.txt new file mode 100644 index 0000000000..955802cde9 --- /dev/null +++ b/Tests/RunCMake/Emscripten/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 4.0) +project(${RunCMake_TEST} NONE) +include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/Emscripten/RunCMakeTest.cmake b/Tests/RunCMake/Emscripten/RunCMakeTest.cmake new file mode 100644 index 0000000000..efce6302c1 --- /dev/null +++ b/Tests/RunCMake/Emscripten/RunCMakeTest.cmake @@ -0,0 +1,66 @@ +include(RunCMake) + +# Locate Emscripten toolchain +if(RunCMake_GENERATOR MATCHES "Makefile|Ninja") + file(GLOB _emscripten_toolchains + "${CMake_TEST_Emscripten_TOOLCHAINS}/emcc" ) + if(_emscripten_toolchains STREQUAL "") + message(FATAL_ERROR "Could not find any Emscripten toolchains at: ${CMake_TEST_Emscripten_TOOLCHAINS}.") + endif() +endif() + +function(run_toolchain case) + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${case}-build) + run_cmake_with_options(${case} ${ARGN}) + set(RunCMake_TEST_NO_CLEAN 1) + run_cmake_command(${case}-build ${CMAKE_COMMAND} --build .) +endfunction() + +macro(run_cmake_target test subtest target) + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${test}-build) + set(RunCMake_TEST_NO_CLEAN 1) + run_cmake_command(${test}-${subtest}-build ${CMAKE_COMMAND} --build . --target ${target} --config Release --verbose ${ARGN}) + unset(RunCMake_TEST_BINARY_DIR) + unset(RunCMake_TEST_NO_CLEAN) +endmacro() + +foreach(_emscripten_toolchain IN LISTS _emscripten_toolchains) + message(STATUS "Found Emscripten toolchain: ${_emscripten_toolchain}") + cmake_path(GET _emscripten_toolchain PARENT_PATH BIN_DIR) + + if (WIN32) + set(EMCC_SUFFIX ".bat") + else() + set(EMCC_SUFFIX "") + endif() + + set(c_comp ${BIN_DIR}/emcc${EMCC_SUFFIX}) + set(cxx_comp ${BIN_DIR}/em++${EMCC_SUFFIX}) + set(comp_ar ${BIN_DIR}/emar${EMCC_SUFFIX}) + + # Create an executable from .c sources only. + run_toolchain(emscripten-c + -DCMAKE_SYSTEM_NAME=Emscripten + -DCMAKE_C_COMPILER=${c_comp} + ) + + # Create an executable from .c and .cxx sources. + run_toolchain(emscripten-cxx + -DCMAKE_SYSTEM_NAME=Emscripten + -DCMAKE_C_COMPILER=${c_comp} + -DCMAKE_CXX_COMPILER=${cxx_comp} + ) + + # Create a library and executable from .c sources. + run_toolchain(emscripten-lib + -DCMAKE_SYSTEM_NAME=Emscripten + -DCMAKE_C_COMPILER=${c_comp} + ) + + run_cmake_with_options(emscripten-WHOLE_ARCHIVE + -DCMAKE_SYSTEM_NAME=Emscripten + -DCMAKE_C_COMPILER=${c_comp} + ) + run_cmake_target(emscripten-WHOLE_ARCHIVE link-exe main) + run_cmake_target(emscripten-WHOLE_ARCHIVE circular-exe main_circular) +endforeach() diff --git a/Tests/RunCMake/Emscripten/base.c b/Tests/RunCMake/Emscripten/base.c new file mode 100644 index 0000000000..ed769a07b0 --- /dev/null +++ b/Tests/RunCMake/Emscripten/base.c @@ -0,0 +1,9 @@ + +#if !defined(STATIC_BASE) +# if defined(_WIN32) +__declspec(dllexport) +# endif +#endif + void base(void) +{ +} diff --git a/Tests/RunCMake/Emscripten/circular1.c b/Tests/RunCMake/Emscripten/circular1.c new file mode 100644 index 0000000000..80ee413a18 --- /dev/null +++ b/Tests/RunCMake/Emscripten/circular1.c @@ -0,0 +1,6 @@ +void circular2(void); + +void circular1(void) +{ + circular2(); +} diff --git a/Tests/RunCMake/Emscripten/circular2.c b/Tests/RunCMake/Emscripten/circular2.c new file mode 100644 index 0000000000..751bab5dd4 --- /dev/null +++ b/Tests/RunCMake/Emscripten/circular2.c @@ -0,0 +1,7 @@ + +void circular1(void); + +void circular2(void) +{ + circular1(); +} diff --git a/Tests/RunCMake/Emscripten/emscripten-WHOLE_ARCHIVE.cmake b/Tests/RunCMake/Emscripten/emscripten-WHOLE_ARCHIVE.cmake new file mode 100644 index 0000000000..e826eaea70 --- /dev/null +++ b/Tests/RunCMake/Emscripten/emscripten-WHOLE_ARCHIVE.cmake @@ -0,0 +1,20 @@ + +enable_language(C) + +add_library(base STATIC base.c unref.c) +target_compile_definitions(base PUBLIC STATIC_BASE) + +add_library(lib SHARED lib.c) +target_link_libraries(lib PRIVATE "$") + +add_executable(main main.c) +target_link_libraries(main PRIVATE lib) + +add_library(circular1 STATIC circular1.c) +add_library(circular2 STATIC circular2.c) + +target_link_libraries(circular1 PRIVATE circular2) +target_link_libraries(circular2 PRIVATE circular1) + +add_executable(main_circular main_circular.c) +target_link_libraries(main_circular PRIVATE $) diff --git a/Tests/RunCMake/Emscripten/emscripten-c.cmake b/Tests/RunCMake/Emscripten/emscripten-c.cmake new file mode 100644 index 0000000000..39325a7d81 --- /dev/null +++ b/Tests/RunCMake/Emscripten/emscripten-c.cmake @@ -0,0 +1,2 @@ +enable_language(C) +add_executable(exec-c module.c) diff --git a/Tests/RunCMake/Emscripten/emscripten-cxx.cmake b/Tests/RunCMake/Emscripten/emscripten-cxx.cmake new file mode 100644 index 0000000000..9e00aa39c7 --- /dev/null +++ b/Tests/RunCMake/Emscripten/emscripten-cxx.cmake @@ -0,0 +1,2 @@ +enable_language(CXX) +add_executable(exec-cxx module.cxx) diff --git a/Tests/RunCMake/Emscripten/emscripten-lib.cmake b/Tests/RunCMake/Emscripten/emscripten-lib.cmake new file mode 100644 index 0000000000..a215d0232a --- /dev/null +++ b/Tests/RunCMake/Emscripten/emscripten-lib.cmake @@ -0,0 +1,6 @@ +enable_language(C) +add_library(emscripten-test-lib libmod.c) + +add_executable(exec-lib-c module.c) +target_compile_definitions(exec-lib-c PRIVATE __USE_LIBFUN) +target_link_libraries(exec-lib-c PRIVATE emscripten-test-lib) diff --git a/Tests/RunCMake/Emscripten/lib.c b/Tests/RunCMake/Emscripten/lib.c new file mode 100644 index 0000000000..21f559cad1 --- /dev/null +++ b/Tests/RunCMake/Emscripten/lib.c @@ -0,0 +1,15 @@ + +#if !defined(STATIC_BASE) +# if defined(_WIN32) +__declspec(dllimport) +# endif +#endif + void base(void); + +#if defined(_WIN32) +__declspec(dllexport) +#endif + void lib(void) +{ + base(); +} diff --git a/Tests/RunCMake/Emscripten/libmod.c b/Tests/RunCMake/Emscripten/libmod.c new file mode 100644 index 0000000000..b0d3952201 --- /dev/null +++ b/Tests/RunCMake/Emscripten/libmod.c @@ -0,0 +1,4 @@ +int emscripten_libfun() +{ + return 42; +} diff --git a/Tests/RunCMake/Emscripten/main.c b/Tests/RunCMake/Emscripten/main.c new file mode 100644 index 0000000000..2e39bceee0 --- /dev/null +++ b/Tests/RunCMake/Emscripten/main.c @@ -0,0 +1,18 @@ + +#if defined(_WIN32) +__declspec(dllimport) +#endif + void lib(void); + +#if defined(_WIN32) +__declspec(dllimport) +#endif + void unref(void); + +int main(void) +{ + lib(); + unref(); + + return 0; +} diff --git a/Tests/RunCMake/Emscripten/main_circular.c b/Tests/RunCMake/Emscripten/main_circular.c new file mode 100644 index 0000000000..16ebee6d76 --- /dev/null +++ b/Tests/RunCMake/Emscripten/main_circular.c @@ -0,0 +1,9 @@ + +void circular1(void); + +int main(void) +{ + circular1(); + + return 0; +} diff --git a/Tests/RunCMake/Emscripten/module.c b/Tests/RunCMake/Emscripten/module.c new file mode 100644 index 0000000000..62014fab67 --- /dev/null +++ b/Tests/RunCMake/Emscripten/module.c @@ -0,0 +1,15 @@ +#include "module.h" +#if defined(__USE_LIBFUN) +extern int emscripten_libfun(); +#endif + +int i; +int main() +{ +#if defined(__USE_LIBFUN) + i = emscripten_libfun(); +#else + i = INTERNAL; +#endif + return i; +} diff --git a/Tests/RunCMake/Emscripten/module.cxx b/Tests/RunCMake/Emscripten/module.cxx new file mode 100644 index 0000000000..b4d46b123f --- /dev/null +++ b/Tests/RunCMake/Emscripten/module.cxx @@ -0,0 +1,7 @@ +#include "module.h" +int i; +int main() +{ + i = INTERNAL; + return i; +} diff --git a/Tests/RunCMake/Emscripten/module.h b/Tests/RunCMake/Emscripten/module.h new file mode 100644 index 0000000000..a8a85a64c4 --- /dev/null +++ b/Tests/RunCMake/Emscripten/module.h @@ -0,0 +1,12 @@ +#ifndef __MODULE_H__ +#define __MODULE_H__ + +#if defined(__cplusplus) +# define INTERNAL 64 +#elif !defined(__cplusplus) +# define INTERNAL 32 +#else +# error "Unable to determine INTERNAL symbol." +#endif + +#endif /* __MODULE_H__ */ diff --git a/Tests/RunCMake/Emscripten/unref.c b/Tests/RunCMake/Emscripten/unref.c new file mode 100644 index 0000000000..11922de0e0 --- /dev/null +++ b/Tests/RunCMake/Emscripten/unref.c @@ -0,0 +1,8 @@ + + +#if defined(_WIN32) +__declspec(dllexport) +#endif + void unref(void) +{ +}