Merge topic 'embt-compiler'

e739170f15 EMBTClang: Add support for the Embarcadero bcc64x compiler
f29cfe2bf9 Borland: Do not identify Clang-based Embarcadero compilers
641d5321a7 Tests/Plugin: Fix symbol lookup with 64-bit Embarcadero compilers
cdfd0615b8 Tests/RunCMake/target_link_libraries-LINK_LIBRARY: Fix MinGW lld check
ab4d0130ed Tests/BundleUtilities: Fix test with Clang-based MinGW toolchains

Acked-by: Kitware Robot <kwrobot@kitware.com>
Merge-request: !11356
This commit is contained in:
Brad King authored and Kitware Robot committed 2026-11-02 10:05:36 -05:00
commit 35de7eca76
80 files changed
+1191 -29

No files matched your search

+11
View File
@@ -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}")
+1
View File
@@ -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
+1
View File
@@ -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
+26
View File
@@ -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``.
+9
View File
@@ -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.
+1
View File
@@ -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`_
+1
View File
@@ -47,6 +47,7 @@ function(compiler_id_detection outvar lang)
IntelLLVM
DPClang
PathScale
EMBTClang
Embarcadero
Borland
Watcom
+2 -2
View File
@@ -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)
+1 -1
View File
@@ -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)
+1 -1
View File
@@ -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.
+2 -1
View File
@@ -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 */
+4
View File
@@ -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)
+4
View File
@@ -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)
+19
View File
@@ -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)
+37
View File
@@ -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)
+140
View File
@@ -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()
+1
View File
@@ -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);
+57
View File
@@ -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 =
+4
View File
@@ -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",
+2
View File
@@ -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
)
+1 -1
View File
@@ -2,7 +2,7 @@
#ifndef framework_h
#define framework_h
#ifdef WIN32
#ifdef _WIN32
# ifdef framework_EXPORTS
# define FRAMEWORK_EXPORT __declspec(dllexport)
# else
+1 -1
View File
@@ -2,7 +2,7 @@
#ifndef shared_h
#define shared_h
#ifdef WIN32
#ifdef _WIN32
# ifdef shared_EXPORTS
# define SHARED_EXPORT __declspec(dllexport)
# else
+1 -1
View File
@@ -2,7 +2,7 @@
#ifndef shared2_h
#define shared2_h
#ifdef WIN32
#ifdef _WIN32
# ifdef shared2_EXPORTS
# define SHARED2_EXPORT __declspec(dllexport)
# else
+2 -2
View File
@@ -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");
+2 -2
View File
@@ -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");
+2 -2
View File
@@ -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")
+4
View File
@@ -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")
+66
View File
@@ -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()
+1
View File
@@ -0,0 +1 @@
#include "verify.h"
+1
View File
@@ -0,0 +1 @@
#include "verify.h"
+38
View File
@@ -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
+2 -1
View File
@@ -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)
+3 -1
View File
@@ -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()
+1 -1
View File
@@ -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();
+1
View File
@@ -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()
+3
View File
@@ -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")
+4
View File
@@ -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;
}
+1 -1
View File
@@ -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>"
@@ -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()
+5 -2
View File
@@ -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)