CMakeLists.txt 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. cmake_minimum_required(VERSION 3.1.0)
  2. project(WriteCompilerDetectionHeader)
  3. set(CMAKE_INCLUDE_CURRENT_DIR ON)
  4. include(WriteCompilerDetectionHeader)
  5. include(CheckCXXSourceCompiles)
  6. get_property(cxx_known_features GLOBAL PROPERTY CMAKE_CXX_KNOWN_FEATURES)
  7. get_property(c_known_features GLOBAL PROPERTY CMAKE_C_KNOWN_FEATURES)
  8. write_compiler_detection_header(
  9. FILE "${CMAKE_CURRENT_BINARY_DIR}/test_compiler_detection.h"
  10. PREFIX TEST
  11. COMPILERS GNU Clang AppleClang MSVC SunPro Intel
  12. VERSION 3.1
  13. PROLOG "// something"
  14. EPILOG "// more"
  15. FEATURES
  16. ${cxx_known_features} ${c_known_features}
  17. )
  18. write_compiler_detection_header(
  19. FILE "${CMAKE_CURRENT_BINARY_DIR}/compiler_multi_files/multi_file_compiler_detection.h"
  20. PREFIX MULTI
  21. OUTPUT_FILES_VAR multi_files
  22. OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/compiler_multi_files/compiler_support"
  23. COMPILERS GNU Clang AppleClang MSVC SunPro Intel
  24. VERSION 3.1
  25. FEATURES
  26. ${cxx_known_features} ${c_known_features}
  27. )
  28. macro(set_defines target true_defs false_defs)
  29. set(defines)
  30. foreach(def ${true_defs})
  31. list(APPEND defines ${def}=1)
  32. endforeach()
  33. foreach(def ${false_defs})
  34. list(APPEND defines ${def}=0)
  35. endforeach()
  36. target_compile_definitions(${target}
  37. PRIVATE
  38. ${defines}
  39. EXPECTED_COMPILER_VERSION_MAJOR=${COMPILER_VERSION_MAJOR}
  40. EXPECTED_COMPILER_VERSION_MINOR=${COMPILER_VERSION_MINOR}
  41. EXPECTED_COMPILER_VERSION_PATCH=${COMPILER_VERSION_PATCH}
  42. )
  43. endmacro()
  44. # Only run the compiler detection header test for compilers with
  45. # detailed features tables, not just meta-features
  46. if (CMAKE_C_COMPILE_FEATURES)
  47. if(NOT CMAKE_C_COMPILER_ID MATCHES "^(Cray|PGI|XL|XLClang)$")
  48. set(C_expected_features ${CMAKE_C_COMPILE_FEATURES})
  49. list(FILTER C_expected_features EXCLUDE REGEX "^c_std_[0-9][0-9]")
  50. endif()
  51. endif()
  52. if (C_expected_features)
  53. string(REGEX REPLACE "^([0-9]+)\\.[0-9]+\\.[0-9]+.*" "\\1" COMPILER_VERSION_MAJOR "${CMAKE_C_COMPILER_VERSION}")
  54. string(REGEX REPLACE "^[0-9]+\\.([0-9]+)\\.[0-9]+.*" "\\1" COMPILER_VERSION_MINOR "${CMAKE_C_COMPILER_VERSION}")
  55. string(REGEX REPLACE "^[0-9]+\\.[0-9]+\\.([0-9]+).*" "\\1" COMPILER_VERSION_PATCH "${CMAKE_C_COMPILER_VERSION}")
  56. if (CMAKE_C_COMPILER_ID STREQUAL "GNU"
  57. OR (CMAKE_C_COMPILER_ID STREQUAL "Clang" AND NOT "x${CMAKE_CXX_SIMULATE_ID}" STREQUAL "xMSVC")
  58. OR CMAKE_C_COMPILER_ID STREQUAL "AppleClang"
  59. OR CMAKE_C_COMPILER_ID STREQUAL "Intel")
  60. add_executable(WriteCompilerDetectionHeader_C11 main.c)
  61. set_property(TARGET WriteCompilerDetectionHeader_C11 PROPERTY C_STANDARD 11)
  62. set_defines(WriteCompilerDetectionHeader_C11 "EXPECTED_COMPILER_C_FUNCTION_PROTOTYPES;EXPECTED_COMPILER_C_RESTRICT" "")
  63. add_executable(WriteCompilerDetectionHeader_C11_multi main_multi.c)
  64. set_property(TARGET WriteCompilerDetectionHeader_C11_multi PROPERTY C_STANDARD 11)
  65. set_defines(WriteCompilerDetectionHeader_C11_multi "EXPECTED_COMPILER_C_FUNCTION_PROTOTYPES;EXPECTED_COMPILER_C_RESTRICT" "")
  66. target_include_directories(WriteCompilerDetectionHeader_C11_multi PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/compiler_multi_files)
  67. add_executable(C_undefined c_undefined.c)
  68. set_property(TARGET C_undefined PROPERTY C_STANDARD 90)
  69. include(CheckCCompilerFlag)
  70. check_c_compiler_flag(-Werror=undef use_error_undef)
  71. if (use_error_undef)
  72. target_compile_options(C_undefined PRIVATE -Werror=undef)
  73. endif()
  74. add_executable(WriteCompilerDetectionHeader_C main.c)
  75. set_property(TARGET WriteCompilerDetectionHeader_C PROPERTY C_STANDARD 90)
  76. set_defines(WriteCompilerDetectionHeader_C "EXPECTED_COMPILER_C_FUNCTION_PROTOTYPES" "EXPECTED_COMPILER_C_RESTRICT")
  77. add_executable(WriteCompilerDetectionHeader_C_multi main_multi.c)
  78. set_property(TARGET WriteCompilerDetectionHeader_C_multi PROPERTY C_STANDARD 90)
  79. set_defines(WriteCompilerDetectionHeader_C_multi "EXPECTED_COMPILER_C_FUNCTION_PROTOTYPES" "EXPECTED_COMPILER_C_RESTRICT")
  80. target_include_directories(WriteCompilerDetectionHeader_C_multi PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/compiler_multi_files)
  81. endif()
  82. endif()
  83. if (CMAKE_CXX_COMPILE_FEATURES)
  84. if(NOT CMAKE_CXX_COMPILER_ID MATCHES "^(Cray|PGI|XL|XLClang)$")
  85. set(CXX_expected_features ${CMAKE_CXX_COMPILE_FEATURES})
  86. list(FILTER CXX_expected_features EXCLUDE REGEX "^cxx_std_[0-9][0-9]")
  87. endif()
  88. endif()
  89. if (NOT CXX_expected_features)
  90. file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/dummy.cpp"
  91. "int main(int,char**) { return 0; }\n"
  92. )
  93. add_executable(WriteCompilerDetectionHeader "${CMAKE_CURRENT_BINARY_DIR}/dummy.cpp")
  94. if(UNIX OR NOT CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
  95. check_cxx_source_compiles("#include \"${CMAKE_CURRENT_BINARY_DIR}/test_compiler_detection.h\"\nint main() { return 0; }\n"
  96. file_include_works
  97. )
  98. if (file_include_works)
  99. message(SEND_ERROR "Inclusion of ${CMAKE_CURRENT_BINARY_DIR}/test_compiler_detection.h was expected to cause an error, but did not.")
  100. endif()
  101. endif()
  102. return()
  103. endif()
  104. string(REGEX REPLACE "^([0-9]+)\\.[0-9]+\\.[0-9]+.*" "\\1" COMPILER_VERSION_MAJOR "${CMAKE_CXX_COMPILER_VERSION}")
  105. string(REGEX REPLACE "^[0-9]+\\.([0-9]+)\\.[0-9]+.*" "\\1" COMPILER_VERSION_MINOR "${CMAKE_CXX_COMPILER_VERSION}")
  106. string(REGEX REPLACE "^[0-9]+\\.[0-9]+\\.([0-9]+).*" "\\1" COMPILER_VERSION_PATCH "${CMAKE_CXX_COMPILER_VERSION}")
  107. if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU"
  108. OR (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND NOT "x${CMAKE_CXX_SIMULATE_ID}" STREQUAL "xMSVC")
  109. OR CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang"
  110. OR CMAKE_CXX_COMPILER_ID STREQUAL "SunPro"
  111. OR CMAKE_CXX_COMPILER_ID STREQUAL "Intel")
  112. # False for C++98 mode.
  113. list(APPEND false_defs EXPECTED_COMPILER_CXX_DELEGATING_CONSTRUCTORS)
  114. list(APPEND false_defs EXPECTED_COMPILER_CXX_VARIADIC_TEMPLATES)
  115. endif()
  116. # for msvc the compiler version determines which c++11 features are available.
  117. if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC"
  118. OR (CMAKE_CXX_COMPILER_ID STREQUAL "Clang"
  119. AND "x${CMAKE_CXX_SIMULATE_ID}" STREQUAL "xMSVC"
  120. AND "x${CMAKE_CXX_COMPILER_FRONTEND_VARIANT}" STREQUAL "xMSVC" ))
  121. if(";${CMAKE_CXX_COMPILE_FEATURES};" MATCHES ";cxx_delegating_constructors;")
  122. list(APPEND true_defs EXPECTED_COMPILER_CXX_DELEGATING_CONSTRUCTORS)
  123. list(APPEND true_defs EXPECTED_COMPILER_CXX_VARIADIC_TEMPLATES)
  124. else()
  125. list(APPEND false_defs EXPECTED_COMPILER_CXX_DELEGATING_CONSTRUCTORS)
  126. list(APPEND false_defs EXPECTED_COMPILER_CXX_VARIADIC_TEMPLATES)
  127. endif()
  128. endif()
  129. add_executable(WriteCompilerDetectionHeader main.cpp)
  130. set_property(TARGET WriteCompilerDetectionHeader PROPERTY CXX_STANDARD 98)
  131. set_defines(WriteCompilerDetectionHeader "${true_defs}" "${false_defs}")
  132. add_executable(multi_files multi_files.cpp)
  133. set_property(TARGET multi_files PROPERTY CXX_STANDARD 98)
  134. target_include_directories(multi_files PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/compiler_multi_files)
  135. set_defines(multi_files "${true_defs}" "${false_defs}")
  136. if(MSVC)
  137. return() # MSVC has only one mode.
  138. endif()
  139. # Since GNU 4.7
  140. if (";${CMAKE_CXX_COMPILE_FEATURES};" MATCHES ";cxx_delegating_constructors;")
  141. list(APPEND true_defs EXPECTED_COMPILER_CXX_DELEGATING_CONSTRUCTORS)
  142. list(REMOVE_ITEM false_defs EXPECTED_COMPILER_CXX_DELEGATING_CONSTRUCTORS)
  143. endif()
  144. # Since GNU 4.4
  145. if (";${CMAKE_CXX_COMPILE_FEATURES};" MATCHES ";cxx_variadic_templates;")
  146. list(APPEND true_defs EXPECTED_COMPILER_CXX_VARIADIC_TEMPLATES)
  147. list(REMOVE_ITEM false_defs EXPECTED_COMPILER_CXX_VARIADIC_TEMPLATES)
  148. endif()
  149. add_executable(WriteCompilerDetectionHeader_11 main.cpp)
  150. set_property(TARGET WriteCompilerDetectionHeader_11 PROPERTY CXX_STANDARD 11)
  151. set_defines(WriteCompilerDetectionHeader_11 "${true_defs}" "${false_defs}")
  152. add_executable(multi_files_11 multi_files.cpp)
  153. set_property(TARGET multi_files_11 PROPERTY CXX_STANDARD 11)
  154. target_include_directories(multi_files_11 PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/compiler_multi_files)
  155. set_defines(multi_files_11 "${true_defs}" "${false_defs}")
  156. # test for ALLOW_UNKNOWN_COMPILERS
  157. # use a compiler does not match the current one,
  158. # so one always hits the fallback code
  159. if (CMAKE_CXX_COMPILER_ID STREQUAL "SunPro")
  160. set(OTHER_CXX "Intel")
  161. else()
  162. set(OTHER_CXX "SunPro")
  163. endif()
  164. write_compiler_detection_header(
  165. FILE "${CMAKE_CURRENT_BINARY_DIR}/test_compiler_detection_allow_unknown.h"
  166. PREFIX TEST
  167. COMPILERS ${OTHER_CXX}
  168. FEATURES cxx_nullptr
  169. ALLOW_UNKNOWN_COMPILERS
  170. )
  171. # intentionally abuse the TEST_NULLPTR variable: this will only work
  172. # with the fallback code.
  173. check_cxx_source_compiles("#include \"${CMAKE_CURRENT_BINARY_DIR}/test_compiler_detection_allow_unknown.h\"
  174. int main() {\n int i = TEST_NULLPTR;\n return 0; }\n"
  175. file_include_works_allow_unknown
  176. )
  177. if (NOT file_include_works_allow_unknown)
  178. message(SEND_ERROR "Inclusion of ${CMAKE_CURRENT_BINARY_DIR}/test_compiler_detection_allow_unknown.h was expected to work, but did not.")
  179. endif()
  180. # test for BARE_FEATURES
  181. write_compiler_detection_header(
  182. FILE "${CMAKE_CURRENT_BINARY_DIR}/test_compiler_detection_bare_features.h"
  183. PREFIX TEST
  184. COMPILERS GNU Clang AppleClang MSVC SunPro Intel
  185. VERSION 3.1
  186. BARE_FEATURES cxx_nullptr cxx_override cxx_noexcept cxx_final
  187. )
  188. add_executable(WriteCompilerDetectionHeaderBareFeatures main_bare.cpp)
  189. set_property(TARGET WriteCompilerDetectionHeaderBareFeatures PROPERTY CXX_STANDARD 11)