diff options
author | Brad King <brad.king@kitware.com> | 2017-02-01 14:21:44 (GMT) |
---|---|---|
committer | CMake Topic Stage <kwrobot@kitware.com> | 2017-02-01 14:21:44 (GMT) |
commit | 6f2e2c74ba7f9061be8a8831195f02db5604160a (patch) | |
tree | b60457daade4021ce688a9833cf992a1cdd5ae92 | |
parent | e8f55c17371ced4c6d5eb19cf40cf1141c0ef62a (diff) | |
parent | 1679fecb74ee4eb4500d591796f93fe4271b688e (diff) | |
download | CMake-6f2e2c74ba7f9061be8a8831195f02db5604160a.zip CMake-6f2e2c74ba7f9061be8a8831195f02db5604160a.tar.gz CMake-6f2e2c74ba7f9061be8a8831195f02db5604160a.tar.bz2 |
Merge topic 'WCDH_allow_unsupported'
1679fecb CompileFeatures Test: make sure the target "CompileFeatures" is always defined
98e6d1e5 Tests/Module/WCDH: make it work with only C features defined
c8703e9d WCDH: optionally omit error code for unknown compilers or compiler versions
0de9c398 WCDH: add macro to write simple replacement defines
-rw-r--r-- | Help/release/dev/WCDH_allow_unsupported.rst | 8 | ||||
-rw-r--r-- | Modules/WriteCompilerDetectionHeader.cmake | 122 | ||||
-rw-r--r-- | Tests/CompileFeatures/CMakeLists.txt | 18 | ||||
-rw-r--r-- | Tests/Module/WriteCompilerDetectionHeader/CMakeLists.txt | 128 |
4 files changed, 137 insertions, 139 deletions
diff --git a/Help/release/dev/WCDH_allow_unsupported.rst b/Help/release/dev/WCDH_allow_unsupported.rst new file mode 100644 index 0000000..c0b7377 --- /dev/null +++ b/Help/release/dev/WCDH_allow_unsupported.rst @@ -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. diff --git a/Modules/WriteCompilerDetectionHeader.cmake b/Modules/WriteCompilerDetectionHeader.cmake index ba249e1..0b16aa4 100644 --- a/Modules/WriteCompilerDetectionHeader.cmake +++ b/Modules/WriteCompilerDetectionHeader.cmake @@ -20,6 +20,8 @@ # [VERSION <version>] # [PROLOG <prolog>] # [EPILOG <epilog>] +# [ALLOW_UNKNOWN_COMPILERS] +# [ALLOW_UNKNOWN_COMPILER_VERSIONS] # ) # # The ``write_compiler_detection_header`` function generates the @@ -81,6 +83,11 @@ # See the :manual:`cmake-compile-features(7)` manual for information on # 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 # =================== # @@ -232,6 +239,19 @@ function(_load_compiler_variables CompilerId lang) set(_compiler_id_version_compute_${CompilerId} ${_compiler_id_version_compute} PARENT_SCOPE) endfunction() +macro(_simpledefine FEATURE_NAME FEATURE_TESTNAME FEATURE_STRING FEATURE_DEFAULT_STRING) + if (feature STREQUAL "${FEATURE_NAME}") + set(def_value "${prefix_arg}_${FEATURE_TESTNAME}") + string(APPEND file_content " +# if defined(${def_name}) && ${def_name} +# define ${def_value} ${FEATURE_STRING} +# else +# define ${def_value} ${FEATURE_DEFAULT_STRING} +# endif +\n") + endif() +endmacro() + function(write_compiler_detection_header file_keyword file_arg prefix_keyword prefix_arg @@ -242,7 +262,7 @@ function(write_compiler_detection_header if (NOT "x${prefix_keyword}" STREQUAL "xPREFIX") message(FATAL_ERROR "write_compiler_detection_header: PREFIX parameter missing.") endif() - set(options) + set(options ALLOW_UNKNOWN_COMPILERS ALLOW_UNKNOWN_COMPILER_VERSIONS) set(oneValueArgs VERSION EPILOG PROLOG OUTPUT_FILES_VAR OUTPUT_DIR) set(multiValueArgs COMPILERS FEATURES) cmake_parse_arguments(_WCD "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) @@ -426,10 +446,12 @@ function(write_compiler_detection_header set(compiler_file_content file_content) 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}}) # error Unsupported compiler version # endif\n") + endif() set(PREFIX ${prefix_arg}_) if (_need_hex_conversion) @@ -460,67 +482,36 @@ function(write_compiler_detection_header endforeach() endforeach() 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 # error Unsupported compiler # endif\n") + endif() endif() foreach(feature ${${_lang}_features}) string(TOUPPER ${feature} feature_upper) set(feature_PP "COMPILER_${feature_upper}") set(def_name ${prefix_arg}_${feature_PP}) - if (feature STREQUAL c_restrict) - set(def_value "${prefix_arg}_RESTRICT") - string(APPEND file_content " -# if ${def_name} -# define ${def_value} restrict -# else -# define ${def_value} -# endif -\n") - endif() - if (feature STREQUAL cxx_constexpr) - set(def_value "${prefix_arg}_CONSTEXPR") - string(APPEND file_content " -# if ${def_name} -# define ${def_value} constexpr -# else -# define ${def_value} -# endif -\n") - endif() - if (feature STREQUAL cxx_final) - set(def_value "${prefix_arg}_FINAL") - string(APPEND file_content " -# if ${def_name} -# define ${def_value} final -# else -# define ${def_value} -# endif -\n") - endif() - if (feature STREQUAL cxx_override) - set(def_value "${prefix_arg}_OVERRIDE") - string(APPEND file_content " -# if ${def_name} -# define ${def_value} override -# else -# define ${def_value} -# endif -\n") - endif() + _simpledefine(c_restrict RESTRICT restrict "") + _simpledefine(cxx_constexpr CONSTEXPR constexpr "") + _simpledefine(cxx_final FINAL final "") + _simpledefine(cxx_override OVERRIDE override "") if (feature STREQUAL cxx_static_assert) set(def_value "${prefix_arg}_STATIC_ASSERT(X)") set(def_value_msg "${prefix_arg}_STATIC_ASSERT_MSG(X, MSG)") 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_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() if (feature STREQUAL cxx_alignas) set(def_value "${prefix_arg}_ALIGNAS(X)") string(APPEND file_content " -# if ${def_name} +# if defined(${def_name}) && ${def_name} # define ${def_value} alignas(X) # elif ${prefix_arg}_COMPILER_IS_GNU || ${prefix_arg}_COMPILER_IS_Clang || ${prefix_arg}_COMPILER_IS_AppleClang # define ${def_value} __attribute__ ((__aligned__(X))) @@ -534,7 +525,7 @@ function(write_compiler_detection_header if (feature STREQUAL cxx_alignof) set(def_value "${prefix_arg}_ALIGNOF(X)") string(APPEND file_content " -# if ${def_name} +# if defined(${def_name}) && ${def_name} # define ${def_value} alignof(X) # elif ${prefix_arg}_COMPILER_IS_GNU || ${prefix_arg}_COMPILER_IS_Clang || ${prefix_arg}_COMPILER_IS_AppleClang # define ${def_value} __alignof__(X) @@ -543,30 +534,12 @@ function(write_compiler_detection_header # endif \n") endif() - if (feature STREQUAL cxx_deleted_functions) - set(def_value "${prefix_arg}_DELETED_FUNCTION") - string(APPEND file_content " -# if ${def_name} -# define ${def_value} = delete -# else -# define ${def_value} -# endif -\n") - endif() - if (feature STREQUAL cxx_extern_templates) - set(def_value "${prefix_arg}_EXTERN_TEMPLATE") - string(APPEND file_content " -# if ${def_name} -# define ${def_value} extern -# else -# define ${def_value} -# endif -\n") - endif() + _simpledefine(cxx_deleted_functions DELETED_FUNCTION "= delete" "") + _simpledefine(cxx_extern_templates EXTERN_TEMPLATE extern "") if (feature STREQUAL cxx_noexcept) set(def_value "${prefix_arg}_NOEXCEPT") string(APPEND file_content " -# if ${def_name} +# if defined(${def_name}) && ${def_name} # define ${def_value} noexcept # define ${def_value}_EXPR(X) noexcept(X) # else @@ -575,20 +548,11 @@ function(write_compiler_detection_header # endif \n") endif() - if (feature STREQUAL cxx_nullptr) - set(def_value "${prefix_arg}_NULLPTR") - string(APPEND file_content " -# if ${def_name} -# define ${def_value} nullptr -# else -# define ${def_value} 0 -# endif -\n") - endif() + _simpledefine(cxx_nullptr NULLPTR nullptr 0) if (feature STREQUAL cxx_thread_local) set(def_value "${prefix_arg}_THREAD_LOCAL") string(APPEND file_content " -# if ${def_name} +# if defined(${def_name}) && ${def_name} # define ${def_value} thread_local # elif ${prefix_arg}_COMPILER_IS_GNU || ${prefix_arg}_COMPILER_IS_Clang || ${prefix_arg}_COMPILER_IS_AppleClang # define ${def_value} __thread @@ -604,7 +568,7 @@ function(write_compiler_detection_header set(def_value "${prefix_arg}_DEPRECATED") string(APPEND file_content " # ifndef ${def_value} -# if ${def_name} +# if defined(${def_name}) && ${def_name} # define ${def_value} [[deprecated]] # define ${def_value}_MSG(MSG) [[deprecated(MSG)]] # elif ${prefix_arg}_COMPILER_IS_GNU || ${prefix_arg}_COMPILER_IS_Clang diff --git a/Tests/CompileFeatures/CMakeLists.txt b/Tests/CompileFeatures/CMakeLists.txt index 13aa86e..2a307d0 100644 --- a/Tests/CompileFeatures/CMakeLists.txt +++ b/Tests/CompileFeatures/CMakeLists.txt @@ -3,14 +3,6 @@ cmake_minimum_required(VERSION 3.1) project(CompileFeatures) -if (NOT CMAKE_C_COMPILE_FEATURES AND NOT CMAKE_CXX_COMPILE_FEATURES) - file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/dummy.cpp" - "int main(int,char**) { return 0; }\n" - ) - add_executable(CompileFeatures "${CMAKE_CURRENT_BINARY_DIR}/dummy.cpp") - return() -endif() - macro(run_test feature lang) if (";${CMAKE_${lang}_COMPILE_FEATURES};" MATCHES ${feature}) add_library(test_${feature} OBJECT ${feature}) @@ -277,8 +269,14 @@ if (CMAKE_CXX_COMPILE_FEATURES) endif() endif () -# these tests only work if at least cxx_auto_type is available -if (";${CMAKE_CXX_COMPILE_FEATURES};" MATCHES ";cxx_auto_type;") +# always add a target "CompileFeatures" +if (NOT ";${CMAKE_CXX_COMPILE_FEATURES};" MATCHES ";cxx_auto_type;") + file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/dummy.cpp" + "int main(int,char**) { return 0; }\n" + ) + add_executable(CompileFeatures "${CMAKE_CURRENT_BINARY_DIR}/dummy.cpp") +else() + # these tests only work if at least cxx_auto_type is available add_executable(CompileFeatures main.cpp) set_property(TARGET CompileFeatures PROPERTY COMPILE_FEATURES "cxx_auto_type" diff --git a/Tests/Module/WriteCompilerDetectionHeader/CMakeLists.txt b/Tests/Module/WriteCompilerDetectionHeader/CMakeLists.txt index 8b251d7..7957ab8 100644 --- a/Tests/Module/WriteCompilerDetectionHeader/CMakeLists.txt +++ b/Tests/Module/WriteCompilerDetectionHeader/CMakeLists.txt @@ -4,6 +4,7 @@ project(WriteCompilerDetectionHeader) set(CMAKE_INCLUDE_CURRENT_DIR ON) include(WriteCompilerDetectionHeader) +include(CheckCXXSourceCompiles) get_property(cxx_known_features GLOBAL PROPERTY CMAKE_CXX_KNOWN_FEATURES) get_property(c_known_features GLOBAL PROPERTY CMAKE_C_KNOWN_FEATURES) @@ -19,14 +20,63 @@ write_compiler_detection_header( ${cxx_known_features} ${c_known_features} ) -if (NOT CMAKE_CXX_COMPILE_FEATURES AND NOT CMAKE_C_COMPILE_FEATURES) +macro(set_defines target true_defs false_defs) + set(defines) + foreach(def ${true_defs}) + list(APPEND defines ${def}=1) + endforeach() + foreach(def ${false_defs}) + list(APPEND defines ${def}=0) + endforeach() + target_compile_definitions(${target} + PRIVATE + ${defines} + EXPECTED_COMPILER_VERSION_MAJOR=${COMPILER_VERSION_MAJOR} + EXPECTED_COMPILER_VERSION_MINOR=${COMPILER_VERSION_MINOR} + EXPECTED_COMPILER_VERSION_PATCH=${COMPILER_VERSION_PATCH} + ) +endmacro() + +if (CMAKE_C_COMPILE_FEATURES) + string(REGEX REPLACE "^([0-9]+)\\.[0-9]+\\.[0-9]+.*" "\\1" COMPILER_VERSION_MAJOR "${CMAKE_C_COMPILER_VERSION}") + string(REGEX REPLACE "^[0-9]+\\.([0-9]+)\\.[0-9]+.*" "\\1" COMPILER_VERSION_MINOR "${CMAKE_C_COMPILER_VERSION}") + string(REGEX REPLACE "^[0-9]+\\.[0-9]+\\.([0-9]+).*" "\\1" COMPILER_VERSION_PATCH "${CMAKE_C_COMPILER_VERSION}") + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" + OR CMAKE_C_COMPILER_ID STREQUAL "Clang" + OR CMAKE_C_COMPILER_ID STREQUAL "AppleClang" + OR CMAKE_C_COMPILER_ID STREQUAL "Intel") + add_executable(WriteCompilerDetectionHeader_C11 main.c) + set_property(TARGET WriteCompilerDetectionHeader_C11 PROPERTY C_STANDARD 11) + set_defines(WriteCompilerDetectionHeader_C11 "EXPECTED_COMPILER_C_FUNCTION_PROTOTYPES;EXPECTED_COMPILER_C_RESTRICT" "") + + add_executable(WriteCompilerDetectionHeader_C11_multi main_multi.c) + set_property(TARGET WriteCompilerDetectionHeader_C11_multi PROPERTY C_STANDARD 11) + 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) + + add_executable(C_undefined c_undefined.c) + set_property(TARGET C_undefined PROPERTY C_STANDARD 90) + target_compile_options(C_undefined PRIVATE -Werror=undef) + + add_executable(WriteCompilerDetectionHeader_C main.c) + set_property(TARGET WriteCompilerDetectionHeader_C PROPERTY C_STANDARD 90) + set_defines(WriteCompilerDetectionHeader_C "EXPECTED_COMPILER_C_FUNCTION_PROTOTYPES" "EXPECTED_COMPILER_C_RESTRICT") + + add_executable(WriteCompilerDetectionHeader_C_multi main_multi.c) + set_property(TARGET WriteCompilerDetectionHeader_C_multi PROPERTY C_STANDARD 90) + set_defines(WriteCompilerDetectionHeader_C_multi "EXPECTED_COMPILER_C_FUNCTION_PROTOTYPES" "EXPECTED_COMPILER_C_RESTRICT") + target_include_directories(WriteCompilerDetectionHeader_C_multi PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/compiler_multi_files) + endif() +endif() + +if (NOT CMAKE_CXX_COMPILE_FEATURES) file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/dummy.cpp" "int main(int,char**) { return 0; }\n" ) add_executable(WriteCompilerDetectionHeader "${CMAKE_CURRENT_BINARY_DIR}/dummy.cpp") 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" file_include_works ) @@ -41,23 +91,6 @@ string(REGEX REPLACE "^([0-9]+)\\.[0-9]+\\.[0-9]+.*" "\\1" COMPILER_VERSION_MAJO string(REGEX REPLACE "^[0-9]+\\.([0-9]+)\\.[0-9]+.*" "\\1" COMPILER_VERSION_MINOR "${CMAKE_CXX_COMPILER_VERSION}") string(REGEX REPLACE "^[0-9]+\\.[0-9]+\\.([0-9]+).*" "\\1" COMPILER_VERSION_PATCH "${CMAKE_CXX_COMPILER_VERSION}") -macro(set_defines target true_defs false_defs) - set(defines) - foreach(def ${true_defs}) - list(APPEND defines ${def}=1) - endforeach() - foreach(def ${false_defs}) - list(APPEND defines ${def}=0) - endforeach() - target_compile_definitions(${target} - PRIVATE - ${defines} - EXPECTED_COMPILER_VERSION_MAJOR=${COMPILER_VERSION_MAJOR} - EXPECTED_COMPILER_VERSION_MINOR=${COMPILER_VERSION_MINOR} - EXPECTED_COMPILER_VERSION_PATCH=${COMPILER_VERSION_PATCH} - ) -endmacro() - if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang" @@ -79,25 +112,6 @@ if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") endif() endif() -if (CMAKE_C_COMPILER_ID STREQUAL "GNU" - OR CMAKE_C_COMPILER_ID STREQUAL "Clang" - OR CMAKE_C_COMPILER_ID STREQUAL "AppleClang" - OR CMAKE_C_COMPILER_ID STREQUAL "Intel") - - add_executable(C_undefined c_undefined.c) - set_property(TARGET C_undefined PROPERTY C_STANDARD 90) - target_compile_options(C_undefined PRIVATE -Werror=undef) - - add_executable(WriteCompilerDetectionHeader_C main.c) - set_property(TARGET WriteCompilerDetectionHeader_C PROPERTY C_STANDARD 90) - set_defines(WriteCompilerDetectionHeader_C "EXPECTED_COMPILER_C_FUNCTION_PROTOTYPES" "EXPECTED_COMPILER_C_RESTRICT") - - add_executable(WriteCompilerDetectionHeader_C_multi main_multi.c) - set_property(TARGET WriteCompilerDetectionHeader_C_multi PROPERTY C_STANDARD 90) - set_defines(WriteCompilerDetectionHeader_C_multi "EXPECTED_COMPILER_C_FUNCTION_PROTOTYPES" "EXPECTED_COMPILER_C_RESTRICT") - target_include_directories(WriteCompilerDetectionHeader_C_multi PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/compiler_multi_files) -endif() - add_executable(WriteCompilerDetectionHeader main.cpp) set_property(TARGET WriteCompilerDetectionHeader PROPERTY CXX_STANDARD 98) set_defines(WriteCompilerDetectionHeader "${true_defs}" "${false_defs}") @@ -143,16 +157,30 @@ set_property(TARGET multi_files_11 PROPERTY CXX_STANDARD 11) target_include_directories(multi_files_11 PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/compiler_multi_files) set_defines(multi_files_11 "${true_defs}" "${false_defs}") -if (CMAKE_C_COMPILER_ID STREQUAL "GNU" - OR CMAKE_C_COMPILER_ID STREQUAL "Clang" - OR CMAKE_C_COMPILER_ID STREQUAL "AppleClang" - OR CMAKE_C_COMPILER_ID STREQUAL "Intel") - add_executable(WriteCompilerDetectionHeader_C11 main.c) - set_property(TARGET WriteCompilerDetectionHeader_C11 PROPERTY C_STANDARD 11) - set_defines(WriteCompilerDetectionHeader_C11 "EXPECTED_COMPILER_C_FUNCTION_PROTOTYPES;EXPECTED_COMPILER_C_RESTRICT" "") - - add_executable(WriteCompilerDetectionHeader_C11_multi main_multi.c) - set_property(TARGET WriteCompilerDetectionHeader_C11_multi PROPERTY C_STANDARD 11) - 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) +# 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() |