mirror of
https://github.com/Kitware/CMake.git
synced 2026-11-06 05:16:58 +00:00
Merge topic 'embt-compiler'
e739170f15EMBTClang: Add support for the Embarcadero bcc64x compilerf29cfe2bf9Borland: Do not identify Clang-based Embarcadero compilers641d5321a7Tests/Plugin: Fix symbol lookup with 64-bit Embarcadero compilerscdfd0615b8Tests/RunCMake/target_link_libraries-LINK_LIBRARY: Fix MinGW lld checkab4d0130edTests/BundleUtilities: Fix test with Clang-based MinGW toolchains Acked-by: Kitware Robot <kwrobot@kitware.com> Merge-request: !11356
This commit is contained in:
commit
35de7eca76
80 files changed
+1191
-29
No files matched your search
@@ -113,6 +113,17 @@ foreach(lang IN ITEMS C CXX)
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# CMake's own sources are UTF-8. The Embarcadero (EMBTClang) bcc64x compiler
|
||||
# defaults the narrow execution code page to the host ANSI code page, unlike
|
||||
# Clang and MSVC which preserve UTF-8, so non-ASCII narrow string literals such
|
||||
# as the localized regexes in Source/CTest/cmCTestBuildHandler.cxx are corrupted.
|
||||
# Select UTF-8 (code page 65001) when building CMake itself with EMBTClang.
|
||||
foreach(lang IN ITEMS C CXX)
|
||||
if(CMAKE_${lang}_COMPILER_ID STREQUAL "EMBTClang")
|
||||
string(APPEND CMAKE_${lang}_FLAGS " -fborland-exec-code-page=65001")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# use the ansi CXX compile flag for building cmake
|
||||
if (CMAKE_ANSI_CXXFLAGS)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CMAKE_ANSI_CXXFLAGS}")
|
||||
|
||||
@@ -254,6 +254,7 @@ Properties on Targets
|
||||
/prop_tgt/DOTNET_SDK
|
||||
/prop_tgt/DOTNET_TARGET_FRAMEWORK
|
||||
/prop_tgt/DOTNET_TARGET_FRAMEWORK_VERSION
|
||||
/prop_tgt/EMBT_RUNTIME_LIBRARY
|
||||
/prop_tgt/EchoString
|
||||
/prop_tgt/ENABLE_EXPORTS
|
||||
/prop_tgt/EXCLUDE_FROM_ALL
|
||||
|
||||
@@ -486,6 +486,7 @@ Variables that Control the Build
|
||||
/variable/CMAKE_DEPENDS_USE_COMPILER
|
||||
/variable/CMAKE_DISABLE_PRECOMPILE_HEADERS
|
||||
/variable/CMAKE_DLL_NAME_WITH_SOVERSION
|
||||
/variable/CMAKE_EMBT_RUNTIME_LIBRARY
|
||||
/variable/CMAKE_EXECUTABLE_ENABLE_EXPORTS
|
||||
/variable/CMAKE_EXE_LINKER_FLAGS
|
||||
/variable/CMAKE_EXE_LINKER_FLAGS_CONFIG
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
EMBT_RUNTIME_LIBRARY
|
||||
--------------------
|
||||
|
||||
.. versionadded:: 4.6
|
||||
|
||||
Select the runtime library used by the Embarcadero (``bcc64x``) toolchain.
|
||||
|
||||
The allowed values are:
|
||||
|
||||
.. include:: include/EMBT_RUNTIME_LIBRARY-VALUES.rst
|
||||
|
||||
Use :manual:`generator expressions <cmake-generator-expressions(7)>` to
|
||||
support per-configuration specification.
|
||||
|
||||
For example, the code:
|
||||
|
||||
.. code-block:: cmake
|
||||
|
||||
add_library(mylib SHARED mylib.cxx)
|
||||
set_property(TARGET mylib PROPERTY EMBT_RUNTIME_LIBRARY "Dynamic")
|
||||
|
||||
selects for the target ``mylib`` the dynamically-linked runtime library.
|
||||
|
||||
This property is initialized by the :variable:`CMAKE_EMBT_RUNTIME_LIBRARY`
|
||||
variable if it is set when a target is created. It has no effect on
|
||||
toolchains other than ``EMBTClang``.
|
||||
@@ -0,0 +1,12 @@
|
||||
``Static``
|
||||
Compile without additional flags to use the statically-linked runtime
|
||||
library.
|
||||
``Dynamic``
|
||||
Compile with ``-tR`` and define ``USEPACKAGES`` to use the
|
||||
dynamically-linked (shared) runtime library.
|
||||
|
||||
The value is ignored on non-Embarcadero compilers but an unsupported value
|
||||
will be rejected as an error when using the ``bcc64x`` toolchain.
|
||||
|
||||
If this property is not set then no runtime library selection flag is added
|
||||
explicitly by CMake, which is equivalent to ``Static``.
|
||||
@@ -0,0 +1,9 @@
|
||||
embtclang-toolchain
|
||||
-------------------
|
||||
|
||||
* Embarcadero Clang-based compilers are now supported with
|
||||
:variable:`compiler id <CMAKE_<LANG>_COMPILER_ID>` ``EMBTClang``.
|
||||
C++ modules are not yet supported with this compiler.
|
||||
|
||||
* The runtime library for the Embarcadero ``bcc64x`` toolchain may now be
|
||||
selected with the :prop_tgt:`EMBT_RUNTIME_LIBRARY` target property.
|
||||
@@ -0,0 +1,15 @@
|
||||
CMAKE_EMBT_RUNTIME_LIBRARY
|
||||
--------------------------
|
||||
|
||||
.. versionadded:: 4.6
|
||||
|
||||
Select the runtime library used by the Embarcadero (``bcc64x``) toolchain.
|
||||
This variable is used to initialize the :prop_tgt:`EMBT_RUNTIME_LIBRARY`
|
||||
property on all targets as they are created.
|
||||
|
||||
The allowed values are:
|
||||
|
||||
.. include:: ../prop_tgt/include/EMBT_RUNTIME_LIBRARY-VALUES.rst
|
||||
|
||||
If this variable is not set then the :prop_tgt:`EMBT_RUNTIME_LIBRARY` target
|
||||
property is not set automatically.
|
||||
@@ -22,6 +22,7 @@ Value Name
|
||||
``CrayClang`` Cray Clang-based Compiler
|
||||
``Diab`` `Wind River Systems Diab Compiler`_
|
||||
``DPClang`` `Open-source DPC++ Compiler`_
|
||||
``EMBTClang`` `Embarcadero`_ Clang-based Compiler
|
||||
``Embarcadero``, ``Borland`` `Embarcadero`_
|
||||
``Flang`` `Classic Flang Fortran Compiler`_
|
||||
``LLVMFlang`` `LLVM Flang Fortran Compiler`_
|
||||
|
||||
@@ -47,6 +47,7 @@ function(compiler_id_detection outvar lang)
|
||||
IntelLLVM
|
||||
DPClang
|
||||
PathScale
|
||||
EMBTClang
|
||||
Embarcadero
|
||||
Borland
|
||||
Watcom
|
||||
|
||||
@@ -43,9 +43,9 @@ if(NOT CMAKE_ASM${ASM_DIALECT}_COMPILER)
|
||||
else()
|
||||
# List all default C and CXX compilers
|
||||
set(CMAKE_ASM_COMPILER_LIST
|
||||
${_CMAKE_TOOLCHAIN_PREFIX}cc ${_CMAKE_TOOLCHAIN_PREFIX}gcc xlc
|
||||
${_CMAKE_TOOLCHAIN_PREFIX}cc ${_CMAKE_TOOLCHAIN_PREFIX}gcc bcc64x xlc
|
||||
${_CMAKE_ASM_MAYBE_CL}
|
||||
CC ${_CMAKE_TOOLCHAIN_PREFIX}c++ ${_CMAKE_TOOLCHAIN_PREFIX}g++ xlC)
|
||||
CC ${_CMAKE_TOOLCHAIN_PREFIX}c++ ${_CMAKE_TOOLCHAIN_PREFIX}g++ bcc64x xlC)
|
||||
unset(_CMAKE_ASM_MAYBE_CL)
|
||||
unset(_CMAKE_ASM_REGEX_CL)
|
||||
unset(_CMAKE_ASM_REGEX_MSVC)
|
||||
|
||||
@@ -58,7 +58,7 @@ else()
|
||||
|
||||
# finally list compilers to try
|
||||
if(NOT CMAKE_C_COMPILER_INIT)
|
||||
set(CMAKE_C_COMPILER_LIST ${_CMAKE_TOOLCHAIN_PREFIX}cc ${_CMAKE_TOOLCHAIN_PREFIX}gcc cl bcc xlc icx clang dpclang)
|
||||
set(CMAKE_C_COMPILER_LIST ${_CMAKE_TOOLCHAIN_PREFIX}cc ${_CMAKE_TOOLCHAIN_PREFIX}gcc cl bcc64x bcc xlc icx clang dpclang)
|
||||
endif()
|
||||
|
||||
_cmake_find_compiler(C)
|
||||
|
||||
@@ -57,7 +57,7 @@ else()
|
||||
|
||||
# finally list compilers to try
|
||||
if(NOT CMAKE_CXX_COMPILER_INIT)
|
||||
set(CMAKE_CXX_COMPILER_LIST CC ${_CMAKE_TOOLCHAIN_PREFIX}c++ ${_CMAKE_TOOLCHAIN_PREFIX}g++ aCC cl bcc xlC)
|
||||
set(CMAKE_CXX_COMPILER_LIST CC ${_CMAKE_TOOLCHAIN_PREFIX}c++ ${_CMAKE_TOOLCHAIN_PREFIX}g++ aCC cl bcc64x bcc xlC)
|
||||
if(NOT CMAKE_HOST_WIN32)
|
||||
# FIXME(#24314): Add support for the GNU-like icpx compiler driver
|
||||
# on Windows, first introduced by Intel oneAPI 2023.0.
|
||||
|
||||
@@ -361,6 +361,7 @@ function(CMAKE_DETERMINE_COMPILER_ID lang flagvar src)
|
||||
elseif("x${CMAKE_${lang}_COMPILER_ID}" STREQUAL "xGNU"
|
||||
OR "x${CMAKE_${lang}_COMPILER_ID}" STREQUAL "xAdaptiveCpp"
|
||||
OR "x${CMAKE_${lang}_COMPILER_ID}" STREQUAL "xAppleClang"
|
||||
OR "x${CMAKE_${lang}_COMPILER_ID}" STREQUAL "xEMBTClang"
|
||||
OR "x${CMAKE_${lang}_COMPILER_ID}" STREQUAL "xFujitsuClang"
|
||||
OR "x${CMAKE_${lang}_COMPILER_ID}" STREQUAL "xIBMClang"
|
||||
OR "x${CMAKE_${lang}_COMPILER_ID}" STREQUAL "xTIClang")
|
||||
@@ -375,7 +376,7 @@ function(CMAKE_DETERMINE_COMPILER_ID lang flagvar src)
|
||||
# for C++ and the GNU-frontend variant.
|
||||
set(CMAKE_${lang}_COMPILER_CLANG_RESOURCE_DIR "")
|
||||
if ("x${lang}" STREQUAL "xCXX" AND
|
||||
CMAKE_${lang}_COMPILER_ID MATCHES "^(Clang|DPClang)$" AND
|
||||
CMAKE_${lang}_COMPILER_ID MATCHES "^(Clang|DPClang|EMBTClang)$" AND
|
||||
"x${CMAKE_${lang}_COMPILER_FRONTEND_VARIANT}" STREQUAL "xGNU")
|
||||
execute_process(
|
||||
COMMAND "${CMAKE_${lang}_COMPILER}"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
set(_compiler_id_pp_test "defined(__BORLANDC__)")
|
||||
set(_compiler_id_pp_test "defined(__BORLANDC__) && !defined(__clang__)")
|
||||
|
||||
set(_compiler_id_version_compute "
|
||||
/* __BORLANDC__ = 0xVRR */
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
include(Compiler/Clang-ASM)
|
||||
include(Compiler/EMBTClang)
|
||||
|
||||
string(APPEND CMAKE_ASM_FLAGS_INIT " -q")
|
||||
@@ -0,0 +1 @@
|
||||
include(Compiler/Clang-C-FeatureTests)
|
||||
@@ -0,0 +1,4 @@
|
||||
include(Compiler/Clang-C)
|
||||
include(Compiler/EMBTClang)
|
||||
|
||||
string(APPEND CMAKE_C_FLAGS_INIT " -q")
|
||||
@@ -0,0 +1 @@
|
||||
include(Compiler/Clang-CXX-FeatureTests)
|
||||
@@ -0,0 +1,19 @@
|
||||
# Keep a scanning rule set before enable_language() (CMake's own tests set one
|
||||
# to fake scanning); drop only the one Compiler/Clang-CXX adds.
|
||||
if(DEFINED CMAKE_CXX_SCANDEP_SOURCE)
|
||||
set(__embt_scandep_source "${CMAKE_CXX_SCANDEP_SOURCE}")
|
||||
endif()
|
||||
|
||||
include(Compiler/Clang-CXX)
|
||||
include(Compiler/EMBTClang)
|
||||
|
||||
# The toolchain's clang-scan-deps does not apply the bcc64x driver's target,
|
||||
# standard, and include paths, so C++ module scanning is not supported.
|
||||
if(DEFINED __embt_scandep_source)
|
||||
set(CMAKE_CXX_SCANDEP_SOURCE "${__embt_scandep_source}")
|
||||
unset(__embt_scandep_source)
|
||||
else()
|
||||
unset(CMAKE_CXX_SCANDEP_SOURCE)
|
||||
endif()
|
||||
|
||||
string(APPEND CMAKE_CXX_FLAGS_INIT " -q")
|
||||
@@ -0,0 +1,4 @@
|
||||
|
||||
set(_compiler_id_pp_test "defined(__CODEGEARC__) && defined(__clang__) && defined(__MINGW64__)")
|
||||
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/Clang-DetermineCompilerInternal.cmake")
|
||||
@@ -0,0 +1,69 @@
|
||||
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||
# file LICENSE.rst or https://cmake.org/licensing for details.
|
||||
|
||||
|
||||
# Runs immediately after CMakeFindBinUtils during compiler determination.
|
||||
# CMakeFindBinUtils does not match EMBTClang in its Clang/IntelLLVM/LLVMFlang
|
||||
# regex, so it falls through to the generic branch and finds whatever "ar"
|
||||
# happens to be on PATH (often a stray ar.exe from MSYS, MinGW, etc.).
|
||||
# Override CMAKE_AR/CMAKE_RANLIB with the llvm-ar/llvm-ranlib that ship
|
||||
# alongside bcc64x in the Embarcadero installation.
|
||||
|
||||
if(NOT DEFINED _CMAKE_PROCESSING_LANGUAGE OR _CMAKE_PROCESSING_LANGUAGE STREQUAL "")
|
||||
message(FATAL_ERROR "Internal error: _CMAKE_PROCESSING_LANGUAGE is not set")
|
||||
endif()
|
||||
|
||||
# The compiler path is fully resolved by this point in the determination
|
||||
# phase, so get_filename_component yields a real directory.
|
||||
get_filename_component(__embt_hint
|
||||
"${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER}" REALPATH)
|
||||
get_filename_component(__embt_hint "${__embt_hint}" DIRECTORY)
|
||||
|
||||
find_program(__embt_ar NAMES llvm-ar
|
||||
HINTS "${__embt_hint}"
|
||||
NO_CMAKE_PATH NO_CMAKE_ENVIRONMENT_PATH NO_DEFAULT_PATH)
|
||||
if(__embt_ar)
|
||||
set(CMAKE_AR "${__embt_ar}" CACHE FILEPATH "Archiver" FORCE)
|
||||
set(CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_AR "${__embt_ar}"
|
||||
CACHE FILEPATH "LLVM archiver" FORCE)
|
||||
mark_as_advanced(CMAKE_AR
|
||||
CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_AR)
|
||||
endif()
|
||||
unset(__embt_ar CACHE)
|
||||
|
||||
find_program(__embt_ranlib NAMES llvm-ranlib
|
||||
HINTS "${__embt_hint}"
|
||||
NO_CMAKE_PATH NO_CMAKE_ENVIRONMENT_PATH NO_DEFAULT_PATH)
|
||||
if(__embt_ranlib)
|
||||
set(CMAKE_RANLIB "${__embt_ranlib}" CACHE FILEPATH "Archive index tool" FORCE)
|
||||
set(CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_RANLIB "${__embt_ranlib}"
|
||||
CACHE FILEPATH "Generate index for LLVM archive" FORCE)
|
||||
mark_as_advanced(CMAKE_RANLIB
|
||||
CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_RANLIB)
|
||||
endif()
|
||||
unset(__embt_ranlib CACHE)
|
||||
|
||||
# Pin the linker and the remaining LLVM binutils that ship beside bcc64x, for the
|
||||
# same reason as CMAKE_AR above: CMakeFindBinUtils leaves them unset (or, for a
|
||||
# bare name, resolvable from a stray PATH entry). Linking itself goes through
|
||||
# the bcc64x driver, so CMAKE_LINKER is informational (CheckLinkerFlag and the
|
||||
# like consume it).
|
||||
foreach(__embt_tool "LINKER=ld.lld" "NM=llvm-nm" "OBJDUMP=llvm-objdump"
|
||||
"STRIP=llvm-strip" "DLLTOOL=llvm-dlltool")
|
||||
string(REPLACE "=" ";" __embt_tool "${__embt_tool}")
|
||||
list(GET __embt_tool 0 __embt_var)
|
||||
list(GET __embt_tool 1 __embt_prog)
|
||||
find_program(__embt_found NAMES ${__embt_prog}
|
||||
HINTS "${__embt_hint}"
|
||||
NO_CMAKE_PATH NO_CMAKE_ENVIRONMENT_PATH NO_DEFAULT_PATH)
|
||||
if(__embt_found)
|
||||
set(CMAKE_${__embt_var} "${__embt_found}" CACHE FILEPATH "${__embt_prog}" FORCE)
|
||||
mark_as_advanced(CMAKE_${__embt_var})
|
||||
endif()
|
||||
unset(__embt_found CACHE)
|
||||
endforeach()
|
||||
unset(__embt_var)
|
||||
unset(__embt_prog)
|
||||
unset(__embt_tool)
|
||||
|
||||
unset(__embt_hint)
|
||||
@@ -0,0 +1,37 @@
|
||||
# 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.
|
||||
if(__COMPILER_EMBTCLANG)
|
||||
return()
|
||||
endif()
|
||||
set(__COMPILER_EMBTCLANG 1)
|
||||
|
||||
if("x${CMAKE_C_COMPILER_ID}" STREQUAL "xEMBTClang")
|
||||
set(__embt_driver "${CMAKE_C_COMPILER}")
|
||||
elseif("x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xEMBTClang")
|
||||
set(__embt_driver "${CMAKE_CXX_COMPILER}")
|
||||
elseif("x${CMAKE_ASM_COMPILER_ID}" STREQUAL "xEMBTClang")
|
||||
set(__embt_driver "${CMAKE_ASM_COMPILER}")
|
||||
endif()
|
||||
if(__embt_driver)
|
||||
get_filename_component(EMBT_DRIVER_NAME "${__embt_driver}" NAME_WE)
|
||||
endif()
|
||||
|
||||
if(WIN32 AND EMBT_DRIVER_NAME AND NOT CMAKE_RC_COMPILER_INIT AND NOT CMAKE_GENERATOR_RC)
|
||||
# Resolve the resource compiler that ships beside the driver to an absolute
|
||||
# path, not a bare name that would be taken from PATH at build time.
|
||||
get_filename_component(__embt_bindir "${__embt_driver}" DIRECTORY)
|
||||
find_program(__embt_rc NAMES ${EMBT_DRIVER_NAME}-windres
|
||||
HINTS "${__embt_bindir}"
|
||||
NO_CMAKE_PATH NO_CMAKE_ENVIRONMENT_PATH NO_DEFAULT_PATH)
|
||||
if(__embt_rc)
|
||||
set(CMAKE_RC_COMPILER_INIT "${__embt_rc}")
|
||||
else()
|
||||
set(CMAKE_RC_COMPILER_INIT ${EMBT_DRIVER_NAME}-windres)
|
||||
endif()
|
||||
unset(__embt_rc CACHE)
|
||||
unset(__embt_bindir)
|
||||
endif()
|
||||
unset(__embt_driver)
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
set(_compiler_id_pp_test "defined(__BORLANDC__) && defined(__CODEGEARC_VERSION__)")
|
||||
set(_compiler_id_pp_test "defined(__BORLANDC__) && defined(__CODEGEARC_VERSION__) && !defined(__MINGW64__)")
|
||||
|
||||
set(_compiler_id_version_compute "
|
||||
# define @PREFIX@COMPILER_VERSION_MAJOR @MACRO_HEX@(__CODEGEARC_VERSION__>>24 & 0x00FF)
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
include(Platform/Windows-EMBTClang)
|
||||
__windows_compiler_embtclang(ASM)
|
||||
@@ -0,0 +1,2 @@
|
||||
include(Platform/Windows-EMBTClang)
|
||||
__windows_compiler_embtclang(C)
|
||||
@@ -0,0 +1,2 @@
|
||||
include(Platform/Windows-EMBTClang)
|
||||
__windows_compiler_embtclang(CXX)
|
||||
@@ -0,0 +1,140 @@
|
||||
# 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.
|
||||
if(__WINDOWS_EMBTCLANG)
|
||||
return()
|
||||
endif()
|
||||
set(__WINDOWS_EMBTCLANG 1)
|
||||
|
||||
include(Platform/Windows-Clang)
|
||||
|
||||
# CMAKE_EMBT_RUNTIME_LIBRARY is forwarded into try_compile() by cmCoreTryCompile,
|
||||
# so probes compile with the right runtime. The derived RTL link directory and
|
||||
# RAD Studio include base are not, so forward them too: a probe for a project
|
||||
# that adds -tJ to link the RAD Studio RTL, or that includes the RAD headers,
|
||||
# then resolves rtl.lib/rtl.bpi/rtle.lib and <System.hpp> from these paths.
|
||||
list(APPEND CMAKE_TRY_COMPILE_PLATFORM_VARIABLES
|
||||
CMAKE_EMBT_RTL_LIBRARY_DIR CMAKE_EMBT_INCLUDE_DIR)
|
||||
|
||||
macro(__windows_compiler_embtclang lang)
|
||||
__windows_compiler_clang(${lang})
|
||||
|
||||
# The GNU-driver Clang path gives Debug builds only "-g"; the RAD Studio
|
||||
# headers select debug runtime behavior on _DEBUG, which "-g" does not
|
||||
# define. Add it so a Debug build matches the debug runtime.
|
||||
string(APPEND CMAKE_${lang}_FLAGS_DEBUG_INIT " -D_DEBUG")
|
||||
|
||||
# Drive the WIN32_EXECUTABLE property through the bcc64x subsystem switches
|
||||
# instead of the inherited MSVC-style linker options. These are link rules.
|
||||
# At compile -tC only defines __CONSOLE__, which the RAD Studio headers
|
||||
# branch on, and -tW defines nothing; but -tC is recorded in precompiled
|
||||
# headers, so the compile side defines the macro instead. Keep the two
|
||||
# separate: a CREATE_*_EXE link rule may carry link-only syntax (LINKER:)
|
||||
# that is meaningless on a compile command.
|
||||
set(CMAKE_${lang}_CREATE_WIN32_EXE "-tW")
|
||||
set(CMAKE_${lang}_CREATE_CONSOLE_EXE "-tC")
|
||||
set(CMAKE_${lang}_COMPILE_OPTIONS_EMBT_GUI "")
|
||||
set(CMAKE_${lang}_COMPILE_OPTIONS_EMBT_CONSOLE -D__CONSOLE__=1)
|
||||
|
||||
# The bcc64x toolchain uses MSVC-style naming (no "lib" prefix, ".lib"
|
||||
# import/static, ".dll" shared), not the GNU/MinGW names inherited from
|
||||
# Windows-Clang's non-MSVC path.
|
||||
set(CMAKE_STATIC_LIBRARY_PREFIX "")
|
||||
set(CMAKE_STATIC_LIBRARY_SUFFIX ".lib")
|
||||
set(CMAKE_SHARED_LIBRARY_PREFIX "")
|
||||
set(CMAKE_SHARED_LIBRARY_SUFFIX ".dll")
|
||||
set(CMAKE_SHARED_MODULE_PREFIX "")
|
||||
set(CMAKE_SHARED_MODULE_SUFFIX ".dll")
|
||||
set(CMAKE_IMPORT_LIBRARY_PREFIX "")
|
||||
set(CMAKE_IMPORT_LIBRARY_SUFFIX ".lib")
|
||||
# Find RAD Studio-named libraries first, then the MinGW names the toolchain's
|
||||
# own libraries use: static before import, as the driver links by default.
|
||||
set(CMAKE_FIND_LIBRARY_PREFIXES "" "lib")
|
||||
set(CMAKE_FIND_LIBRARY_SUFFIXES ".lib" ".a" ".dll.a")
|
||||
|
||||
# Disable the GNU link-type switches (-Bstatic/-Bdynamic) inherited above.
|
||||
# Static and import libraries share the ".lib" name, so they cannot select
|
||||
# between them, and the driver sets the link type itself to match the
|
||||
# runtime library, which a switch left at the end of the line would undo.
|
||||
foreach(__embt_type IN ITEMS EXE SHARED_LIBRARY SHARED_MODULE)
|
||||
set(CMAKE_${__embt_type}_LINK_STATIC_${lang}_FLAGS "")
|
||||
set(CMAKE_${__embt_type}_LINK_DYNAMIC_${lang}_FLAGS "")
|
||||
endforeach()
|
||||
unset(__embt_type)
|
||||
|
||||
set(CMAKE_${lang}_OUTPUT_EXTENSION ".o")
|
||||
# Append (foo.c.o), do not replace (foo.o): replacing the source extension
|
||||
# collides when a target has two sources sharing a stem (e.g. test.c +
|
||||
# test.cxx), producing "multiple rules generate <stem>.o"
|
||||
set(CMAKE_${lang}_OUTPUT_EXTENSION_REPLACE 0)
|
||||
|
||||
# The default archive command (qc) does not write a symbol index. The
|
||||
# ARCHIVE_FINISH step runs ranlib to add one, but llvm-ranlib may not be
|
||||
# present. Use 's' so llvm-ar embeds the index in the same pass; lld
|
||||
# requires the index to resolve symbols from a static archive.
|
||||
set(CMAKE_${lang}_ARCHIVE_CREATE "<CMAKE_AR> -qcDs <TARGET> <LINK_FLAGS> <OBJECTS>")
|
||||
set(CMAKE_${lang}_ARCHIVE_APPEND "<CMAKE_AR> -qDs <TARGET> <LINK_FLAGS> <OBJECTS>")
|
||||
|
||||
# The EMBT_RUNTIME_LIBRARY property selects the runtime library the same way as
|
||||
# MSVC_RUNTIME_LIBRARY / WATCOM_RUNTIME_LIBRARY: a default activates it and the
|
||||
# property overrides. Static relies on the driver's -tC/-tW/-tD default, which
|
||||
# links libc++ statically; Dynamic adds -tR for the shared libc++ and defines
|
||||
# USEPACKAGES so the RAD Studio headers import RTL symbols.
|
||||
set(CMAKE_EMBT_RUNTIME_LIBRARY_DEFAULT "Static")
|
||||
set(CMAKE_${lang}_COMPILE_OPTIONS_EMBT_RUNTIME_LIBRARY_Static "")
|
||||
set(CMAKE_${lang}_COMPILE_OPTIONS_EMBT_RUNTIME_LIBRARY_Dynamic -tR -DUSEPACKAGES)
|
||||
|
||||
# A shared or module library is a plain DLL: -tD at link. At compile -tD
|
||||
# only defines __DLL__, but it is recorded in precompiled headers, which
|
||||
# then cannot be reused by other target kinds; define the macro instead.
|
||||
set(CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS "-shared -tD")
|
||||
set(CMAKE_SHARED_MODULE_CREATE_${lang}_FLAGS "-shared -tD")
|
||||
set(CMAKE_${lang}_COMPILE_OPTIONS_EMBT_DLL -D__DLL__=1)
|
||||
|
||||
# When a project adds -tJ to link against the RAD Studio RTL, the driver pulls
|
||||
# the RTL import libraries (rtl.lib/rtl.bpi and rtle.lib) and startup object
|
||||
# from the link search path. They sit next to the compiler at
|
||||
# <compiler>/../lib/win64x/<config>. Put that directory on the standard link
|
||||
# path so a user-added -tJ resolves them. Override with
|
||||
# CMAKE_EMBT_RTL_LIBRARY_DIR.
|
||||
if(NOT DEFINED CMAKE_EMBT_RTL_LIBRARY_DIR)
|
||||
get_filename_component(__embt_bindir "${CMAKE_${lang}_COMPILER}" DIRECTORY)
|
||||
# Use the debug RTL only for a Debug build -- the config that also defines
|
||||
# _DEBUG, matching the debug runtime; use release otherwise, including when
|
||||
# no build type is set. Keyed on CMAKE_BUILD_TYPE, so this assumes a
|
||||
# single-config generator; multi-config would need a $<CONFIG:Debug> genex.
|
||||
if(CMAKE_BUILD_TYPE MATCHES "^[Dd][Ee][Bb][Uu][Gg]$")
|
||||
set(__embt_rtl_config debug)
|
||||
else()
|
||||
set(__embt_rtl_config release)
|
||||
endif()
|
||||
get_filename_component(CMAKE_EMBT_RTL_LIBRARY_DIR
|
||||
"${__embt_bindir}/../lib/win64x/${__embt_rtl_config}" ABSOLUTE)
|
||||
unset(__embt_bindir)
|
||||
unset(__embt_rtl_config)
|
||||
endif()
|
||||
if(EXISTS "${CMAKE_EMBT_RTL_LIBRARY_DIR}")
|
||||
list(APPEND CMAKE_${lang}_STANDARD_LINK_DIRECTORIES
|
||||
"${CMAKE_EMBT_RTL_LIBRARY_DIR}")
|
||||
endif()
|
||||
|
||||
# The bcc64x driver does not put the RAD Studio C++ headers on the default
|
||||
# include path (the IDE adds them). Do the same so <System.hpp> and the
|
||||
# framework headers resolve. They live at <compiler>/../include/windows/<set>.
|
||||
# Override the base with CMAKE_EMBT_INCLUDE_DIR.
|
||||
if(NOT DEFINED CMAKE_EMBT_INCLUDE_DIR)
|
||||
get_filename_component(__embt_bindir "${CMAKE_${lang}_COMPILER}" DIRECTORY)
|
||||
get_filename_component(CMAKE_EMBT_INCLUDE_DIR
|
||||
"${__embt_bindir}/../include/windows" ABSOLUTE)
|
||||
unset(__embt_bindir)
|
||||
endif()
|
||||
foreach(__embt_inc IN ITEMS sdk rtl vcl fmx)
|
||||
if(EXISTS "${CMAKE_EMBT_INCLUDE_DIR}/${__embt_inc}")
|
||||
list(APPEND CMAKE_${lang}_STANDARD_INCLUDE_DIRECTORIES
|
||||
"${CMAKE_EMBT_INCLUDE_DIR}/${__embt_inc}")
|
||||
endif()
|
||||
endforeach()
|
||||
unset(__embt_inc)
|
||||
endmacro()
|
||||
@@ -1150,6 +1150,7 @@ cm::optional<cmTryCompileResult> cmCoreTryCompile::TryCompileCode(
|
||||
vars.insert("CMAKE_SYCL_DEVICE_TARGETS");
|
||||
vars.emplace("CMAKE_MSVC_RUNTIME_LIBRARY"_s);
|
||||
vars.emplace("CMAKE_WATCOM_RUNTIME_LIBRARY"_s);
|
||||
vars.emplace("CMAKE_EMBT_RUNTIME_LIBRARY"_s);
|
||||
vars.emplace("CMAKE_MSVC_DEBUG_INFORMATION_FORMAT"_s);
|
||||
vars.emplace("CMAKE_MSVC_RUNTIME_CHECKS"_s);
|
||||
vars.emplace("CMAKE_CXX_COMPILER_CLANG_SCAN_DEPS"_s);
|
||||
|
||||
@@ -2318,6 +2318,7 @@ void cmLocalGenerator::AddLanguageFlags(std::string& flags,
|
||||
(compilerId == "MSVC" || compilerSimulateId == "MSVC");
|
||||
bool const compilerTargetsWatcomABI =
|
||||
(compilerId == "OpenWatcom" || compilerSimulateId == "OpenWatcom");
|
||||
bool const compilerTargetsEmbtABI = (compilerId == "EMBTClang");
|
||||
|
||||
if (lang == "Swift") {
|
||||
target->AddSwiftTargetFlags(flags);
|
||||
@@ -2419,6 +2420,62 @@ void cmLocalGenerator::AddLanguageFlags(std::string& flags,
|
||||
}
|
||||
}
|
||||
|
||||
// Add Embarcadero (bcc64x) runtime library flags. This is activated by the
|
||||
// presence of a default selection whether or not it is overridden by a
|
||||
// property, the same way as MSVC and Watcom above.
|
||||
cmValue embtRuntimeLibraryDefault =
|
||||
this->Makefile->GetDefinition("CMAKE_EMBT_RUNTIME_LIBRARY_DEFAULT");
|
||||
if (cmNonempty(embtRuntimeLibraryDefault)) {
|
||||
cmValue embtRuntimeLibraryValue =
|
||||
target->GetProperty("EMBT_RUNTIME_LIBRARY");
|
||||
if (!embtRuntimeLibraryValue) {
|
||||
embtRuntimeLibraryValue = embtRuntimeLibraryDefault;
|
||||
}
|
||||
std::string const embtRuntimeLibrary = cmGeneratorExpression::Evaluate(
|
||||
*embtRuntimeLibraryValue, this, config, target);
|
||||
if (!embtRuntimeLibrary.empty()) {
|
||||
if (cmValue embtRuntimeLibraryOptions = this->Makefile->GetDefinition(
|
||||
cmStrCat("CMAKE_", lang, "_COMPILE_OPTIONS_EMBT_RUNTIME_LIBRARY_",
|
||||
embtRuntimeLibrary))) {
|
||||
this->AppendCompileOptions(flags, *embtRuntimeLibraryOptions);
|
||||
} else if (compilerTargetsEmbtABI &&
|
||||
!cmSystemTools::GetErrorOccurredFlag()) {
|
||||
// The compiler is EMBTClang so it needs a known runtime library.
|
||||
this->IssueMessage(
|
||||
MessageType::FATAL_ERROR,
|
||||
cmStrCat("EMBT_RUNTIME_LIBRARY value '", embtRuntimeLibrary,
|
||||
"' not known for this ", lang, " compiler."));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add Embarcadero (bcc64x) target-kind flags for shared and module libraries
|
||||
// and the console/GUI subsystem, active only for the EMBTClang toolchain.
|
||||
if (compilerId == "EMBTClang") {
|
||||
// A shared or module library is a plain DLL: it is compiled with __DLL__
|
||||
// for the RAD Studio headers (the platform module links it with -tD).
|
||||
if (target->GetType() == cm::TargetType::SHARED_LIBRARY ||
|
||||
target->GetType() == cm::TargetType::MODULE_LIBRARY) {
|
||||
if (cmValue embtOptions = this->Makefile->GetDefinition(
|
||||
cmStrCat("CMAKE_", lang, "_COMPILE_OPTIONS_EMBT_DLL"))) {
|
||||
this->AppendCompileOptions(flags, *embtOptions);
|
||||
}
|
||||
}
|
||||
// -tC/-tW set the subsystem at link, and a console executable is also
|
||||
// compiled with __CONSOLE__, which the RAD Studio headers branch on.
|
||||
// WIN32_EXECUTABLE drives the switch only at link, so apply the matching
|
||||
// compile options to an executable too, via dedicated compile-option
|
||||
// variables (not the CREATE_{WIN32,CONSOLE}_EXE link rules, which may
|
||||
// carry link-only syntax).
|
||||
if (target->GetType() == cm::TargetType::EXECUTABLE) {
|
||||
if (cmValue subsystem = this->Makefile->GetDefinition(
|
||||
cmStrCat("CMAKE_", lang, "_COMPILE_OPTIONS_EMBT_",
|
||||
target->IsWin32Executable(config) ? "GUI" : "CONSOLE"))) {
|
||||
this->AppendCompileOptions(flags, *subsystem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add MSVC runtime checks flags. This is activated by the presence
|
||||
// of a default selection whether or not it is overridden by a property.
|
||||
cmValue msvcRuntimeChecksDefault =
|
||||
|
||||
@@ -362,6 +362,8 @@ TargetProperty const StaticTargetProperties[] = {
|
||||
{ "VS_USE_DEBUG_LIBRARIES"_s, IC::NonImportedTarget },
|
||||
// ---- OpenWatcom
|
||||
{ "WATCOM_RUNTIME_LIBRARY"_s, IC::CanCompileSources },
|
||||
// ---- Embarcadero
|
||||
{ "EMBT_RUNTIME_LIBRARY"_s, IC::CanCompileSources },
|
||||
// ---- AIX
|
||||
{ "AIX_SHARED_LIBRARY_ARCHIVE"_s, IC::SharedLibraryTarget },
|
||||
{ "AIX_SHARED_LIBRARY_SYMLINKS"_s, IC::SharedLibraryTarget },
|
||||
@@ -2027,6 +2029,8 @@ void cmTarget::CopyCxxModulesProperties(cmTarget const* tgt)
|
||||
"VS_PLATFORM_TOOLSET",
|
||||
// ---- OpenWatcom
|
||||
"WATCOM_RUNTIME_LIBRARY",
|
||||
// ---- Embarcadero
|
||||
"EMBT_RUNTIME_LIBRARY",
|
||||
// -- Language
|
||||
// ---- C++
|
||||
"CXX_COMPILER_LAUNCHER",
|
||||
|
||||
@@ -51,6 +51,7 @@ add_custom_target(testbundleutils1_test ALL
|
||||
"-DMODULE=$<TARGET_FILE:module1>"
|
||||
"-DINPUTDIR=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}"
|
||||
"-DOUTPUTDIR=${CMAKE_CURRENT_BINARY_DIR}/testdir1"
|
||||
"-DCMAKE_OBJDUMP=${CMAKE_OBJDUMP}"
|
||||
-P "${CMAKE_CURRENT_SOURCE_DIR}/bundleutils.cmake"
|
||||
DEPENDS testbundleutils1 module1
|
||||
)
|
||||
@@ -82,6 +83,7 @@ add_custom_target(testbundleutils2_test ALL
|
||||
"-DMODULE=$<TARGET_FILE:module2>"
|
||||
"-DINPUTDIR=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}"
|
||||
"-DOUTPUTDIR=${CMAKE_CURRENT_BINARY_DIR}/testdir2"
|
||||
"-DCMAKE_OBJDUMP=${CMAKE_OBJDUMP}"
|
||||
-P "${CMAKE_CURRENT_SOURCE_DIR}/bundleutils.cmake"
|
||||
DEPENDS testbundleutils1 module2
|
||||
)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#ifndef framework_h
|
||||
#define framework_h
|
||||
|
||||
#ifdef WIN32
|
||||
#ifdef _WIN32
|
||||
# ifdef framework_EXPORTS
|
||||
# define FRAMEWORK_EXPORT __declspec(dllexport)
|
||||
# else
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#ifndef shared_h
|
||||
#define shared_h
|
||||
|
||||
#ifdef WIN32
|
||||
#ifdef _WIN32
|
||||
# ifdef shared_EXPORTS
|
||||
# define SHARED_EXPORT __declspec(dllexport)
|
||||
# else
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#ifndef shared2_h
|
||||
#define shared2_h
|
||||
|
||||
#ifdef WIN32
|
||||
#ifdef _WIN32
|
||||
# ifdef shared2_EXPORTS
|
||||
# define SHARED2_EXPORT __declspec(dllexport)
|
||||
# else
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#include "shared.h"
|
||||
#include "stdio.h"
|
||||
|
||||
#if defined(WIN32)
|
||||
#if defined(_WIN32)
|
||||
# include <windows.h>
|
||||
#else
|
||||
# include "dlfcn.h"
|
||||
@@ -14,7 +14,7 @@ int main(int, char**)
|
||||
framework();
|
||||
shared();
|
||||
|
||||
#if defined(WIN32)
|
||||
#if defined(_WIN32)
|
||||
HANDLE lib = LoadLibraryA("module1.dll");
|
||||
if (!lib) {
|
||||
printf("Failed to open module1\n");
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#include "shared.h"
|
||||
#include "stdio.h"
|
||||
|
||||
#if defined(WIN32)
|
||||
#if defined(_WIN32)
|
||||
# include <windows.h>
|
||||
#else
|
||||
# include "dlfcn.h"
|
||||
@@ -14,7 +14,7 @@ int main(int, char**)
|
||||
framework();
|
||||
shared();
|
||||
|
||||
#if defined(WIN32)
|
||||
#if defined(_WIN32)
|
||||
HANDLE lib = LoadLibraryA("module2.dll");
|
||||
if (!lib) {
|
||||
printf("Failed to open module2\n");
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#include "shared.h"
|
||||
#include "stdio.h"
|
||||
|
||||
#if defined(WIN32)
|
||||
#if defined(_WIN32)
|
||||
# include <windows.h>
|
||||
#else
|
||||
# include "dlfcn.h"
|
||||
@@ -14,7 +14,7 @@ int main(int, char**)
|
||||
framework();
|
||||
shared();
|
||||
|
||||
#if defined(WIN32)
|
||||
#if defined(_WIN32)
|
||||
HANDLE lib = LoadLibraryA("module3.dll");
|
||||
if (!lib) {
|
||||
printf("Failed to open module3\n");
|
||||
|
||||
@@ -10,11 +10,11 @@ add_executable(target_compile_options
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/main.cpp"
|
||||
)
|
||||
target_compile_options(target_compile_options
|
||||
PRIVATE $<$<CXX_COMPILER_ID:AppleClang,IBMClang,CrayClang,Clang,DPClang,GNU,LCC>:-DMY_PRIVATE_DEFINE>
|
||||
PRIVATE $<$<CXX_COMPILER_ID:AppleClang,IBMClang,CrayClang,EMBTClang,Clang,DPClang,GNU,LCC>:-DMY_PRIVATE_DEFINE>
|
||||
PUBLIC $<$<COMPILE_LANG_AND_ID:CXX,GNU,LCC>:-DMY_PUBLIC_DEFINE>
|
||||
PUBLIC $<$<COMPILE_LANG_AND_ID:CXX,GNU,LCC,Clang,DPClang,AppleClang,CrayClang,IBMClang>:-DMY_MUTLI_COMP_PUBLIC_DEFINE>
|
||||
PUBLIC $<$<COMPILE_LANG_AND_ID:CXX,GNU,LCC,Clang,DPClang,AppleClang,CrayClang,EMBTClang,IBMClang>:-DMY_MUTLI_COMP_PUBLIC_DEFINE>
|
||||
INTERFACE $<$<CXX_COMPILER_ID:GNU,LCC>:-DMY_INTERFACE_DEFINE>
|
||||
INTERFACE $<$<CXX_COMPILER_ID:GNU,LCC,Clang,DPClang,AppleClang,CrayClang,IBMClang>:-DMY_MULTI_COMP_INTERFACE_DEFINE>
|
||||
INTERFACE $<$<CXX_COMPILER_ID:GNU,LCC,Clang,DPClang,AppleClang,CrayClang,EMBTClang,IBMClang>:-DMY_MULTI_COMP_INTERFACE_DEFINE>
|
||||
)
|
||||
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|LCC")
|
||||
@@ -50,7 +50,7 @@ if(CMAKE_GENERATOR MATCHES "Visual Studio")
|
||||
endif()
|
||||
|
||||
target_compile_options(consumer
|
||||
PRIVATE $<$<CXX_COMPILER_ID:GNU,LCC,Clang,DPClang,AppleClang,CrayClang,IBMClang>:$<TARGET_PROPERTY:target_compile_options,INTERFACE_COMPILE_OPTIONS>>
|
||||
PRIVATE $<$<CXX_COMPILER_ID:GNU,LCC,Clang,DPClang,AppleClang,CrayClang,EMBTClang,IBMClang>:$<TARGET_PROPERTY:target_compile_options,INTERFACE_COMPILE_OPTIONS>>
|
||||
)
|
||||
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|LCC")
|
||||
|
||||
@@ -2143,6 +2143,10 @@ if(BUILD_TESTING)
|
||||
ADD_TEST_MACRO(WatcomRuntimeLibrary)
|
||||
endif()
|
||||
|
||||
if(CMAKE_C_COMPILER_ID MATCHES "EMBTClang" AND WIN32)
|
||||
ADD_TEST_MACRO(EMBTRuntimeLibrary)
|
||||
endif()
|
||||
|
||||
ADD_TEST_MACRO(CheckCompilerRelatedVariables CheckCompilerRelatedVariables)
|
||||
|
||||
if("${CMAKE_GENERATOR}" MATCHES "^Ninja$|Makefile|FASTBuild")
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
cmake_minimum_required(VERSION 3.28)
|
||||
project(EMBTRuntimeLibrary C CXX)
|
||||
|
||||
# Verify that an EMBT_RUNTIME_LIBRARY selection compiles and defines the expected
|
||||
# macros. The selection is applied both as a directory variable (which
|
||||
# initializes the target property and is forwarded into try_compile) and directly
|
||||
# on a target, so both paths are exercised. The VERIFY_* switches arm the #error
|
||||
# guards in verify.h, making a wrong property->flag mapping a build failure.
|
||||
function(verify tag lang src)
|
||||
cmake_parse_arguments(PARSE_ARGV 3 A "" "PROP;VALUE;TYPE" "DEFS")
|
||||
if(NOT A_TYPE)
|
||||
set(A_TYPE STATIC)
|
||||
endif()
|
||||
|
||||
# Local to this function scope, so it does not leak to sibling cases.
|
||||
if(A_PROP)
|
||||
set(CMAKE_${A_PROP} "${A_VALUE}")
|
||||
endif()
|
||||
|
||||
# try_compile wants -D-prefixed definitions; target_compile_definitions wants
|
||||
# bare names.
|
||||
set(try_defs "")
|
||||
foreach(d IN LISTS A_DEFS)
|
||||
list(APPEND try_defs "-D${d}")
|
||||
endforeach()
|
||||
|
||||
# try_compile only supports EXECUTABLE / STATIC_LIBRARY target types, so the
|
||||
# shared-library case is covered by the real add_library() target below.
|
||||
if(NOT A_TYPE STREQUAL "SHARED")
|
||||
set(CMAKE_TRY_COMPILE_TARGET_TYPE "STATIC_LIBRARY")
|
||||
try_compile(${tag}_${lang}_COMPILES
|
||||
${CMAKE_CURRENT_BINARY_DIR}/tc/${tag}-${lang}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/${src}
|
||||
COMPILE_DEFINITIONS ${try_defs}
|
||||
OUTPUT_VARIABLE out)
|
||||
if(${tag}_${lang}_COMPILES)
|
||||
message(STATUS "try_compile ${tag} (${lang}) worked")
|
||||
else()
|
||||
string(REPLACE "\n" "\n " out " ${out}")
|
||||
message(SEND_ERROR "try_compile ${tag} (${lang}) failed:\n${out}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
add_library(${tag}-${lang} ${A_TYPE} ${src})
|
||||
if(A_PROP)
|
||||
set_property(TARGET ${tag}-${lang} PROPERTY ${A_PROP} "${A_VALUE}")
|
||||
endif()
|
||||
target_compile_definitions(${tag}-${lang} PRIVATE ${A_DEFS})
|
||||
endfunction()
|
||||
|
||||
foreach(lang_src "C;verify.c" "CXX;verify.cxx")
|
||||
list(GET lang_src 0 lang)
|
||||
list(GET lang_src 1 src)
|
||||
|
||||
# No selection: none of the macros are defined.
|
||||
verify(default ${lang} ${src})
|
||||
|
||||
# Runtime library.
|
||||
verify(static ${lang} ${src} PROP EMBT_RUNTIME_LIBRARY VALUE Static)
|
||||
verify(dynamic ${lang} ${src} PROP EMBT_RUNTIME_LIBRARY VALUE Dynamic
|
||||
DEFS VERIFY_RTLDLL VERIFY_USEPACKAGES)
|
||||
|
||||
# A shared library is a plain DLL: linked with -tD and compiled with __DLL__.
|
||||
# A trivial DLL links without the RAD Studio runtime.
|
||||
verify(dll ${lang} ${src} TYPE SHARED DEFS VERIFY_DLL)
|
||||
endforeach()
|
||||
@@ -0,0 +1 @@
|
||||
#include "verify.h"
|
||||
@@ -0,0 +1 @@
|
||||
#include "verify.h"
|
||||
@@ -0,0 +1,38 @@
|
||||
/* The EMBT_RUNTIME_LIBRARY property and the target type select bcc64x driver
|
||||
flags. Each flag defines characteristic preprocessor macros; assert them
|
||||
here so a wrong mapping fails the build. The VERIFY_* switches are passed
|
||||
by the test for the selection under test. */
|
||||
|
||||
/* EMBT_RUNTIME_LIBRARY=Dynamic uses the dynamic RTL (-tR), which defines
|
||||
_RTLDLL. */
|
||||
#ifdef VERIFY_RTLDLL
|
||||
# ifndef _RTLDLL
|
||||
# error "_RTLDLL not defined by the dynamic runtime selection"
|
||||
# endif
|
||||
#else
|
||||
# ifdef _RTLDLL
|
||||
# error "_RTLDLL defined without the dynamic runtime selection"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* The dynamic RTL also defines USEPACKAGES (added by CMake). */
|
||||
#ifdef VERIFY_USEPACKAGES
|
||||
# ifndef USEPACKAGES
|
||||
# error "USEPACKAGES not defined by the dynamic runtime selection"
|
||||
# endif
|
||||
#else
|
||||
# ifdef USEPACKAGES
|
||||
# error "USEPACKAGES defined without the dynamic runtime selection"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* A shared library defines __DLL__. */
|
||||
#ifdef VERIFY_DLL
|
||||
# ifndef __DLL__
|
||||
# error "__DLL__ not defined for a shared library"
|
||||
# endif
|
||||
#else
|
||||
# ifdef __DLL__
|
||||
# error "__DLL__ defined for a non-shared target"
|
||||
# endif
|
||||
#endif
|
||||
@@ -12,7 +12,8 @@ if(MSVC AND NOT MSVC_VERSION LESS 1400)
|
||||
-P ${CMAKE_CURRENT_SOURCE_DIR}/check.cmake)
|
||||
add_executable(MSManifestNone main.c)
|
||||
set_property(TARGET MSManifestNone PROPERTY LINK_FLAGS "/MANIFEST:NO")
|
||||
elseif(WIN32 AND CMAKE_C_COMPILER_ID MATCHES "Clang")
|
||||
elseif(WIN32 AND CMAKE_C_COMPILER_ID MATCHES "Clang"
|
||||
AND CMAKE_C_SIMULATE_ID STREQUAL "MSVC")
|
||||
add_test(NAME MSManifest.Single COMMAND
|
||||
${CMAKE_COMMAND} -Dexe=$<TARGET_FILE:MSManifest>
|
||||
-P ${CMAKE_CURRENT_SOURCE_DIR}/check.cmake)
|
||||
|
||||
@@ -6,7 +6,9 @@ add_executable(MSMultipleManifest main.c
|
||||
${CMAKE_CURRENT_BINARY_DIR}/test_manifest2.manifest
|
||||
${CMAKE_CURRENT_BINARY_DIR}/test_manifest3.manifest)
|
||||
|
||||
if((MSVC AND NOT MSVC_VERSION LESS 1400) OR (WIN32 AND CMAKE_C_COMPILER_ID MATCHES "Clang") )
|
||||
if((MSVC AND NOT MSVC_VERSION LESS 1400)
|
||||
OR (WIN32 AND CMAKE_C_COMPILER_ID MATCHES "Clang"
|
||||
AND CMAKE_C_SIMULATE_ID STREQUAL "MSVC"))
|
||||
add_test(NAME MSManifest.Multiple COMMAND
|
||||
${CMAKE_COMMAND} -Dexe=$<TARGET_FILE:MSMultipleManifest>
|
||||
-P ${CMAKE_CURRENT_SOURCE_DIR}/check.cmake)
|
||||
|
||||
@@ -55,7 +55,7 @@ endmacro()
|
||||
# detailed features tables, not just meta-features
|
||||
|
||||
if (CMAKE_C_COMPILE_FEATURES)
|
||||
if (NOT CMAKE_C_COMPILER_ID MATCHES "^(LCC|Cray|CrayClang|PGI|NVHPC|XL|XLClang|IBMClang|IntelLLVM|DPClang|Fujitsu|FujitsuClang|OrangeC)$")
|
||||
if (NOT CMAKE_C_COMPILER_ID MATCHES "^(LCC|Cray|CrayClang|PGI|NVHPC|XL|XLClang|IBMClang|IntelLLVM|DPClang|Fujitsu|FujitsuClang|OrangeC|EMBTClang)$")
|
||||
set(C_expected_features ${CMAKE_C_COMPILE_FEATURES})
|
||||
list(FILTER C_expected_features EXCLUDE REGEX "^c_std_[0-9][0-9]")
|
||||
endif()
|
||||
@@ -98,7 +98,7 @@ if (C_expected_features)
|
||||
endif()
|
||||
|
||||
if (CMAKE_CXX_COMPILE_FEATURES)
|
||||
if (NOT CMAKE_CXX_COMPILER_ID MATCHES "^(LCC|Cray|CrayClang|PGI|NVHPC|XL|XLClang|IBMClang|IntelLLVM|DPClang|Fujitsu|FujitsuClang|OrangeC)$")
|
||||
if (NOT CMAKE_CXX_COMPILER_ID MATCHES "^(LCC|Cray|CrayClang|PGI|NVHPC|XL|XLClang|IBMClang|IntelLLVM|DPClang|Fujitsu|FujitsuClang|OrangeC|EMBTClang)$")
|
||||
set(CXX_expected_features ${CMAKE_CXX_COMPILE_FEATURES})
|
||||
list(FILTER CXX_expected_features EXCLUDE REGEX "^cxx_std_[0-9][0-9]")
|
||||
endif()
|
||||
|
||||
@@ -111,7 +111,7 @@ DynamicLoader::SymbolPointer DynamicLoader::GetSymbolAddress(
|
||||
DynamicLoader::LibraryHandle lib, std::string const& sym)
|
||||
{
|
||||
void* result;
|
||||
# if defined(__BORLANDC__) || defined(__WATCOMC__)
|
||||
# if (defined(__BORLANDC__) && !defined(_WIN64)) || defined(__WATCOMC__)
|
||||
// Need to prepend symbols with '_'
|
||||
std::string ssym = '_' + sym;
|
||||
char const* rsym = ssym.c_str();
|
||||
|
||||
@@ -666,6 +666,7 @@ if(MSVC)
|
||||
add_RunCMake_test(MSVCRuntimeTypeInfo)
|
||||
add_RunCMake_test(MSVCDebugInformationFormat)
|
||||
endif()
|
||||
add_RunCMake_test(EMBTClang)
|
||||
if(XCODE_VERSION)
|
||||
set(ObjectLibrary_ARGS -DXCODE_VERSION=${XCODE_VERSION})
|
||||
endif()
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
cmake_minimum_required(VERSION 3.14)
|
||||
project(${RunCMake_TEST} NONE)
|
||||
include(${RunCMake_TEST}.cmake)
|
||||
@@ -0,0 +1,32 @@
|
||||
include(RunCMake)
|
||||
|
||||
# Registration and initialization of the EMBT_RUNTIME_LIBRARY target property is
|
||||
# generic and does not require the Embarcadero toolchain, so it runs on any host.
|
||||
run_cmake(embt-properties)
|
||||
|
||||
# EMBT_RUNTIME_LIBRARY link selection: Dynamic links the shared libc++
|
||||
# (libc++-380.dll import), Static links it statically (no import). Builds real
|
||||
# exes with bcc64x and checks imports; a no-op where bcc64x is absent.
|
||||
run_cmake(runtime-library)
|
||||
|
||||
# Compiler-id regression: bcc64x -> EMBTClang, older drivers -> Embarcadero.
|
||||
# The case finds the drivers itself and is a no-op where none are installed.
|
||||
run_cmake(compiler-id-drivers)
|
||||
|
||||
# Binutils pinning: the linker and LLVM tools resolve to distinct absolute paths
|
||||
# beside the compiler. Finds bcc64x itself; a no-op where it is absent.
|
||||
run_cmake(binutils-pinned)
|
||||
|
||||
# Subsystem macros: a console target compiles with __CONSOLE__ and a GUI target
|
||||
# without it (compilation sees the macro, not just the link switch).
|
||||
# Driver-gated.
|
||||
run_cmake(subsystem-macros)
|
||||
|
||||
# Precompiled header reuse across target kinds: a static library's header is
|
||||
# reused by shared and module libraries and console and GUI executables.
|
||||
# Driver-gated.
|
||||
run_cmake(pch-reuse-kinds)
|
||||
|
||||
# C++ module scanning is not supported: a C++20 target builds without being
|
||||
# scanned, and C++ module sources are rejected. Driver-gated.
|
||||
run_cmake(cxx-module-scanning)
|
||||
@@ -0,0 +1,60 @@
|
||||
# Regression guard for C4: EMBTClang-FindBinUtils must pin the linker and the
|
||||
# LLVM binutils to absolute paths beside the compiler, each a distinct tool.
|
||||
# The distinctness check specifically catches the find_program cache-reuse trap
|
||||
# -- dropping the per-iteration unset(... CACHE) collapses every tool onto the
|
||||
# first (ld.lld). Gated on bcc64x being present; a no-op where it is absent.
|
||||
|
||||
if(NOT WIN32)
|
||||
return()
|
||||
endif()
|
||||
|
||||
set(_hints "")
|
||||
if(DEFINED ENV{TP})
|
||||
list(APPEND _hints "$ENV{TP}/bin64")
|
||||
endif()
|
||||
find_program(EMBT_BCC64X NAMES bcc64x HINTS ${_hints})
|
||||
if(NOT EMBT_BCC64X)
|
||||
message(STATUS "bcc64x not found on PATH or under $TP; binutils pinning check skipped.")
|
||||
return()
|
||||
endif()
|
||||
|
||||
# Start from a clean nested build tree: compiler determination (and thus
|
||||
# FindBinUtils) is cached, so a stale tree would not re-run the logic under test.
|
||||
file(REMOVE_RECURSE "${CMAKE_CURRENT_BINARY_DIR}/build")
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
-S "${CMAKE_CURRENT_SOURCE_DIR}/binutils"
|
||||
-B "${CMAKE_CURRENT_BINARY_DIR}/build"
|
||||
-G "${CMAKE_GENERATOR}"
|
||||
"-DCMAKE_MAKE_PROGRAM=${CMAKE_MAKE_PROGRAM}"
|
||||
"-DCMAKE_C_COMPILER=${EMBT_BCC64X}"
|
||||
-DCMAKE_C_COMPILER_WORKS=1
|
||||
OUTPUT_VARIABLE _out ERROR_VARIABLE _err)
|
||||
|
||||
# FindBinUtils pins tools found under REALPATH(compiler dir), so canonicalize
|
||||
# both sides before comparing -- the work trees are reachable through junctions,
|
||||
# where a literal directory would not string-match the resolved one.
|
||||
get_filename_component(_bindir "${EMBT_BCC64X}" REALPATH)
|
||||
get_filename_component(_bindir "${_bindir}" DIRECTORY)
|
||||
set(_seen "")
|
||||
foreach(_tool LINKER NM OBJDUMP STRIP DLLTOOL)
|
||||
if(NOT _out MATCHES "BINUTIL ${_tool}=\\[([^]]+)\\]")
|
||||
message(SEND_ERROR "no CMAKE_${_tool} reported.\n${_out}${_err}")
|
||||
continue()
|
||||
endif()
|
||||
set(_path "${CMAKE_MATCH_1}")
|
||||
if(NOT IS_ABSOLUTE "${_path}" OR NOT EXISTS "${_path}")
|
||||
message(SEND_ERROR "CMAKE_${_tool} is not an existing absolute path: [${_path}]")
|
||||
endif()
|
||||
get_filename_component(_dir "${_path}" REALPATH)
|
||||
get_filename_component(_dir "${_dir}" DIRECTORY)
|
||||
if(NOT _dir STREQUAL _bindir)
|
||||
message(SEND_ERROR "CMAKE_${_tool} is not beside the compiler: [${_path}]")
|
||||
endif()
|
||||
if(_path IN_LIST _seen)
|
||||
message(SEND_ERROR
|
||||
"CMAKE_${_tool} collapsed onto an already-pinned tool: [${_path}] "
|
||||
"(find_program cache-reuse regression)")
|
||||
endif()
|
||||
list(APPEND _seen "${_path}")
|
||||
endforeach()
|
||||
@@ -0,0 +1,6 @@
|
||||
cmake_minimum_required(VERSION 3.14)
|
||||
project(embt_binutils C)
|
||||
# The parent test reads these back to assert each tool was pinned.
|
||||
foreach(t LINKER NM OBJDUMP STRIP DLLTOOL)
|
||||
message(STATUS "BINUTIL ${t}=[${CMAKE_${t}}]")
|
||||
endforeach()
|
||||
@@ -0,0 +1,56 @@
|
||||
# Regression guard for the Embarcadero compiler-id detection: bcc64x must
|
||||
# identify as EMBTClang while the older Clang-based drivers (bcc32x, bcc64,
|
||||
# bcc32c) stay Embarcadero. bcc64x is
|
||||
# discriminated by __MINGW64__ (bcc64 also defines _WIN64, so _WIN64 would not
|
||||
# tell them apart), and EMBTClang is tried before Embarcadero because bcc64x
|
||||
# also defines __BORLANDC__/__CODEGEARC_VERSION__.
|
||||
#
|
||||
# Each driver's identity is checked by a nested configure, gated on the driver
|
||||
# being present: real coverage where a RAD Studio tree is installed, a no-op
|
||||
# elsewhere (upstream CI has none of these compilers).
|
||||
|
||||
if(NOT WIN32)
|
||||
return()
|
||||
endif()
|
||||
|
||||
set(_hints "")
|
||||
if(DEFINED ENV{TP})
|
||||
list(APPEND _hints "$ENV{TP}/bin64" "$ENV{TP}/bin")
|
||||
endif()
|
||||
|
||||
# driver name -> expected CMAKE_C_COMPILER_ID
|
||||
set(_expect
|
||||
bcc64x EMBTClang
|
||||
bcc32x Embarcadero
|
||||
bcc64 Embarcadero
|
||||
bcc32c Embarcadero)
|
||||
|
||||
set(_found_any NO)
|
||||
while(_expect)
|
||||
list(POP_FRONT _expect _drv _want)
|
||||
find_program(EMBT_DRIVER_${_drv} NAMES ${_drv} HINTS ${_hints})
|
||||
if(NOT EMBT_DRIVER_${_drv})
|
||||
continue()
|
||||
endif()
|
||||
set(_found_any YES)
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
-S "${CMAKE_CURRENT_SOURCE_DIR}/compiler-id"
|
||||
-B "${CMAKE_CURRENT_BINARY_DIR}/id-${_drv}"
|
||||
-G "${CMAKE_GENERATOR}"
|
||||
"-DCMAKE_MAKE_PROGRAM=${CMAKE_MAKE_PROGRAM}"
|
||||
"-DCMAKE_C_COMPILER=${EMBT_DRIVER_${_drv}}"
|
||||
-DCMAKE_C_COMPILER_WORKS=1
|
||||
OUTPUT_VARIABLE _out ERROR_VARIABLE _err)
|
||||
if(NOT _out MATCHES "DRIVER_COMPILER_ID=\\[${_want}\\]")
|
||||
message(SEND_ERROR
|
||||
"driver '${_drv}' should identify as '${_want}'.\n"
|
||||
"----- configure output -----\n${_out}${_err}")
|
||||
endif()
|
||||
endwhile()
|
||||
|
||||
if(NOT _found_any)
|
||||
message(STATUS
|
||||
"No Embarcadero drivers found on PATH or under \$TP; "
|
||||
"compiler-id regression check skipped.")
|
||||
endif()
|
||||
@@ -0,0 +1,4 @@
|
||||
cmake_minimum_required(VERSION 3.14)
|
||||
project(embt_compiler_id C)
|
||||
# The parent test reads this line back to assert the detected identity.
|
||||
message(STATUS "DRIVER_COMPILER_ID=[${CMAKE_C_COMPILER_ID}]")
|
||||
@@ -0,0 +1,80 @@
|
||||
# C++ module scanning is not supported: a C++20 target that includes standard
|
||||
# headers must build without being scanned, even when clang-scan-deps is
|
||||
# present beside bcc64x, and a target with C++ module sources must be rejected
|
||||
# at configure time. Driver-gated: a no-op where bcc64x is not installed.
|
||||
if(NOT WIN32)
|
||||
return()
|
||||
endif()
|
||||
|
||||
set(_hints "")
|
||||
if(DEFINED ENV{TP})
|
||||
list(APPEND _hints "$ENV{TP}/bin64" "$ENV{TP}/bin")
|
||||
endif()
|
||||
find_program(EMBT_BCC64X NAMES bcc64x HINTS ${_hints})
|
||||
if(NOT EMBT_BCC64X)
|
||||
message(STATUS "bcc64x not found; C++ module scanning check skipped.")
|
||||
return()
|
||||
endif()
|
||||
get_filename_component(_bindir "${EMBT_BCC64X}" DIRECTORY)
|
||||
|
||||
function(_scan_configure case)
|
||||
set(_b "${CMAKE_CURRENT_BINARY_DIR}/scan-${case}")
|
||||
file(REMOVE_RECURSE "${_b}")
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
-S "${CMAKE_CURRENT_SOURCE_DIR}/cxx-module-scanning"
|
||||
-B "${_b}"
|
||||
-G "${CMAKE_GENERATOR}"
|
||||
"-DCMAKE_MAKE_PROGRAM=${CMAKE_MAKE_PROGRAM}"
|
||||
"-DCMAKE_CXX_COMPILER=${EMBT_BCC64X}"
|
||||
${ARGN}
|
||||
OUTPUT_VARIABLE _out ERROR_VARIABLE _err RESULT_VARIABLE _rc)
|
||||
set(_rc "${_rc}" PARENT_SCOPE)
|
||||
set(_log "${_out}${_err}" PARENT_SCOPE)
|
||||
set(_b "${_b}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
# A C++20 target builds without scan steps, also when a scanner is named.
|
||||
set(_cases plain)
|
||||
if(EXISTS "${_bindir}/clang-scan-deps.exe")
|
||||
list(APPEND _cases scanner)
|
||||
endif()
|
||||
foreach(_case IN LISTS _cases)
|
||||
set(_opts "")
|
||||
if(_case STREQUAL "scanner")
|
||||
set(_opts
|
||||
"-DCMAKE_CXX_COMPILER_CLANG_SCAN_DEPS=${_bindir}/clang-scan-deps.exe")
|
||||
endif()
|
||||
_scan_configure(${_case} ${_opts})
|
||||
if(NOT _rc EQUAL 0)
|
||||
message(SEND_ERROR "configure (${_case}) failed:\n${_log}")
|
||||
continue()
|
||||
endif()
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND} --build "${_b}"
|
||||
OUTPUT_VARIABLE _out ERROR_VARIABLE _err RESULT_VARIABLE _rc)
|
||||
if(NOT _rc EQUAL 0)
|
||||
message(SEND_ERROR "build (${_case}) failed:\n${_out}${_err}")
|
||||
continue()
|
||||
endif()
|
||||
if(CMAKE_GENERATOR MATCHES "Ninja")
|
||||
file(GLOB _ninja_files "${_b}/build*.ninja")
|
||||
foreach(_f IN LISTS _ninja_files)
|
||||
file(STRINGS "${_f}" _steps REGEX "^build [^:]*: CXX_SCAN__")
|
||||
if(_steps)
|
||||
message(SEND_ERROR "sources are scanned (${_case}):\n${_steps}")
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# A target with C++ module sources is rejected.
|
||||
_scan_configure(module -DWITH_MODULE=ON)
|
||||
set(_want "does not provide a way to discover the import graph dependencies")
|
||||
string(REGEX REPLACE "[ \n]+" " " _flat "${_log}")
|
||||
string(FIND "${_flat}" "${_want}" _pos)
|
||||
if(_rc EQUAL 0 OR _pos EQUAL -1)
|
||||
message(SEND_ERROR
|
||||
"a CXX_MODULES target should be rejected with:\n ${_want}\n"
|
||||
"Result: ${_rc}\n${_log}")
|
||||
endif()
|
||||
@@ -0,0 +1,13 @@
|
||||
cmake_minimum_required(VERSION 3.28)
|
||||
project(scantest CXX)
|
||||
|
||||
# CMP0155 is NEW, so a C++20 target would be scanned for module dependencies
|
||||
# if the toolchain provided a scanning rule.
|
||||
add_library(scantest STATIC scantest.cpp)
|
||||
target_compile_features(scantest PRIVATE cxx_std_20)
|
||||
|
||||
if(WITH_MODULE)
|
||||
add_library(modtest STATIC)
|
||||
target_sources(modtest PUBLIC FILE_SET CXX_MODULES FILES modtest.cppm)
|
||||
target_compile_features(modtest PUBLIC cxx_std_20)
|
||||
endif()
|
||||
@@ -0,0 +1,6 @@
|
||||
export module modtest;
|
||||
|
||||
export int modtest()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
#include <iostream>
|
||||
|
||||
int scantest()
|
||||
{
|
||||
std::cout << "scantest\n";
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
enable_language(C)
|
||||
|
||||
function(expect_prop tgt prop want)
|
||||
get_property(got TARGET ${tgt} PROPERTY ${prop})
|
||||
if(NOT "${got}" STREQUAL "${want}")
|
||||
message(SEND_ERROR "${tgt} ${prop}: expected '${want}', got '${got}'")
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# A target created before the variable is set must not inherit it.
|
||||
add_library(before empty.c)
|
||||
expect_prop(before EMBT_RUNTIME_LIBRARY "")
|
||||
|
||||
# The CMAKE_EMBT_RUNTIME_LIBRARY variable initializes the property at creation.
|
||||
set(CMAKE_EMBT_RUNTIME_LIBRARY "Dynamic")
|
||||
|
||||
add_library(after empty.c)
|
||||
expect_prop(after EMBT_RUNTIME_LIBRARY "Dynamic")
|
||||
@@ -0,0 +1,4 @@
|
||||
int embt_empty(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
# One precompiled header, built by a static library and reused by a shared
|
||||
# library, a module library, a console executable and a GUI executable. bcc64x
|
||||
# records some target-kind switches in a precompiled header and rejects a
|
||||
# mismatch (E904), so they must not reach compilation; each target must still
|
||||
# see its own __DLL__/__CONSOLE__ state. The sources #error on the wrong
|
||||
# state, so a clean build is the assertion. Driver-gated; a no-op where bcc64x
|
||||
# is absent.
|
||||
|
||||
if(NOT WIN32)
|
||||
return()
|
||||
endif()
|
||||
|
||||
set(_hints "")
|
||||
if(DEFINED ENV{TP})
|
||||
list(APPEND _hints "$ENV{TP}/bin64")
|
||||
endif()
|
||||
find_program(EMBT_BCC64X NAMES bcc64x HINTS ${_hints})
|
||||
if(NOT EMBT_BCC64X)
|
||||
message(STATUS
|
||||
"bcc64x not found on PATH or under $TP; PCH reuse check skipped.")
|
||||
return()
|
||||
endif()
|
||||
|
||||
set(_bin "${CMAKE_CURRENT_BINARY_DIR}/pch-reuse-kinds-build")
|
||||
file(REMOVE_RECURSE "${_bin}")
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
-S "${CMAKE_CURRENT_SOURCE_DIR}/pch-reuse-kinds"
|
||||
-B "${_bin}"
|
||||
-G "${CMAKE_GENERATOR}"
|
||||
"-DCMAKE_MAKE_PROGRAM=${CMAKE_MAKE_PROGRAM}"
|
||||
"-DCMAKE_CXX_COMPILER=${EMBT_BCC64X}"
|
||||
RESULT_VARIABLE _rc OUTPUT_VARIABLE _o ERROR_VARIABLE _e)
|
||||
if(NOT _rc EQUAL 0)
|
||||
message(SEND_ERROR "configure failed:\n${_o}${_e}")
|
||||
return()
|
||||
endif()
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND} --build "${_bin}"
|
||||
RESULT_VARIABLE _rc OUTPUT_VARIABLE _o ERROR_VARIABLE _e)
|
||||
if(NOT _rc EQUAL 0)
|
||||
message(SEND_ERROR
|
||||
"build failed -- a target could not reuse the precompiled header, or saw "
|
||||
"the wrong __DLL__/__CONSOLE__ state:\n${_o}${_e}")
|
||||
endif()
|
||||
@@ -0,0 +1,13 @@
|
||||
cmake_minimum_required(VERSION 3.23)
|
||||
project(embt_pch_reuse CXX)
|
||||
|
||||
add_library(pch STATIC lib.cpp)
|
||||
target_precompile_headers(pch PRIVATE pch.h)
|
||||
|
||||
add_library(dll SHARED dll.cpp)
|
||||
add_library(mod MODULE dll.cpp)
|
||||
add_executable(console console.cpp)
|
||||
add_executable(gui WIN32 gui.cpp)
|
||||
foreach(t IN ITEMS dll mod console gui)
|
||||
target_precompile_headers(${t} REUSE_FROM pch)
|
||||
endforeach()
|
||||
@@ -0,0 +1,8 @@
|
||||
// A console executable must be compiled with __CONSOLE__ and without __DLL__.
|
||||
#if !defined(__CONSOLE__) || defined(__DLL__)
|
||||
# error "console target compiled with the wrong __CONSOLE__/__DLL__ state"
|
||||
#endif
|
||||
int main()
|
||||
{
|
||||
return static_cast<int>(std::string().size());
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
// A shared or module library must be compiled with __DLL__.
|
||||
#ifndef __DLL__
|
||||
# error "DLL compiled without __DLL__"
|
||||
#endif
|
||||
__declspec(dllexport) int dll_value()
|
||||
{
|
||||
return static_cast<int>(std::string("dll").size());
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
// A GUI (WIN32) executable must be compiled without __CONSOLE__ and __DLL__.
|
||||
#if defined(__CONSOLE__) || defined(__DLL__)
|
||||
# error "GUI target compiled with __CONSOLE__ or __DLL__"
|
||||
#endif
|
||||
extern "C" int __stdcall WinMain(void*, void*, char*, int)
|
||||
{
|
||||
return static_cast<int>(std::string().size());
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
// A static library is neither a DLL nor a console target.
|
||||
#if defined(__DLL__) || defined(__CONSOLE__)
|
||||
# error "static library compiled with __DLL__ or __CONSOLE__"
|
||||
#endif
|
||||
std::string lib_value()
|
||||
{
|
||||
return "lib";
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
#include <string>
|
||||
@@ -0,0 +1,107 @@
|
||||
# EMBT_RUNTIME_LIBRARY must select the linked C++ runtime: Dynamic links the
|
||||
# shared libc++ (an import of libc++-<ver>.dll), Static (and the default) link it
|
||||
# statically (no such import). Build a real exe and module library for each
|
||||
# value with bcc64x and inspect their imports -- a configure-only check cannot
|
||||
# tell them apart, since the switches only change the link. The module library
|
||||
# must also be compiled with __DLL__, seen as an export only defined under it.
|
||||
# The helper project also carries a .rc source, so this guards against the
|
||||
# runtime-library handling mishandling a non-C/CXX language. Driver-gated: a
|
||||
# no-op where bcc64x is not installed.
|
||||
if(NOT WIN32)
|
||||
return()
|
||||
endif()
|
||||
|
||||
set(_hints "")
|
||||
if(DEFINED ENV{TP})
|
||||
list(APPEND _hints "$ENV{TP}/bin64" "$ENV{TP}/bin")
|
||||
endif()
|
||||
find_program(EMBT_BCC64X NAMES bcc64x HINTS ${_hints})
|
||||
if(NOT EMBT_BCC64X)
|
||||
message(STATUS "bcc64x not found; EMBT_RUNTIME_LIBRARY link check skipped.")
|
||||
return()
|
||||
endif()
|
||||
get_filename_component(_bindir "${EMBT_BCC64X}" DIRECTORY)
|
||||
find_program(EMBT_OBJDUMP NAMES llvm-objdump HINTS "${_bindir}")
|
||||
if(NOT EMBT_OBJDUMP)
|
||||
message(STATUS
|
||||
"llvm-objdump not found; EMBT_RUNTIME_LIBRARY link check skipped.")
|
||||
return()
|
||||
endif()
|
||||
|
||||
# "" exercises the default (Static); Static and Dynamic the explicit values.
|
||||
foreach(_val "" Static Dynamic)
|
||||
if(_val STREQUAL "")
|
||||
set(_tag default)
|
||||
else()
|
||||
set(_tag "${_val}")
|
||||
endif()
|
||||
set(_b "${CMAKE_CURRENT_BINARY_DIR}/rtl-${_tag}")
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
-S "${CMAKE_CURRENT_SOURCE_DIR}/runtime-library"
|
||||
-B "${_b}"
|
||||
-G "${CMAKE_GENERATOR}"
|
||||
"-DCMAKE_MAKE_PROGRAM=${CMAKE_MAKE_PROGRAM}"
|
||||
"-DCMAKE_CXX_COMPILER=${EMBT_BCC64X}"
|
||||
"-DRTL_VALUE=${_val}"
|
||||
OUTPUT_VARIABLE _out ERROR_VARIABLE _err RESULT_VARIABLE _rc)
|
||||
if(NOT _rc EQUAL 0)
|
||||
message(SEND_ERROR "configure (${_tag}) failed:\n${_out}${_err}")
|
||||
continue()
|
||||
endif()
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND} --build "${_b}"
|
||||
OUTPUT_VARIABLE _out ERROR_VARIABLE _err RESULT_VARIABLE _rc)
|
||||
if(NOT _rc EQUAL 0)
|
||||
message(SEND_ERROR "build (${_tag}) failed:\n${_out}${_err}")
|
||||
continue()
|
||||
endif()
|
||||
foreach(_art IN ITEMS rtltest.exe rtlmod.dll)
|
||||
execute_process(
|
||||
COMMAND "${EMBT_OBJDUMP}" -p "${_b}/${_art}"
|
||||
OUTPUT_VARIABLE _imports RESULT_VARIABLE _od_rc)
|
||||
if(NOT _od_rc EQUAL 0)
|
||||
message(SEND_ERROR
|
||||
"llvm-objdump (${_tag}, ${_art}) failed:\n${_imports}")
|
||||
continue()
|
||||
endif()
|
||||
if(_imports MATCHES "libc\\+\\+[-0-9]*\\.dll")
|
||||
set(_dynamic YES)
|
||||
else()
|
||||
set(_dynamic NO)
|
||||
endif()
|
||||
if(_val STREQUAL "Dynamic" AND NOT _dynamic)
|
||||
message(SEND_ERROR
|
||||
"EMBT_RUNTIME_LIBRARY=Dynamic should link the shared libc++, but "
|
||||
"${_art} has no libc++ import.")
|
||||
elseif(NOT _val STREQUAL "Dynamic" AND _dynamic)
|
||||
message(SEND_ERROR
|
||||
"EMBT_RUNTIME_LIBRARY=${_tag} should link libc++ statically, but "
|
||||
"${_art} imports the shared libc++.")
|
||||
endif()
|
||||
if(_art STREQUAL "rtlmod.dll" AND
|
||||
NOT _imports MATCHES "rtlmod_has_dll_macro")
|
||||
message(SEND_ERROR
|
||||
"The module library (${_tag}) was not compiled with __DLL__.")
|
||||
endif()
|
||||
endforeach()
|
||||
endforeach()
|
||||
|
||||
# An unknown value is rejected when generating for the bcc64x toolchain.
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
-S "${CMAKE_CURRENT_SOURCE_DIR}/runtime-library"
|
||||
-B "${CMAKE_CURRENT_BINARY_DIR}/rtl-Bogus"
|
||||
-G "${CMAKE_GENERATOR}"
|
||||
"-DCMAKE_MAKE_PROGRAM=${CMAKE_MAKE_PROGRAM}"
|
||||
"-DCMAKE_CXX_COMPILER=${EMBT_BCC64X}"
|
||||
"-DRTL_VALUE=Bogus"
|
||||
OUTPUT_VARIABLE _out ERROR_VARIABLE _err RESULT_VARIABLE _rc)
|
||||
set(_want
|
||||
"EMBT_RUNTIME_LIBRARY value 'Bogus' not known for this CXX compiler.")
|
||||
string(FIND "${_err}" "${_want}" _pos)
|
||||
if(_rc EQUAL 0 OR _pos EQUAL -1)
|
||||
message(SEND_ERROR
|
||||
"EMBT_RUNTIME_LIBRARY=Bogus should be rejected with:\n ${_want}\n"
|
||||
"Result: ${_rc}\n${_out}${_err}")
|
||||
endif()
|
||||
@@ -0,0 +1,18 @@
|
||||
cmake_minimum_required(VERSION 3.28)
|
||||
project(rtltest CXX RC)
|
||||
|
||||
# A console exe that uses libc++ (std::string), so the runtime-library choice is
|
||||
# observable in its imports. It also carries a .rc resource -- which a RAD
|
||||
# Studio WIN32 app almost always has -- to guard against the runtime-library
|
||||
# handling mishandling a non-C/CXX language (the RC "compiler" has no runtime
|
||||
# library). RTL_VALUE is passed as Static, Dynamic, or empty (the default).
|
||||
add_executable(rtltest main.cpp app.rc)
|
||||
|
||||
# A module library takes the same runtime-library choice, and must also be
|
||||
# compiled with __DLL__ defined.
|
||||
add_library(rtlmod MODULE module.cpp)
|
||||
|
||||
if(NOT RTL_VALUE STREQUAL "")
|
||||
set_property(TARGET rtltest rtlmod
|
||||
PROPERTY EMBT_RUNTIME_LIBRARY "${RTL_VALUE}")
|
||||
endif()
|
||||
@@ -0,0 +1,4 @@
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
1 "EMBTClang runtime-library test"
|
||||
END
|
||||
@@ -0,0 +1,6 @@
|
||||
#include <string>
|
||||
int main()
|
||||
{
|
||||
std::string s = "x";
|
||||
return static_cast<int>(s.size());
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
#include <string>
|
||||
|
||||
extern "C" __declspec(dllexport) int rtlmod_size()
|
||||
{
|
||||
std::string s = "x";
|
||||
return static_cast<int>(s.size());
|
||||
}
|
||||
|
||||
#ifdef __DLL__
|
||||
extern "C" __declspec(dllexport) int rtlmod_has_dll_macro()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,57 @@
|
||||
# Regression guard for C3: a console target is compiled with __CONSOLE__, which
|
||||
# -tC defines in the IDE build, not only linked with -tC, and a GUI target is
|
||||
# not -- and compile uses the same per-config WIN32_EXECUTABLE determination as
|
||||
# the link, so a genex-valued property cannot make the two disagree. The
|
||||
# sources #error on the wrong __CONSOLE__ state, so a clean build is the
|
||||
# assertion. Driver-gated; a no-op where bcc64x is absent.
|
||||
|
||||
if(NOT WIN32)
|
||||
return()
|
||||
endif()
|
||||
|
||||
set(_hints "")
|
||||
if(DEFINED ENV{TP})
|
||||
list(APPEND _hints "$ENV{TP}/bin64")
|
||||
endif()
|
||||
find_program(EMBT_BCC64X NAMES bcc64x HINTS ${_hints})
|
||||
if(NOT EMBT_BCC64X)
|
||||
message(STATUS "bcc64x not found on PATH or under $TP; __CONSOLE__ check skipped.")
|
||||
return()
|
||||
endif()
|
||||
|
||||
function(_subsystem_build case config)
|
||||
set(_bin "${CMAKE_CURRENT_BINARY_DIR}/${case}")
|
||||
file(REMOVE_RECURSE "${_bin}")
|
||||
set(_cfg_arg "")
|
||||
if(config)
|
||||
set(_cfg_arg "-DCMAKE_BUILD_TYPE=${config}")
|
||||
endif()
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
-S "${CMAKE_CURRENT_SOURCE_DIR}/subsystem-macros"
|
||||
-B "${_bin}"
|
||||
-G "${CMAKE_GENERATOR}"
|
||||
"-DCMAKE_MAKE_PROGRAM=${CMAKE_MAKE_PROGRAM}"
|
||||
"-DCMAKE_CXX_COMPILER=${EMBT_BCC64X}"
|
||||
"-DCASE=${case}"
|
||||
${_cfg_arg}
|
||||
RESULT_VARIABLE _rc OUTPUT_VARIABLE _o ERROR_VARIABLE _e)
|
||||
if(NOT _rc EQUAL 0)
|
||||
message(SEND_ERROR "CASE ${case}: configure failed:\n${_o}${_e}")
|
||||
return()
|
||||
endif()
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND} --build "${_bin}"
|
||||
RESULT_VARIABLE _rc OUTPUT_VARIABLE _o ERROR_VARIABLE _e)
|
||||
if(NOT _rc EQUAL 0)
|
||||
message(SEND_ERROR
|
||||
"CASE ${case}: build failed -- a target compiled with the wrong "
|
||||
"__CONSOLE__ state:\n${_o}${_e}")
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# Plain bool: console gets __CONSOLE__, GUI does not.
|
||||
_subsystem_build(plain "")
|
||||
# Genex WIN32_EXECUTABLE ($<CONFIG:Release>): GUI in a Release build, so it must
|
||||
# not get __CONSOLE__ -- catches a non-genex read that would pick console.
|
||||
_subsystem_build(genex "Release")
|
||||
@@ -0,0 +1,14 @@
|
||||
cmake_minimum_required(VERSION 3.23)
|
||||
project(embt_subsystem CXX)
|
||||
|
||||
if(NOT DEFINED CASE OR CASE STREQUAL "plain")
|
||||
add_executable(console console.cpp) # console (default subsystem)
|
||||
add_executable(gui WIN32 gui.cpp) # GUI subsystem
|
||||
elseif(CASE STREQUAL "genex")
|
||||
# WIN32_EXECUTABLE as a per-config genex: GUI in Release, console otherwise.
|
||||
# Built in Release, so it is GUI and must NOT see __CONSOLE__ (gui.cpp asserts
|
||||
# that). A non-genex read of the property would pick console here and define
|
||||
# __CONSOLE__, tripping the #error -- so this locks compile==link per config.
|
||||
add_executable(genexgui gui.cpp)
|
||||
set_target_properties(genexgui PROPERTIES WIN32_EXECUTABLE "$<CONFIG:Release>")
|
||||
endif()
|
||||
@@ -0,0 +1,8 @@
|
||||
// A console target must be compiled with __CONSOLE__.
|
||||
#ifndef __CONSOLE__
|
||||
# error "console target compiled without __CONSOLE__"
|
||||
#endif
|
||||
int main()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
// A GUI (WIN32) target must NOT be compiled with __CONSOLE__.
|
||||
#ifdef __CONSOLE__
|
||||
# error "GUI target compiled with __CONSOLE__"
|
||||
#endif
|
||||
extern "C" int __stdcall WinMain(void*, void*, char*, int)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -1133,7 +1133,7 @@ def gen_check_build_system_targets(c, g, inSource):
|
||||
e["compileGroups"] = apple_exe_framework["compileGroups"]
|
||||
e["link"] = apple_exe_framework["link"]
|
||||
|
||||
if args.cxx_compiler_id in ['Clang', 'AppleClang', 'LCC', 'GNU', 'Intel', 'IntelLLVM', 'DPClang', 'MSVC', 'Embarcadero', 'CrayClang', 'IBMClang'] and g["name"] != "Xcode":
|
||||
if args.cxx_compiler_id in ['Clang', 'AppleClang', 'LCC', 'GNU', 'Intel', 'IntelLLVM', 'DPClang', 'MSVC', 'Embarcadero', 'CrayClang', 'EMBTClang', 'IBMClang'] and g["name"] != "Xcode":
|
||||
for e in expected:
|
||||
if e["name"] == "cxx_exe":
|
||||
if matches(g["name"], "^(Visual Studio |Ninja Multi-Config)"):
|
||||
|
||||
@@ -30,6 +30,8 @@ set(properties
|
||||
"VS_JUST_MY_CODE_DEBUGGING" "ON" "<SAME>"
|
||||
### OpenWatcom
|
||||
"WATCOM_RUNTIME_LIBRARY" "MultiThreaded" "<SAME>"
|
||||
### Embarcadero
|
||||
"EMBT_RUNTIME_LIBRARY" "Dynamic" "<SAME>"
|
||||
## Language
|
||||
### CUDA
|
||||
"CUDA_SEPARABLE_COMPILATION" "ON" "<SAME>"
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
include("${RunCMake_BINARY_DIR}/LINK_LIBRARY-CMP0156-NEW-build/LIBRARIES_PROCESSING.cmake")
|
||||
|
||||
if (CMAKE_C_LINK_LIBRARIES_PROCESSING MATCHES "ORDER=FORWARD")
|
||||
if (NOT actual_stdout MATCHES "(/|-)-PREFIXGROUP\"? +\"?(/|-)-LIBGROUP.*${LINK_SHARED_LIBRARY_PREFIX}base1${LINK_SHARED_LIBRARY_SUFFIX}\"? +\"?(/|-)-SUFFIXGROUP\"? +\"?(/|-)-LIBFLAG.*${LINK_SHARED_LIBRARY_PREFIX}base3${LINK_SHARED_LIBRARY_SUFFIX}\"? +\"?(/|-)-PREFIXGROUP\"? +\"?(/|-)-LIBGROUP.*${LINK_SHARED_LIBRARY_PREFIX}other1${LINK_SHARED_LIBRARY_SUFFIX}\"? +\"?(/|-)-SUFFIXGROUP")
|
||||
if (NOT actual_stdout MATCHES "(/|-)-PREFIXGROUP\"? +\"?(/|-)-LIBGROUP.*${LINK_SHARED_LIBRARY_PREFIX}base1${LINK_SHARED_LIBRARY_SUFFIX}\"? +\"?(/|-)-SUFFIXGROUP\"? +\"?(/|-)-LIBFLAG.*${LINK_SHARED_LIBRARY_PREFIX}base3${LINK_SHARED_LIBRARY_SUFFIX}\"? +\"?(/|-)-PREFIXGROUP\"? +\"?(/|-)-LIBGROUP.*other1${LINK_EXTERN_LIBRARY_SUFFIX}\"? +\"?(/|-)-SUFFIXGROUP")
|
||||
set (RunCMake_TEST_FAILED "Not found expected '--PREFIXGROUP --LIBGROUP<base1> --SUFFIXGROUP --LIBFLAG<base3> --PREFIXGROUP --LIBGROUP<other1> --SUFFIXGROUP'.")
|
||||
endif()
|
||||
else()
|
||||
|
||||
@@ -6,6 +6,10 @@ endif()
|
||||
project(SetLang)
|
||||
# force this to be verbose so I can debug a dashboard entry
|
||||
set(CMAKE_VERBOSE_MAKEFILE 1)
|
||||
if(CMAKE_C_COMPILER_ID MATCHES "(GNU|LCC|Clang|MSVC|Borland|Embarcadero|Intel|TI|XL)")
|
||||
set(have_explicit_language 1)
|
||||
cmake_policy(SET CMP0119 NEW)
|
||||
endif()
|
||||
add_library(foo foo.c)
|
||||
add_executable(SetLang bar.c)
|
||||
set_source_files_properties(foo.c bar.c PROPERTIES LANGUAGE CXX)
|
||||
@@ -23,8 +27,7 @@ if(CMAKE_GENERATOR MATCHES "^Visual Studio" AND "x${CMAKE_C_COMPILER_ID}" STREQU
|
||||
set_property(TARGET stay PROPERTY COMPILE_OPTIONS "-TP")
|
||||
endif()
|
||||
|
||||
if((CMAKE_C_COMPILER_ID MATCHES "(GNU|LCC|Clang|MSVC|Borland|Embarcadero|Intel|TI|XL)"))
|
||||
cmake_policy(SET CMP0119 NEW)
|
||||
if(have_explicit_language)
|
||||
add_library(zoom zoom.zzz)
|
||||
set_source_files_properties(zoom.zzz PROPERTIES LANGUAGE CXX)
|
||||
target_link_libraries(SetLang zoom)
|
||||
|
||||
Reference in new issue
Block a user