CMakeLists.txt 14 KB

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