CMakeLists.txt 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419
  1. cmake_minimum_required(VERSION 3.1)
  2. project(CompileFeatures)
  3. if (NOT CMAKE_C_COMPILE_FEATURES AND NOT CMAKE_CXX_COMPILE_FEATURES)
  4. file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/dummy.cpp"
  5. "int main(int,char**) { return 0; }\n"
  6. )
  7. add_executable(CompileFeatures "${CMAKE_CURRENT_BINARY_DIR}/dummy.cpp")
  8. return()
  9. endif()
  10. macro(run_test feature lang)
  11. if (";${CMAKE_${lang}_COMPILE_FEATURES};" MATCHES ${feature})
  12. add_library(test_${feature} OBJECT ${feature})
  13. set_property(TARGET test_${feature}
  14. PROPERTY COMPILE_FEATURES "${feature}"
  15. )
  16. else()
  17. list(APPEND ${lang}_non_features ${feature})
  18. endif()
  19. endmacro()
  20. get_property(c_features GLOBAL PROPERTY CMAKE_C_KNOWN_FEATURES)
  21. foreach(feature ${c_features})
  22. run_test(${feature} C)
  23. endforeach()
  24. get_property(cxx_features GLOBAL PROPERTY CMAKE_CXX_KNOWN_FEATURES)
  25. foreach(feature ${cxx_features})
  26. run_test(${feature} CXX)
  27. endforeach()
  28. if (CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang"
  29. AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.1)
  30. # AppleClang prior to 5.1 does not set any preprocessor define to distinguish
  31. # c++1y from c++11, so CMake does not support c++1y features before AppleClang 5.1.
  32. list(REMOVE_ITEM CXX_non_features
  33. cxx_attribute_deprecated
  34. cxx_binary_literals
  35. )
  36. endif()
  37. if (CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang"
  38. AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.2)
  39. # AppleClang prior to 4.1 reports false for __has_feature(cxx_local_type_template_args)
  40. # and __has_feature(cxx_unrestricted_unions) but it happens to pass these tests.
  41. list(REMOVE_ITEM CXX_non_features
  42. cxx_local_type_template_args
  43. cxx_unrestricted_unions
  44. )
  45. endif()
  46. if (CMAKE_CXX_COMPILER_ID STREQUAL SunPro)
  47. list(REMOVE_ITEM CXX_non_features
  48. cxx_attribute_deprecated
  49. cxx_contextual_conversions
  50. cxx_extended_friend_declarations
  51. cxx_long_long_type
  52. cxx_sizeof_member
  53. cxx_variadic_macros
  54. )
  55. endif()
  56. if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU"
  57. AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.5)
  58. # The cxx_raw_string_literals feature happens to work in some distributions
  59. # of GNU 4.4, but it is first documented as available with GNU 4.5.
  60. list(REMOVE_ITEM CXX_non_features
  61. cxx_raw_string_literals
  62. )
  63. endif()
  64. if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU"
  65. AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.6)
  66. # The cxx_constexpr feature happens to work (for *this* testcase) with
  67. # GNU 4.5, but it is first documented as available with GNU 4.6.
  68. list(REMOVE_ITEM CXX_non_features
  69. cxx_constexpr
  70. )
  71. endif()
  72. if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU"
  73. AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.8)
  74. # The cxx_alignof feature happens to work (for *this* testcase) with
  75. # GNU 4.7, but it is first documented as available with GNU 4.8.
  76. list(REMOVE_ITEM CXX_non_features
  77. cxx_alignof
  78. )
  79. endif()
  80. if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU"
  81. AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.9)
  82. # GNU prior to 4.9 does not set any preprocessor define to distinguish
  83. # c++1y from c++11, so CMake does not support c++1y features before GNU 4.9.
  84. list(REMOVE_ITEM CXX_non_features
  85. # GNU 4.8 knows cxx_attributes, but doesn't know [[deprecated]]
  86. # and warns that it is unknown and ignored.
  87. cxx_attribute_deprecated
  88. cxx_binary_literals
  89. cxx_lambda_init_captures
  90. cxx_return_type_deduction
  91. )
  92. endif()
  93. if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
  94. if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 18.0)
  95. list(REMOVE_ITEM CXX_non_features
  96. # The cxx_contextual_conversions feature happens to work
  97. # (for *this* testcase) with VS 2010 and VS 2012, but
  98. # they do not document support until VS 2013.
  99. cxx_contextual_conversions
  100. )
  101. elseif (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 19.0)
  102. list(REMOVE_ITEM CXX_non_features
  103. # The cxx_deleted_functions and cxx_nonstatic_member_init
  104. # features happen to work (for *this* testcase) with VS 2013,
  105. # but they do not document support until VS 2015.
  106. cxx_deleted_functions
  107. cxx_nonstatic_member_init
  108. )
  109. endif()
  110. endif()
  111. if (CMAKE_CXX_COMPILER_ID STREQUAL "Intel")
  112. if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 16.0)
  113. if (CMAKE_CXX_COMIPLER_VERSION VERSION_EQUAL 15.0)
  114. list(REMOVE_ITEM CXX_non_features
  115. # The cxx_contextual_conversions feature happens to work
  116. # (for *this* testcase) with Intel 13/14/15, but they do not
  117. # document support until 16.
  118. cxx_contextual_conversions
  119. )
  120. elseif (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 14.0)
  121. list(REMOVE_ITEM CXX_non_features
  122. cxx_alignof
  123. # not supposed to work until 15
  124. cxx_attribute_deprecated
  125. # The cxx_contextual_conversions feature happens to work
  126. # (for *this* testcase) with Intel 13/14/15, but they do not
  127. # document support until 16.
  128. cxx_contextual_conversions
  129. )
  130. elseif (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 12.1)
  131. list(REMOVE_ITEM CXX_non_features
  132. # These features happen to work but aren't documented to
  133. # do so until 14.0
  134. cxx_constexpr
  135. cxx_enum_forward_declarations
  136. cxx_sizeof_member
  137. cxx_strong_enums
  138. cxx_unicode_literals
  139. # not supposed to work until 15
  140. cxx_attribute_deprecated
  141. cxx_nonstatic_member_init
  142. # The cxx_contextual_conversions feature happens to work
  143. # (for *this* testcase) with Intel 13/14/15, but they do not
  144. # document support until 16.
  145. cxx_contextual_conversions
  146. # This is an undocumented feature; it does not work in future versions
  147. cxx_aggregate_default_initializers
  148. )
  149. endif()
  150. endif()
  151. endif()
  152. set(C_ext c)
  153. set(C_standard_flag 11)
  154. set(CXX_ext cpp)
  155. set(CXX_standard_flag 14)
  156. foreach(lang CXX C)
  157. if (CMAKE_${lang}_COMPILE_FEATURES)
  158. foreach(feature ${${lang}_non_features})
  159. message("Testing feature : ${feature}")
  160. try_compile(${feature}_works
  161. "${CMAKE_CURRENT_BINARY_DIR}/${feature}_test"
  162. "${CMAKE_CURRENT_SOURCE_DIR}/feature_test.${${lang}_ext}"
  163. COMPILE_DEFINITIONS "-DTEST=${feature}.${${lang}_ext}"
  164. CMAKE_FLAGS "-DCMAKE_${lang}_STANDARD=${${lang}_standard_flag}"
  165. "-DINCLUDE_DIRECTORIES=${CMAKE_CURRENT_SOURCE_DIR}"
  166. OUTPUT_VARIABLE OUTPUT
  167. )
  168. if (${feature}_works)
  169. message(SEND_ERROR
  170. "Feature ${feature} expected not to work for ${lang} ${CMAKE_${lang}_COMPILER_ID}-${CMAKE_${lang}_COMPILER_VERSION}.
  171. Update the supported features or blacklist it.\n${OUTPUT}")
  172. else()
  173. message("Testing feature : ${feature} -- Fails, as expected.")
  174. endif()
  175. endforeach()
  176. endif()
  177. endforeach()
  178. if (CMAKE_C_COMPILE_FEATURES)
  179. if (CMAKE_C_STANDARD_DEFAULT)
  180. string(FIND "${CMAKE_C_FLAGS}" "-std=" std_flag_idx)
  181. if (std_flag_idx EQUAL -1)
  182. add_executable(default_dialect_C default_dialect.c)
  183. target_compile_definitions(default_dialect_C PRIVATE
  184. DEFAULT_C11=$<EQUAL:${CMAKE_C_STANDARD_DEFAULT},11>
  185. DEFAULT_C99=$<EQUAL:${CMAKE_C_STANDARD_DEFAULT},99>
  186. DEFAULT_C90=$<EQUAL:${CMAKE_C_STANDARD_DEFAULT},90>
  187. )
  188. endif()
  189. endif()
  190. add_executable(CompileFeaturesGenex_C genex_test.c)
  191. set_property(TARGET CompileFeaturesGenex_C PROPERTY C_STANDARD 11)
  192. if (CMAKE_C_COMPILER_ID STREQUAL "GNU")
  193. if (NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.6)
  194. list(APPEND expected_defs
  195. EXPECT_C_STATIC_ASSERT=1
  196. )
  197. else()
  198. list(APPEND expected_defs
  199. EXPECT_C_STATIC_ASSERT=0
  200. )
  201. endif()
  202. elseif(CMAKE_C_COMPILER_ID STREQUAL "Clang"
  203. OR CMAKE_C_COMPILER_ID STREQUAL "AppleClang")
  204. list(APPEND expected_defs
  205. EXPECT_C_STATIC_ASSERT=1
  206. )
  207. elseif (CMAKE_C_COMPILER_ID STREQUAL "Intel")
  208. if (NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 15)
  209. list(APPEND expected_defs
  210. EXPECT_C_STATIC_ASSERT=1
  211. )
  212. else()
  213. list(APPEND expected_defs
  214. EXPECT_C_STATIC_ASSERT=0
  215. )
  216. endif()
  217. endif()
  218. list(APPEND expected_defs
  219. EXPECT_C_FUNCTION_PROTOTYPES=1
  220. EXPECT_C_RESTRICT=1
  221. )
  222. target_compile_definitions(CompileFeaturesGenex_C PRIVATE
  223. HAVE_C_FUNCTION_PROTOTYPES=$<COMPILE_FEATURES:c_function_prototypes>
  224. HAVE_C_RESTRICT=$<COMPILE_FEATURES:c_restrict>
  225. HAVE_C_STATIC_ASSERT=$<COMPILE_FEATURES:c_static_assert>
  226. ${expected_defs}
  227. )
  228. endif()
  229. if (CMAKE_CXX_COMPILE_FEATURES)
  230. if (CMAKE_CXX_STANDARD_DEFAULT)
  231. string(FIND "${CMAKE_CXX_FLAGS}" "-std=" std_flag_idx)
  232. if (std_flag_idx EQUAL -1)
  233. add_executable(default_dialect default_dialect.cpp)
  234. target_compile_definitions(default_dialect PRIVATE
  235. DEFAULT_CXX14=$<EQUAL:${CMAKE_CXX_STANDARD_DEFAULT},14>
  236. DEFAULT_CXX11=$<EQUAL:${CMAKE_CXX_STANDARD_DEFAULT},11>
  237. DEFAULT_CXX98=$<EQUAL:${CMAKE_CXX_STANDARD_DEFAULT},98>
  238. )
  239. endif()
  240. endif()
  241. add_executable(CompileFeatures main.cpp)
  242. set_property(TARGET CompileFeatures
  243. PROPERTY COMPILE_FEATURES "cxx_auto_type"
  244. )
  245. set_property(TARGET CompileFeatures
  246. PROPERTY CXX_STANDARD_REQUIRED TRUE
  247. )
  248. add_executable(GenexCompileFeatures main.cpp)
  249. set_property(TARGET GenexCompileFeatures
  250. PROPERTY COMPILE_FEATURES "$<1:cxx_auto_type>;$<0:not_a_feature>"
  251. )
  252. add_library(iface INTERFACE)
  253. set_property(TARGET iface
  254. PROPERTY INTERFACE_COMPILE_FEATURES "cxx_auto_type"
  255. )
  256. add_executable(IfaceCompileFeatures main.cpp)
  257. target_link_libraries(IfaceCompileFeatures iface)
  258. if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
  259. if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.8)
  260. add_definitions(
  261. -DEXPECT_OVERRIDE_CONTROL=1
  262. -DEXPECT_INHERITING_CONSTRUCTORS=1
  263. -DEXPECT_FINAL=1
  264. -DEXPECT_INHERITING_CONSTRUCTORS_AND_FINAL=1
  265. )
  266. elseif (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.7)
  267. add_definitions(
  268. -DEXPECT_OVERRIDE_CONTROL=1
  269. -DEXPECT_INHERITING_CONSTRUCTORS=0
  270. -DEXPECT_FINAL=1
  271. -DEXPECT_INHERITING_CONSTRUCTORS_AND_FINAL=0
  272. )
  273. else()
  274. add_definitions(
  275. -DEXPECT_OVERRIDE_CONTROL=0
  276. -DEXPECT_INHERITING_CONSTRUCTORS=0
  277. -DEXPECT_FINAL=0
  278. -DEXPECT_INHERITING_CONSTRUCTORS_AND_FINAL=0
  279. )
  280. endif()
  281. elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
  282. add_definitions(
  283. -DEXPECT_OVERRIDE_CONTROL=1
  284. -DEXPECT_INHERITING_CONSTRUCTORS=1
  285. -DEXPECT_FINAL=1
  286. -DEXPECT_INHERITING_CONSTRUCTORS_AND_FINAL=1
  287. )
  288. elseif(CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
  289. if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.0)
  290. add_definitions(
  291. -DEXPECT_OVERRIDE_CONTROL=1
  292. -DEXPECT_INHERITING_CONSTRUCTORS=1
  293. -DEXPECT_FINAL=1
  294. -DEXPECT_INHERITING_CONSTRUCTORS_AND_FINAL=1
  295. )
  296. else()
  297. add_definitions(
  298. -DEXPECT_OVERRIDE_CONTROL=1
  299. -DEXPECT_INHERITING_CONSTRUCTORS=0
  300. -DEXPECT_FINAL=1
  301. -DEXPECT_INHERITING_CONSTRUCTORS_AND_FINAL=0
  302. )
  303. endif()
  304. elseif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
  305. if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 19.0)
  306. add_definitions(
  307. -DEXPECT_OVERRIDE_CONTROL=1
  308. -DEXPECT_INHERITING_CONSTRUCTORS=1
  309. -DEXPECT_FINAL=1
  310. -DEXPECT_INHERITING_CONSTRUCTORS_AND_FINAL=1
  311. )
  312. elseif(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 17.0)
  313. add_definitions(
  314. -DEXPECT_OVERRIDE_CONTROL=1
  315. -DEXPECT_INHERITING_CONSTRUCTORS=0
  316. -DEXPECT_FINAL=1
  317. -DEXPECT_INHERITING_CONSTRUCTORS_AND_FINAL=0
  318. )
  319. else()
  320. add_definitions(
  321. -DEXPECT_OVERRIDE_CONTROL=0
  322. -DEXPECT_INHERITING_CONSTRUCTORS=0
  323. -DEXPECT_FINAL=0
  324. -DEXPECT_INHERITING_CONSTRUCTORS_AND_FINAL=0
  325. )
  326. endif()
  327. elseif (CMAKE_CXX_COMPILER_ID STREQUAL "SunPro")
  328. add_definitions(
  329. -DEXPECT_OVERRIDE_CONTROL=1
  330. -DEXPECT_INHERITING_CONSTRUCTORS=1
  331. -DEXPECT_FINAL=1
  332. -DEXPECT_INHERITING_CONSTRUCTORS_AND_FINAL=1
  333. )
  334. elseif (CMAKE_CXX_COMPILER_ID STREQUAL "Intel")
  335. if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 15)
  336. add_definitions(
  337. -DEXPECT_OVERRIDE_CONTROL=1
  338. -DEXPECT_INHERITING_CONSTRUCTORS=1
  339. -DEXPECT_FINAL=1
  340. -DEXPECT_INHERITING_CONSTRUCTORS_AND_FINAL=1
  341. )
  342. elseif (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 14)
  343. add_definitions(
  344. -DEXPECT_OVERRIDE_CONTROL=1
  345. -DEXPECT_INHERITING_CONSTRUCTORS=0
  346. -DEXPECT_FINAL=1
  347. -DEXPECT_INHERITING_CONSTRUCTORS_AND_FINAL=0
  348. )
  349. else()
  350. add_definitions(
  351. -DEXPECT_OVERRIDE_CONTROL=0
  352. -DEXPECT_INHERITING_CONSTRUCTORS=0
  353. -DEXPECT_FINAL=0
  354. -DEXPECT_INHERITING_CONSTRUCTORS_AND_FINAL=0
  355. )
  356. endif()
  357. endif()
  358. add_executable(CompileFeaturesGenex genex_test.cpp)
  359. set_property(TARGET CompileFeaturesGenex PROPERTY CXX_STANDARD 11)
  360. target_compile_definitions(CompileFeaturesGenex PRIVATE
  361. HAVE_OVERRIDE_CONTROL=$<COMPILE_FEATURES:cxx_final,cxx_override>
  362. HAVE_AUTO_TYPE=$<COMPILE_FEATURES:cxx_auto_type>
  363. HAVE_INHERITING_CONSTRUCTORS=$<COMPILE_FEATURES:cxx_inheriting_constructors>
  364. HAVE_FINAL=$<COMPILE_FEATURES:cxx_final>
  365. HAVE_INHERITING_CONSTRUCTORS_AND_FINAL=$<COMPILE_FEATURES:cxx_inheriting_constructors,cxx_final>
  366. )
  367. add_executable(CompileFeaturesGenex2 genex_test.cpp)
  368. target_compile_features(CompileFeaturesGenex2 PRIVATE cxx_static_assert)
  369. target_compile_definitions(CompileFeaturesGenex2 PRIVATE
  370. HAVE_OVERRIDE_CONTROL=$<COMPILE_FEATURES:cxx_final,cxx_override>
  371. HAVE_AUTO_TYPE=$<COMPILE_FEATURES:cxx_auto_type>
  372. HAVE_INHERITING_CONSTRUCTORS=$<COMPILE_FEATURES:cxx_inheriting_constructors>
  373. HAVE_FINAL=$<COMPILE_FEATURES:cxx_final>
  374. HAVE_INHERITING_CONSTRUCTORS_AND_FINAL=$<COMPILE_FEATURES:cxx_inheriting_constructors,cxx_final>
  375. )
  376. add_library(static_assert_iface INTERFACE)
  377. target_compile_features(static_assert_iface INTERFACE cxx_static_assert)
  378. add_executable(CompileFeaturesGenex3 genex_test.cpp)
  379. target_link_libraries(CompileFeaturesGenex3 PRIVATE static_assert_iface)
  380. target_compile_definitions(CompileFeaturesGenex3 PRIVATE
  381. HAVE_OVERRIDE_CONTROL=$<COMPILE_FEATURES:cxx_final,cxx_override>
  382. HAVE_AUTO_TYPE=$<COMPILE_FEATURES:cxx_auto_type>
  383. HAVE_INHERITING_CONSTRUCTORS=$<COMPILE_FEATURES:cxx_inheriting_constructors>
  384. HAVE_FINAL=$<COMPILE_FEATURES:cxx_final>
  385. HAVE_INHERITING_CONSTRUCTORS_AND_FINAL=$<COMPILE_FEATURES:cxx_inheriting_constructors,cxx_final>
  386. )
  387. endif()