1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222
|
cmake_minimum_required(VERSION 3.1.0)
if(POLICY CMP0129)
cmake_policy(SET CMP0129 NEW)
endif()
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)
write_compiler_detection_header(
FILE "${CMAKE_CURRENT_BINARY_DIR}/test_compiler_detection.h"
PREFIX TEST
COMPILERS GNU Clang AppleClang MSVC SunPro Intel
VERSION 3.1
PROLOG "// something"
EPILOG "// more"
FEATURES
${cxx_known_features} ${c_known_features}
)
write_compiler_detection_header(
FILE "${CMAKE_CURRENT_BINARY_DIR}/compiler_multi_files/multi_file_compiler_detection.h"
PREFIX MULTI
OUTPUT_FILES_VAR multi_files
OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/compiler_multi_files/compiler_support"
COMPILERS GNU Clang AppleClang MSVC SunPro Intel
VERSION 3.1
FEATURES
${cxx_known_features} ${c_known_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()
# Only run the compiler detection header test for compilers with
# detailed features tables, not just meta-features
if (CMAKE_C_COMPILE_FEATURES)
if (NOT CMAKE_C_COMPILER_ID MATCHES "^(LCC|Cray|PGI|NVHPC|XL|XLClang|IBMClang|IntelLLVM|Fujitsu|FujitsuClang)$")
set(C_expected_features ${CMAKE_C_COMPILE_FEATURES})
list(FILTER C_expected_features EXCLUDE REGEX "^c_std_[0-9][0-9]")
endif()
endif()
if (C_expected_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" AND NOT "x${CMAKE_CXX_SIMULATE_ID}" STREQUAL "xMSVC")
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)
include(CheckCCompilerFlag)
check_c_compiler_flag(-Werror=undef use_error_undef)
if (use_error_undef)
target_compile_options(C_undefined PRIVATE -Werror=undef)
endif()
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 (CMAKE_CXX_COMPILE_FEATURES)
if (NOT CMAKE_CXX_COMPILER_ID MATCHES "^(LCC|Cray|PGI|NVHPC|XL|XLClang|IBMClang|IntelLLVM|Fujitsu|FujitsuClang)$")
set(CXX_expected_features ${CMAKE_CXX_COMPILE_FEATURES})
list(FILTER CXX_expected_features EXCLUDE REGEX "^cxx_std_[0-9][0-9]")
endif()
endif()
if (NOT CXX_expected_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")
check_cxx_source_compiles("#include \"${CMAKE_CURRENT_BINARY_DIR}/test_compiler_detection.h\"\nint main() { return 0; }\n"
file_include_works
)
if (file_include_works)
message(SEND_ERROR "Inclusion of ${CMAKE_CURRENT_BINARY_DIR}/test_compiler_detection.h was expected to cause an error, but did not.")
endif()
endif()
return()
endif()
string(REGEX REPLACE "^([0-9]+)\\.[0-9]+\\.[0-9]+.*" "\\1" COMPILER_VERSION_MAJOR "${CMAKE_CXX_COMPILER_VERSION}")
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}")
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU"
OR (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND NOT "x${CMAKE_CXX_SIMULATE_ID}" STREQUAL "xMSVC")
OR CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang"
OR CMAKE_CXX_COMPILER_ID STREQUAL "SunPro"
OR CMAKE_CXX_COMPILER_ID STREQUAL "Intel")
# False for C++98 mode.
list(APPEND false_defs EXPECTED_COMPILER_CXX_DELEGATING_CONSTRUCTORS)
list(APPEND false_defs EXPECTED_COMPILER_CXX_VARIADIC_TEMPLATES)
endif()
# for msvc the compiler version determines which c++11 features are available.
if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC"
OR (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND "x${CMAKE_CXX_SIMULATE_ID}" STREQUAL "xMSVC"))
if(";${CMAKE_CXX_COMPILE_FEATURES};" MATCHES ";cxx_delegating_constructors;")
list(APPEND true_defs EXPECTED_COMPILER_CXX_DELEGATING_CONSTRUCTORS)
list(APPEND true_defs EXPECTED_COMPILER_CXX_VARIADIC_TEMPLATES)
else()
list(APPEND false_defs EXPECTED_COMPILER_CXX_DELEGATING_CONSTRUCTORS)
list(APPEND false_defs EXPECTED_COMPILER_CXX_VARIADIC_TEMPLATES)
endif()
endif()
add_executable(WriteCompilerDetectionHeader main.cpp)
set_property(TARGET WriteCompilerDetectionHeader PROPERTY CXX_STANDARD 98)
set_defines(WriteCompilerDetectionHeader "${true_defs}" "${false_defs}")
add_executable(multi_files multi_files.cpp)
set_property(TARGET multi_files PROPERTY CXX_STANDARD 98)
target_include_directories(multi_files PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/compiler_multi_files)
set_defines(multi_files "${true_defs}" "${false_defs}")
if(MSVC)
return() # MSVC has only one mode.
endif()
# Since GNU 4.7
if (";${CMAKE_CXX_COMPILE_FEATURES};" MATCHES ";cxx_delegating_constructors;")
list(APPEND true_defs EXPECTED_COMPILER_CXX_DELEGATING_CONSTRUCTORS)
list(REMOVE_ITEM false_defs EXPECTED_COMPILER_CXX_DELEGATING_CONSTRUCTORS)
endif()
# Since GNU 4.4
if (";${CMAKE_CXX_COMPILE_FEATURES};" MATCHES ";cxx_variadic_templates;")
list(APPEND true_defs EXPECTED_COMPILER_CXX_VARIADIC_TEMPLATES)
list(REMOVE_ITEM false_defs EXPECTED_COMPILER_CXX_VARIADIC_TEMPLATES)
endif()
add_executable(WriteCompilerDetectionHeader_11 main.cpp)
set_property(TARGET WriteCompilerDetectionHeader_11 PROPERTY CXX_STANDARD 11)
set_defines(WriteCompilerDetectionHeader_11 "${true_defs}" "${false_defs}")
add_executable(multi_files_11 multi_files.cpp)
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}")
# 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_NULLPTR 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()
# test for BARE_FEATURES
write_compiler_detection_header(
FILE "${CMAKE_CURRENT_BINARY_DIR}/test_compiler_detection_bare_features.h"
PREFIX TEST
COMPILERS GNU Clang AppleClang MSVC SunPro Intel
VERSION 3.1
BARE_FEATURES cxx_nullptr cxx_override cxx_noexcept cxx_final
)
add_executable(WriteCompilerDetectionHeaderBareFeatures main_bare.cpp)
set_property(TARGET WriteCompilerDetectionHeaderBareFeatures PROPERTY CXX_STANDARD 11)
|