mirror of
https://github.com/Kitware/CMake.git
synced 2026-01-04 04:40:56 -06:00
WCDH: optionally omit error code for unknown compilers or compiler versions
This allows one to generate a header that will basically always work. In case an unknown compiler or compiler version is encountered it simply falls back to the unsupported case.
This commit is contained in:
8
Help/release/dev/WCDH_allow_unsupported.rst
Normal file
8
Help/release/dev/WCDH_allow_unsupported.rst
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
WCDH_allow_unsupported
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
* The :module:`WriteCompilerDetectionHeader` module gained the
|
||||||
|
``ALLOW_UNKNOWN_COMPILERS`` and ``ALLOW_UNKNOWN_COMPILER_VERSIONS`` options
|
||||||
|
that allow creation of headers that will work also with unknown or old
|
||||||
|
compilers by simply assuming they do not support any of the requested
|
||||||
|
features.
|
||||||
@@ -20,6 +20,8 @@
|
|||||||
# [VERSION <version>]
|
# [VERSION <version>]
|
||||||
# [PROLOG <prolog>]
|
# [PROLOG <prolog>]
|
||||||
# [EPILOG <epilog>]
|
# [EPILOG <epilog>]
|
||||||
|
# [ALLOW_UNKNOWN_COMPILERS]
|
||||||
|
# [ALLOW_UNKNOWN_COMPILER_VERSIONS]
|
||||||
# )
|
# )
|
||||||
#
|
#
|
||||||
# The ``write_compiler_detection_header`` function generates the
|
# The ``write_compiler_detection_header`` function generates the
|
||||||
@@ -81,6 +83,11 @@
|
|||||||
# See the :manual:`cmake-compile-features(7)` manual for information on
|
# See the :manual:`cmake-compile-features(7)` manual for information on
|
||||||
# compile features.
|
# compile features.
|
||||||
#
|
#
|
||||||
|
# ``ALLOW_UNKNOWN_COMPILERS`` and ``ALLOW_UNKNOWN_COMPILER_VERSIONS`` cause
|
||||||
|
# the module to generate conditions that treat unknown compilers as simply
|
||||||
|
# lacking all features. Without these options the default behavior is to
|
||||||
|
# generate a ``#error`` for unknown compilers.
|
||||||
|
#
|
||||||
# Feature Test Macros
|
# Feature Test Macros
|
||||||
# ===================
|
# ===================
|
||||||
#
|
#
|
||||||
@@ -236,7 +243,7 @@ macro(_simpledefine FEATURE_NAME FEATURE_TESTNAME FEATURE_STRING FEATURE_DEFAULT
|
|||||||
if (feature STREQUAL "${FEATURE_NAME}")
|
if (feature STREQUAL "${FEATURE_NAME}")
|
||||||
set(def_value "${prefix_arg}_${FEATURE_TESTNAME}")
|
set(def_value "${prefix_arg}_${FEATURE_TESTNAME}")
|
||||||
string(APPEND file_content "
|
string(APPEND file_content "
|
||||||
# if ${def_name}
|
# if defined(${def_name}) && ${def_name}
|
||||||
# define ${def_value} ${FEATURE_STRING}
|
# define ${def_value} ${FEATURE_STRING}
|
||||||
# else
|
# else
|
||||||
# define ${def_value} ${FEATURE_DEFAULT_STRING}
|
# define ${def_value} ${FEATURE_DEFAULT_STRING}
|
||||||
@@ -255,7 +262,7 @@ function(write_compiler_detection_header
|
|||||||
if (NOT "x${prefix_keyword}" STREQUAL "xPREFIX")
|
if (NOT "x${prefix_keyword}" STREQUAL "xPREFIX")
|
||||||
message(FATAL_ERROR "write_compiler_detection_header: PREFIX parameter missing.")
|
message(FATAL_ERROR "write_compiler_detection_header: PREFIX parameter missing.")
|
||||||
endif()
|
endif()
|
||||||
set(options)
|
set(options ALLOW_UNKNOWN_COMPILERS ALLOW_UNKNOWN_COMPILER_VERSIONS)
|
||||||
set(oneValueArgs VERSION EPILOG PROLOG OUTPUT_FILES_VAR OUTPUT_DIR)
|
set(oneValueArgs VERSION EPILOG PROLOG OUTPUT_FILES_VAR OUTPUT_DIR)
|
||||||
set(multiValueArgs COMPILERS FEATURES)
|
set(multiValueArgs COMPILERS FEATURES)
|
||||||
cmake_parse_arguments(_WCD "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
cmake_parse_arguments(_WCD "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
||||||
@@ -439,10 +446,12 @@ function(write_compiler_detection_header
|
|||||||
set(compiler_file_content file_content)
|
set(compiler_file_content file_content)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(${compiler_file_content} "${${compiler_file_content}}
|
if(NOT _WCD_ALLOW_UNKNOWN_COMPILER_VERSIONS)
|
||||||
|
set(${compiler_file_content} "${${compiler_file_content}}
|
||||||
# if !(${_cmake_oldestSupported_${compiler}})
|
# if !(${_cmake_oldestSupported_${compiler}})
|
||||||
# error Unsupported compiler version
|
# error Unsupported compiler version
|
||||||
# endif\n")
|
# endif\n")
|
||||||
|
endif()
|
||||||
|
|
||||||
set(PREFIX ${prefix_arg}_)
|
set(PREFIX ${prefix_arg}_)
|
||||||
if (_need_hex_conversion)
|
if (_need_hex_conversion)
|
||||||
@@ -473,10 +482,15 @@ function(write_compiler_detection_header
|
|||||||
endforeach()
|
endforeach()
|
||||||
endforeach()
|
endforeach()
|
||||||
if(pp_if STREQUAL "elif")
|
if(pp_if STREQUAL "elif")
|
||||||
string(APPEND file_content "
|
if(_WCD_ALLOW_UNKNOWN_COMPILERS)
|
||||||
|
string(APPEND file_content "
|
||||||
|
# endif\n")
|
||||||
|
else()
|
||||||
|
string(APPEND file_content "
|
||||||
# else
|
# else
|
||||||
# error Unsupported compiler
|
# error Unsupported compiler
|
||||||
# endif\n")
|
# endif\n")
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
foreach(feature ${${_lang}_features})
|
foreach(feature ${${_lang}_features})
|
||||||
string(TOUPPER ${feature} feature_upper)
|
string(TOUPPER ${feature} feature_upper)
|
||||||
@@ -492,12 +506,12 @@ function(write_compiler_detection_header
|
|||||||
set(static_assert_struct "template<bool> struct ${prefix_arg}StaticAssert;\ntemplate<> struct ${prefix_arg}StaticAssert<true>{};\n")
|
set(static_assert_struct "template<bool> struct ${prefix_arg}StaticAssert;\ntemplate<> struct ${prefix_arg}StaticAssert<true>{};\n")
|
||||||
set(def_standard "# define ${def_value} static_assert(X, #X)\n# define ${def_value_msg} static_assert(X, MSG)")
|
set(def_standard "# define ${def_value} static_assert(X, #X)\n# define ${def_value_msg} static_assert(X, MSG)")
|
||||||
set(def_alternative "${static_assert_struct}# define ${def_value} sizeof(${prefix_arg}StaticAssert<X>)\n# define ${def_value_msg} sizeof(${prefix_arg}StaticAssert<X>)")
|
set(def_alternative "${static_assert_struct}# define ${def_value} sizeof(${prefix_arg}StaticAssert<X>)\n# define ${def_value_msg} sizeof(${prefix_arg}StaticAssert<X>)")
|
||||||
string(APPEND file_content "# if ${def_name}\n${def_standard}\n# else\n${def_alternative}\n# endif\n\n")
|
string(APPEND file_content "# if defined(${def_name}) && ${def_name}\n${def_standard}\n# else\n${def_alternative}\n# endif\n\n")
|
||||||
endif()
|
endif()
|
||||||
if (feature STREQUAL cxx_alignas)
|
if (feature STREQUAL cxx_alignas)
|
||||||
set(def_value "${prefix_arg}_ALIGNAS(X)")
|
set(def_value "${prefix_arg}_ALIGNAS(X)")
|
||||||
string(APPEND file_content "
|
string(APPEND file_content "
|
||||||
# if ${def_name}
|
# if defined(${def_name}) && ${def_name}
|
||||||
# define ${def_value} alignas(X)
|
# define ${def_value} alignas(X)
|
||||||
# elif ${prefix_arg}_COMPILER_IS_GNU || ${prefix_arg}_COMPILER_IS_Clang || ${prefix_arg}_COMPILER_IS_AppleClang
|
# elif ${prefix_arg}_COMPILER_IS_GNU || ${prefix_arg}_COMPILER_IS_Clang || ${prefix_arg}_COMPILER_IS_AppleClang
|
||||||
# define ${def_value} __attribute__ ((__aligned__(X)))
|
# define ${def_value} __attribute__ ((__aligned__(X)))
|
||||||
@@ -511,7 +525,7 @@ function(write_compiler_detection_header
|
|||||||
if (feature STREQUAL cxx_alignof)
|
if (feature STREQUAL cxx_alignof)
|
||||||
set(def_value "${prefix_arg}_ALIGNOF(X)")
|
set(def_value "${prefix_arg}_ALIGNOF(X)")
|
||||||
string(APPEND file_content "
|
string(APPEND file_content "
|
||||||
# if ${def_name}
|
# if defined(${def_name}) && ${def_name}
|
||||||
# define ${def_value} alignof(X)
|
# define ${def_value} alignof(X)
|
||||||
# elif ${prefix_arg}_COMPILER_IS_GNU || ${prefix_arg}_COMPILER_IS_Clang || ${prefix_arg}_COMPILER_IS_AppleClang
|
# elif ${prefix_arg}_COMPILER_IS_GNU || ${prefix_arg}_COMPILER_IS_Clang || ${prefix_arg}_COMPILER_IS_AppleClang
|
||||||
# define ${def_value} __alignof__(X)
|
# define ${def_value} __alignof__(X)
|
||||||
@@ -525,7 +539,7 @@ function(write_compiler_detection_header
|
|||||||
if (feature STREQUAL cxx_noexcept)
|
if (feature STREQUAL cxx_noexcept)
|
||||||
set(def_value "${prefix_arg}_NOEXCEPT")
|
set(def_value "${prefix_arg}_NOEXCEPT")
|
||||||
string(APPEND file_content "
|
string(APPEND file_content "
|
||||||
# if ${def_name}
|
# if defined(${def_name}) && ${def_name}
|
||||||
# define ${def_value} noexcept
|
# define ${def_value} noexcept
|
||||||
# define ${def_value}_EXPR(X) noexcept(X)
|
# define ${def_value}_EXPR(X) noexcept(X)
|
||||||
# else
|
# else
|
||||||
@@ -538,7 +552,7 @@ function(write_compiler_detection_header
|
|||||||
if (feature STREQUAL cxx_thread_local)
|
if (feature STREQUAL cxx_thread_local)
|
||||||
set(def_value "${prefix_arg}_THREAD_LOCAL")
|
set(def_value "${prefix_arg}_THREAD_LOCAL")
|
||||||
string(APPEND file_content "
|
string(APPEND file_content "
|
||||||
# if ${def_name}
|
# if defined(${def_name}) && ${def_name}
|
||||||
# define ${def_value} thread_local
|
# define ${def_value} thread_local
|
||||||
# elif ${prefix_arg}_COMPILER_IS_GNU || ${prefix_arg}_COMPILER_IS_Clang || ${prefix_arg}_COMPILER_IS_AppleClang
|
# elif ${prefix_arg}_COMPILER_IS_GNU || ${prefix_arg}_COMPILER_IS_Clang || ${prefix_arg}_COMPILER_IS_AppleClang
|
||||||
# define ${def_value} __thread
|
# define ${def_value} __thread
|
||||||
@@ -554,7 +568,7 @@ function(write_compiler_detection_header
|
|||||||
set(def_value "${prefix_arg}_DEPRECATED")
|
set(def_value "${prefix_arg}_DEPRECATED")
|
||||||
string(APPEND file_content "
|
string(APPEND file_content "
|
||||||
# ifndef ${def_value}
|
# ifndef ${def_value}
|
||||||
# if ${def_name}
|
# if defined(${def_name}) && ${def_name}
|
||||||
# define ${def_value} [[deprecated]]
|
# define ${def_value} [[deprecated]]
|
||||||
# define ${def_value}_MSG(MSG) [[deprecated(MSG)]]
|
# define ${def_value}_MSG(MSG) [[deprecated(MSG)]]
|
||||||
# elif ${prefix_arg}_COMPILER_IS_GNU || ${prefix_arg}_COMPILER_IS_Clang
|
# elif ${prefix_arg}_COMPILER_IS_GNU || ${prefix_arg}_COMPILER_IS_Clang
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ project(WriteCompilerDetectionHeader)
|
|||||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||||
|
|
||||||
include(WriteCompilerDetectionHeader)
|
include(WriteCompilerDetectionHeader)
|
||||||
|
include(CheckCXXSourceCompiles)
|
||||||
|
|
||||||
get_property(cxx_known_features GLOBAL PROPERTY CMAKE_CXX_KNOWN_FEATURES)
|
get_property(cxx_known_features GLOBAL PROPERTY CMAKE_CXX_KNOWN_FEATURES)
|
||||||
get_property(c_known_features GLOBAL PROPERTY CMAKE_C_KNOWN_FEATURES)
|
get_property(c_known_features GLOBAL PROPERTY CMAKE_C_KNOWN_FEATURES)
|
||||||
@@ -26,7 +27,6 @@ if (NOT CMAKE_CXX_COMPILE_FEATURES AND NOT CMAKE_C_COMPILE_FEATURES)
|
|||||||
add_executable(WriteCompilerDetectionHeader "${CMAKE_CURRENT_BINARY_DIR}/dummy.cpp")
|
add_executable(WriteCompilerDetectionHeader "${CMAKE_CURRENT_BINARY_DIR}/dummy.cpp")
|
||||||
|
|
||||||
if(UNIX OR NOT CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
if(UNIX OR NOT CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||||
include(CheckCXXSourceCompiles)
|
|
||||||
check_cxx_source_compiles("#include \"${CMAKE_CURRENT_BINARY_DIR}/test_compiler_detection.h\"\nint main() { return 0; }\n"
|
check_cxx_source_compiles("#include \"${CMAKE_CURRENT_BINARY_DIR}/test_compiler_detection.h\"\nint main() { return 0; }\n"
|
||||||
file_include_works
|
file_include_works
|
||||||
)
|
)
|
||||||
@@ -156,3 +156,31 @@ if (CMAKE_C_COMPILER_ID STREQUAL "GNU"
|
|||||||
set_defines(WriteCompilerDetectionHeader_C11_multi "EXPECTED_COMPILER_C_FUNCTION_PROTOTYPES;EXPECTED_COMPILER_C_RESTRICT" "")
|
set_defines(WriteCompilerDetectionHeader_C11_multi "EXPECTED_COMPILER_C_FUNCTION_PROTOTYPES;EXPECTED_COMPILER_C_RESTRICT" "")
|
||||||
target_include_directories(WriteCompilerDetectionHeader_C11_multi PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/compiler_multi_files)
|
target_include_directories(WriteCompilerDetectionHeader_C11_multi PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/compiler_multi_files)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# test for ALLOW_UNKNOWN_COMPILERS
|
||||||
|
|
||||||
|
# use a compiler does not match the current one,
|
||||||
|
# so one always hits the fallback code
|
||||||
|
if (CMAKE_CXX_COMPILER_ID STREQUAL "SunPro")
|
||||||
|
set(OTHER_CXX "Intel")
|
||||||
|
else()
|
||||||
|
set(OTHER_CXX "SunPro")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
write_compiler_detection_header(
|
||||||
|
FILE "${CMAKE_CURRENT_BINARY_DIR}/test_compiler_detection_allow_unknown.h"
|
||||||
|
PREFIX TEST
|
||||||
|
COMPILERS ${OTHER_CXX}
|
||||||
|
FEATURES cxx_nullptr
|
||||||
|
ALLOW_UNKNOWN_COMPILERS
|
||||||
|
)
|
||||||
|
|
||||||
|
# intentionally abuse the TEST_NULLPR variable: this will only work
|
||||||
|
# with the fallback code.
|
||||||
|
check_cxx_source_compiles("#include \"${CMAKE_CURRENT_BINARY_DIR}/test_compiler_detection_allow_unknown.h\"
|
||||||
|
int main() {\n int i = TEST_NULLPTR;\n return 0; }\n"
|
||||||
|
file_include_works_allow_unknown
|
||||||
|
)
|
||||||
|
if (NOT file_include_works_allow_unknown)
|
||||||
|
message(SEND_ERROR "Inclusion of ${CMAKE_CURRENT_BINARY_DIR}/test_compiler_detection_allow_unknown.h was expected to work, but did not.")
|
||||||
|
endif()
|
||||||
|
|||||||
Reference in New Issue
Block a user