Merge topic 'emscripten-platform'

d89f1cbc16 ci: Enable Emscripten test on some Debian jobs in nightly pipeline
33082bf817 ci: add scripts to install Emscripten 4.0.9
c6da668b13 Emscripten: Add tests for the Emscripten toolchain
96d9b94a98 Emscripten: Add platform modules

Acked-by: Kitware Robot <kwrobot@kitware.com>
Acked-by: buildbot <buildbot@kitware.com>
Merge-request: !10832
This commit is contained in:
Brad King
2025-06-19 14:22:01 +00:00
committed by Kitware Robot
39 changed files with 345 additions and 0 deletions
+1
View File
@@ -2,6 +2,7 @@
/5.15.1-0-202009071110*
/bcc*
/cmake*
/emsdk
/iar
/intel
/ispc*
@@ -4,6 +4,7 @@ set(CMake_TEST_CXX_STANDARDS "98;11;14;17;20;23" CACHE STRING "")
if (NOT "$ENV{CMAKE_CI_NIGHTLY}" STREQUAL "")
set(CMake_TEST_IAR_TOOLCHAINS "/opt/iarsystems" CACHE PATH "")
set(CMake_TEST_TICLANG_TOOLCHAINS "$ENV{CI_PROJECT_DIR}/.gitlab/ticlang" CACHE PATH "")
set(CMake_TEST_Emscripten_TOOLCHAINS "$ENV{CI_PROJECT_DIR}/.gitlab/emsdk/upstream/emscripten" CACHE PATH "")
endif()
include("${CMAKE_CURRENT_LIST_DIR}/configure_external_test.cmake")
@@ -1,6 +1,7 @@
if (NOT "$ENV{CMAKE_CI_NIGHTLY}" STREQUAL "")
set(CMake_TEST_IAR_TOOLCHAINS "/opt/iarsystems" CACHE PATH "")
set(CMake_TEST_TICLANG_TOOLCHAINS "$ENV{CI_PROJECT_DIR}/.gitlab/ticlang" CACHE PATH "")
set(CMake_TEST_Emscripten_TOOLCHAINS "$ENV{CI_PROJECT_DIR}/.gitlab/emsdk/upstream/emscripten" CACHE PATH "")
endif()
include("${CMAKE_CURRENT_LIST_DIR}/configure_external_test.cmake")
+3
View File
@@ -0,0 +1,3 @@
.gitlab/ci/emsdk.sh
. .gitlab/emsdk/emsdk_env.sh
em++ --version
+25
View File
@@ -0,0 +1,25 @@
#!/bin/sh
set -e
case "$(uname -s)-$(uname -m)" in
Linux-x86_64)
;;
*)
echo "Unrecognized platform $(uname -s)-$(uname -m)"
exit 1
;;
esac
cd .gitlab
version=4.0.9
dirname="emsdk-$version"
filename="$dirname.tar.gz"
curl -OJL "https://github.com/emscripten-core/emsdk/archive/refs/tags/$version.tar.gz"
tar xzf "$filename"
mv "$dirname" emsdk
emsdk/emsdk install "$version"
emsdk/emsdk activate "$version"
rm -f "$filename"
@@ -1,6 +1,7 @@
if test "$CMAKE_CI_NIGHTLY" = "true"; then
source .gitlab/ci/iar-env.sh
source .gitlab/ci/ticlang-env.sh
source .gitlab/ci/emsdk-env.sh
fi
export CC=/usr/bin/clang-15
+1
View File
@@ -1,6 +1,7 @@
if test "$CMAKE_CI_NIGHTLY" = "true"; then
source .gitlab/ci/iar-env.sh
source .gitlab/ci/ticlang-env.sh
source .gitlab/ci/emsdk-env.sh
fi
export CC=/usr/bin/clang-15
+19
View File
@@ -704,3 +704,22 @@ the next rules to make device + simulator configuration work:
- Use :command:`find_package` only for libraries installed with
:variable:`CMAKE_IOS_INSTALL_COMBINED` feature
.. _`Cross Compiling for Emscripten`:
Cross Compiling for Emscripten
------------------------------
.. versionadded:: 4.2
A toolchain file may configure cross-compiling for `Emscripten`_ by
setting the :variable:`CMAKE_SYSTEM_NAME` variable to ``Emscripten``.
For example, a toolchain file might contain:
.. code-block:: cmake
set(CMAKE_SYSTEM_NAME Emscripten)
set(CMAKE_C_COMPILER /path/to/emcc)
set(CMAKE_CXX_COMPILER /path/to/em++)
.. _`Emscripten`: https://emscripten.org/
+5
View File
@@ -0,0 +1,5 @@
emscripten-platform
-------------------
* CMake now supports :ref:`Cross Compiling for Emscripten` with simple
toolchain files.
+5
View File
@@ -219,6 +219,11 @@ else()
list(PREPEND _CMAKE_LINKER_NAMES "armlink")
endif()
if(EMSCRIPTEN)
list(PREPEND _CMAKE_AR_NAMES "emar")
list(PREPEND _CMAKE_RANLIB_NAMES "emranlib")
endif()
list(APPEND _CMAKE_TOOL_VARS AR RANLIB STRIP LINKER NM OBJDUMP OBJCOPY READELF DLLTOOL ADDR2LINE TAPI)
endif()
@@ -0,0 +1,3 @@
include(Platform/Emscripten-Clang)
__emscripten_clang(C)
@@ -0,0 +1,3 @@
include(Platform/Emscripten-Clang)
__emscripten_clang(CXX)
+17
View File
@@ -0,0 +1,17 @@
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file LICENSE.rst or https://cmake.org/licensing for details.
include_guard()
macro(__emscripten_clang lang)
set(CMAKE_SHARED_LIBRARY_SONAME_${lang}_FLAG "-Wl,-soname,")
set(CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS "-sSIDE_MODULE")
set(CMAKE_${lang}_USE_RESPONSE_FILE_FOR_LIBRARIES 1)
set(CMAKE_${lang}_USE_RESPONSE_FILE_FOR_OBJECTS 1)
set(CMAKE_${lang}_USE_RESPONSE_FILE_FOR_INCLUDES 1)
set(CMAKE_${lang}_COMPILE_OBJECT
"<CMAKE_${lang}_COMPILER> -c <SOURCE> <DEFINES> <INCLUDES> <FLAGS> -o <OBJECT> -fPIC")
set(CMAKE_${lang}_LINK_EXECUTABLE
"<CMAKE_${lang}_COMPILER> <FLAGS> <CMAKE_${lang}_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES> -sMAIN_MODULE")
endmacro()
@@ -0,0 +1,2 @@
set(EMSCRIPTEN 1)
set(UNIX 1)
+6
View File
@@ -0,0 +1,6 @@
set(CMAKE_SHARED_LIBRARY_LINK_C_WITH_RUNTIME_PATH ON)
set(CMAKE_SHARED_LIBRARY_SUFFIX ".wasm")
set(CMAKE_EXECUTABLE_SUFFIX ".js")
set(CMAKE_DL_LIBS "")
@@ -0,0 +1,4 @@
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file LICENSE.rst or https://cmake.org/licensing for details.
include(Platform/Linker/Emscripten-LLD-C)
@@ -0,0 +1,4 @@
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file LICENSE.rst or https://cmake.org/licensing for details.
include(Platform/Linker/Emscripten-LLD-CXX)
@@ -0,0 +1,6 @@
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file LICENSE.rst or https://cmake.org/licensing for details.
include(Platform/Linker/Emscripten-LLD)
__emscripten_linker_lld(C)
@@ -0,0 +1,6 @@
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file LICENSE.rst or https://cmake.org/licensing for details.
include(Platform/Linker/Emscripten-LLD)
__emscripten_linker_lld(CXX)
@@ -0,0 +1,11 @@
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file LICENSE.rst or https://cmake.org/licensing for details.
# This module is shared by multiple languages; use include blocker.
include_guard()
macro(__emscripten_linker_lld lang)
set(CMAKE_${lang}_LINK_LIBRARY_USING_WHOLE_ARCHIVE "-Wl,--whole-archive" "<LINK_ITEM>" "-Wl,--no-whole-archive")
set(CMAKE_${lang}_LINK_LIBRARY_USING_WHOLE_ARCHIVE_SUPPORTED TRUE)
set(CMAKE_${lang}_LINK_LIBRARY_WHOLE_ARCHIVE_ATTRIBUTES LIBRARY_TYPE=STATIC DEDUPLICATION=YES OVERRIDE=DEFAULT)
endmacro()
+8
View File
@@ -1386,6 +1386,14 @@ void cmCoreTryCompile::FindOutputFile(std::string const& targetName)
return;
}
if (cmHasLiteralSuffix(outputFileLocation, ".js")) {
std::string wasmOutputLocation = cmStrCat(
outputFileLocation.substr(0, outputFileLocation.length() - 3), ".wasm");
if (cmSystemTools::FileExists(wasmOutputLocation)) {
outputFileLocation = wasmOutputLocation;
}
}
this->OutputFile = cmSystemTools::CollapseFullPath(outputFileLocation);
}
+4
View File
@@ -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()
+3
View File
@@ -0,0 +1,3 @@
cmake_minimum_required(VERSION 4.0)
project(${RunCMake_TEST} NONE)
include(${RunCMake_TEST}.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()
+9
View File
@@ -0,0 +1,9 @@
#if !defined(STATIC_BASE)
# if defined(_WIN32)
__declspec(dllexport)
# endif
#endif
void base(void)
{
}
+6
View File
@@ -0,0 +1,6 @@
void circular2(void);
void circular1(void)
{
circular2();
}
+7
View File
@@ -0,0 +1,7 @@
void circular1(void);
void circular2(void)
{
circular1();
}
@@ -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 "$<LINK_LIBRARY:WHOLE_ARCHIVE,base>")
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 $<LINK_LIBRARY:WHOLE_ARCHIVE,circular1>)
@@ -0,0 +1,2 @@
enable_language(C)
add_executable(exec-c module.c)
@@ -0,0 +1,2 @@
enable_language(CXX)
add_executable(exec-cxx module.cxx)
@@ -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)
+15
View File
@@ -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();
}
+4
View File
@@ -0,0 +1,4 @@
int emscripten_libfun()
{
return 42;
}
+18
View File
@@ -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;
}
@@ -0,0 +1,9 @@
void circular1(void);
int main(void)
{
circular1();
return 0;
}
+15
View File
@@ -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;
}
+7
View File
@@ -0,0 +1,7 @@
#include "module.h"
int i;
int main()
{
i = INTERNAL;
return i;
}
+12
View File
@@ -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__ */
+8
View File
@@ -0,0 +1,8 @@
#if defined(_WIN32)
__declspec(dllexport)
#endif
void unref(void)
{
}