WriteCompilerDetectionHeader.cmake 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648
  1. #.rst:
  2. # WriteCompilerDetectionHeader
  3. # ----------------------------
  4. #
  5. # This module provides the function write_compiler_detection_header().
  6. #
  7. # The ``WRITE_COMPILER_DETECTION_HEADER`` function can be used to generate
  8. # a file suitable for preprocessor inclusion which contains macros to be
  9. # used in source code::
  10. #
  11. # write_compiler_detection_header(
  12. # FILE <file>
  13. # PREFIX <prefix>
  14. # [OUTPUT_FILES_VAR <output_files_var> OUTPUT_DIR <output_dir>]
  15. # COMPILERS <compiler> [...]
  16. # FEATURES <feature> [...]
  17. # [VERSION <version>]
  18. # [PROLOG <prolog>]
  19. # [EPILOG <epilog>]
  20. # )
  21. #
  22. # The ``write_compiler_detection_header`` function generates the
  23. # file ``<file>`` with macros which all have the prefix ``<prefix>``.
  24. #
  25. # By default, all content is written directly to the ``<file>``. The
  26. # ``OUTPUT_FILES_VAR`` may be specified to cause the compiler-specific
  27. # content to be written to separate files. The separate files are then
  28. # available in the ``<output_files_var>`` and may be consumed by the caller
  29. # for installation for example. The ``OUTPUT_DIR`` specifies a relative
  30. # path from the main ``<file>`` to the compiler-specific files. For example:
  31. #
  32. # .. code-block:: cmake
  33. #
  34. # write_compiler_detection_header(
  35. # FILE climbingstats_compiler_detection.h
  36. # PREFIX ClimbingStats
  37. # OUTPUT_FILES_VAR support_files
  38. # OUTPUT_DIR compilers
  39. # COMPILERS GNU Clang
  40. # FEATURES cxx_variadic_templates
  41. # )
  42. # install(FILES
  43. # ${CMAKE_CURRENT_BINARY_DIR}/climbingstats_compiler_detection.h
  44. # DESTINATION include
  45. # )
  46. # install(FILES
  47. # ${support_files}
  48. # DESTINATION include/compilers
  49. # )
  50. #
  51. #
  52. # ``VERSION`` may be used to specify the API version to be generated.
  53. # Future versions of CMake may introduce alternative APIs. A given
  54. # API is selected by any ``<version>`` value greater than or equal
  55. # to the version of CMake that introduced the given API and less
  56. # than the version of CMake that introduced its succeeding API.
  57. # The value of the :variable:`CMAKE_MINIMUM_REQUIRED_VERSION`
  58. # variable is used if no explicit version is specified.
  59. # (As of CMake version |release| there is only one API version.)
  60. #
  61. # ``PROLOG`` may be specified as text content to write at the start of the
  62. # header. ``EPILOG`` may be specified as text content to write at the end
  63. # of the header
  64. #
  65. # At least one ``<compiler>`` and one ``<feature>`` must be listed. Compilers
  66. # which are known to CMake, but not specified are detected and a preprocessor
  67. # ``#error`` is generated for them. A preprocessor macro matching
  68. # ``<PREFIX>_COMPILER_IS_<compiler>`` is generated for each compiler
  69. # known to CMake to contain the value ``0`` or ``1``.
  70. #
  71. # Possible compiler identifiers are documented with the
  72. # :variable:`CMAKE_<LANG>_COMPILER_ID` variable.
  73. # Available features in this version of CMake are listed in the
  74. # :prop_gbl:`CMAKE_C_KNOWN_FEATURES` and
  75. # :prop_gbl:`CMAKE_CXX_KNOWN_FEATURES` global properties.
  76. #
  77. # See the :manual:`cmake-compile-features(7)` manual for information on
  78. # compile features.
  79. #
  80. # Feature Test Macros
  81. # ===================
  82. #
  83. # For each compiler, a preprocessor macro is generated matching
  84. # ``<PREFIX>_COMPILER_IS_<compiler>`` which has the content either ``0``
  85. # or ``1``, depending on the compiler in use. Preprocessor macros for
  86. # compiler version components are generated matching
  87. # ``<PREFIX>_COMPILER_VERSION_MAJOR`` ``<PREFIX>_COMPILER_VERSION_MINOR``
  88. # and ``<PREFIX>_COMPILER_VERSION_PATCH`` containing decimal values
  89. # for the corresponding compiler version components, if defined.
  90. #
  91. # A preprocessor test is generated based on the compiler version
  92. # denoting whether each feature is enabled. A preprocessor macro
  93. # matching ``<PREFIX>_COMPILER_<FEATURE>``, where ``<FEATURE>`` is the
  94. # upper-case ``<feature>`` name, is generated to contain the value
  95. # ``0`` or ``1`` depending on whether the compiler in use supports the
  96. # feature:
  97. #
  98. # .. code-block:: cmake
  99. #
  100. # write_compiler_detection_header(
  101. # FILE climbingstats_compiler_detection.h
  102. # PREFIX ClimbingStats
  103. # COMPILERS GNU Clang AppleClang
  104. # FEATURES cxx_variadic_templates
  105. # )
  106. #
  107. # .. code-block:: c++
  108. #
  109. # #if ClimbingStats_COMPILER_CXX_VARIADIC_TEMPLATES
  110. # template<typename... T>
  111. # void someInterface(T t...) { /* ... */ }
  112. # #else
  113. # // Compatibility versions
  114. # template<typename T1>
  115. # void someInterface(T1 t1) { /* ... */ }
  116. # template<typename T1, typename T2>
  117. # void someInterface(T1 t1, T2 t2) { /* ... */ }
  118. # template<typename T1, typename T2, typename T3>
  119. # void someInterface(T1 t1, T2 t2, T3 t3) { /* ... */ }
  120. # #endif
  121. #
  122. # Symbol Macros
  123. # =============
  124. #
  125. # Some additional symbol-defines are created for particular features for
  126. # use as symbols which may be conditionally defined empty:
  127. #
  128. # .. code-block:: c++
  129. #
  130. # class MyClass ClimbingStats_FINAL
  131. # {
  132. # ClimbingStats_CONSTEXPR int someInterface() { return 42; }
  133. # };
  134. #
  135. # The ``ClimbingStats_FINAL`` macro will expand to ``final`` if the
  136. # compiler (and its flags) support the ``cxx_final`` feature, and the
  137. # ``ClimbingStats_CONSTEXPR`` macro will expand to ``constexpr``
  138. # if ``cxx_constexpr`` is supported.
  139. #
  140. # The following features generate corresponding symbol defines:
  141. #
  142. # ========================== =================================== =================
  143. # Feature Define Symbol
  144. # ========================== =================================== =================
  145. # ``c_restrict`` ``<PREFIX>_RESTRICT`` ``restrict``
  146. # ``cxx_constexpr`` ``<PREFIX>_CONSTEXPR`` ``constexpr``
  147. # ``cxx_deleted_functions`` ``<PREFIX>_DELETED_FUNCTION`` ``= delete``
  148. # ``cxx_extern_templates`` ``<PREFIX>_EXTERN_TEMPLATE`` ``extern``
  149. # ``cxx_final`` ``<PREFIX>_FINAL`` ``final``
  150. # ``cxx_noexcept`` ``<PREFIX>_NOEXCEPT`` ``noexcept``
  151. # ``cxx_noexcept`` ``<PREFIX>_NOEXCEPT_EXPR(X)`` ``noexcept(X)``
  152. # ``cxx_override`` ``<PREFIX>_OVERRIDE`` ``override``
  153. # ========================== =================================== =================
  154. #
  155. # Compatibility Implementation Macros
  156. # ===================================
  157. #
  158. # Some features are suitable for wrapping in a macro with a backward
  159. # compatibility implementation if the compiler does not support the feature.
  160. #
  161. # When the ``cxx_static_assert`` feature is not provided by the compiler,
  162. # a compatibility implementation is available via the
  163. # ``<PREFIX>_STATIC_ASSERT(COND)`` and
  164. # ``<PREFIX>_STATIC_ASSERT_MSG(COND, MSG)`` function-like macros. The macros
  165. # expand to ``static_assert`` where that compiler feature is available, and
  166. # to a compatibility implementation otherwise. In the first form, the
  167. # condition is stringified in the message field of ``static_assert``. In
  168. # the second form, the message ``MSG`` is passed to the message field of
  169. # ``static_assert``, or ignored if using the backward compatibility
  170. # implementation.
  171. #
  172. # The ``cxx_attribute_deprecated`` feature provides a macro definition
  173. # ``<PREFIX>_DEPRECATED``, which expands to either the standard
  174. # ``[[deprecated]]`` attribute or a compiler-specific decorator such
  175. # as ``__attribute__((__deprecated__))`` used by GNU compilers.
  176. #
  177. # The ``cxx_alignas`` feature provides a macro definition
  178. # ``<PREFIX>_ALIGNAS`` which expands to either the standard ``alignas``
  179. # decorator or a compiler-specific decorator such as
  180. # ``__attribute__ ((__aligned__))`` used by GNU compilers.
  181. #
  182. # The ``cxx_alignof`` feature provides a macro definition
  183. # ``<PREFIX>_ALIGNOF`` which expands to either the standard ``alignof``
  184. # decorator or a compiler-specific decorator such as ``__alignof__``
  185. # used by GNU compilers.
  186. #
  187. # ============================= ================================ =====================
  188. # Feature Define Symbol
  189. # ============================= ================================ =====================
  190. # ``cxx_alignas`` ``<PREFIX>_ALIGNAS`` ``alignas``
  191. # ``cxx_alignof`` ``<PREFIX>_ALIGNOF`` ``alignof``
  192. # ``cxx_nullptr`` ``<PREFIX>_NULLPTR`` ``nullptr``
  193. # ``cxx_static_assert`` ``<PREFIX>_STATIC_ASSERT`` ``static_assert``
  194. # ``cxx_static_assert`` ``<PREFIX>_STATIC_ASSERT_MSG`` ``static_assert``
  195. # ``cxx_attribute_deprecated`` ``<PREFIX>_DEPRECATED`` ``[[deprecated]]``
  196. # ``cxx_attribute_deprecated`` ``<PREFIX>_DEPRECATED_MSG`` ``[[deprecated]]``
  197. # ``cxx_thread_local`` ``<PREFIX>_THREAD_LOCAL`` ``thread_local``
  198. # ============================= ================================ =====================
  199. #
  200. # A use-case which arises with such deprecation macros is the deprecation
  201. # of an entire library. In that case, all public API in the library may
  202. # be decorated with the ``<PREFIX>_DEPRECATED`` macro. This results in
  203. # very noisy build output when building the library itself, so the macro
  204. # may be may be defined to empty in that case when building the deprecated
  205. # library:
  206. #
  207. # .. code-block:: cmake
  208. #
  209. # add_library(compat_support ${srcs})
  210. # target_compile_definitions(compat_support
  211. # PRIVATE
  212. # CompatSupport_DEPRECATED=
  213. # )
  214. #=============================================================================
  215. # Copyright 2014 Stephen Kelly <[email protected]>
  216. #
  217. # Distributed under the OSI-approved BSD License (the "License");
  218. # see accompanying file Copyright.txt for details.
  219. #
  220. # This software is distributed WITHOUT ANY WARRANTY; without even the
  221. # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  222. # See the License for more information.
  223. #=============================================================================
  224. # (To distribute this file outside of CMake, substitute the full
  225. # License text for the above reference.)
  226. include(${CMAKE_CURRENT_LIST_DIR}/CMakeParseArguments.cmake)
  227. include(${CMAKE_CURRENT_LIST_DIR}/CMakeCompilerIdDetection.cmake)
  228. function(_load_compiler_variables CompilerId lang)
  229. include("${CMAKE_ROOT}/Modules/Compiler/${CompilerId}-${lang}-FeatureTests.cmake" OPTIONAL)
  230. set(_cmake_oldestSupported_${CompilerId} ${_cmake_oldestSupported} PARENT_SCOPE)
  231. foreach(feature ${ARGN})
  232. set(_cmake_feature_test_${CompilerId}_${feature} ${_cmake_feature_test_${feature}} PARENT_SCOPE)
  233. endforeach()
  234. include("${CMAKE_ROOT}/Modules/Compiler/${CompilerId}-${lang}-DetermineCompiler.cmake" OPTIONAL
  235. RESULT_VARIABLE determinedCompiler)
  236. if (NOT determinedCompiler)
  237. include("${CMAKE_ROOT}/Modules/Compiler/${CompilerId}-DetermineCompiler.cmake" OPTIONAL)
  238. endif()
  239. set(_compiler_id_version_compute_${CompilerId} ${_compiler_id_version_compute} PARENT_SCOPE)
  240. endfunction()
  241. function(write_compiler_detection_header
  242. file_keyword file_arg
  243. prefix_keyword prefix_arg
  244. )
  245. if (NOT file_keyword STREQUAL FILE)
  246. message(FATAL_ERROR "write_compiler_detection_header: FILE parameter missing.")
  247. endif()
  248. if (NOT prefix_keyword STREQUAL PREFIX)
  249. message(FATAL_ERROR "write_compiler_detection_header: PREFIX parameter missing.")
  250. endif()
  251. set(options)
  252. set(oneValueArgs VERSION EPILOG PROLOG OUTPUT_FILES_VAR OUTPUT_DIR)
  253. set(multiValueArgs COMPILERS FEATURES)
  254. cmake_parse_arguments(_WCD "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
  255. if (NOT _WCD_COMPILERS)
  256. message(FATAL_ERROR "Invalid arguments. write_compiler_detection_header requires at least one compiler.")
  257. endif()
  258. if (NOT _WCD_FEATURES)
  259. message(FATAL_ERROR "Invalid arguments. write_compiler_detection_header requires at least one feature.")
  260. endif()
  261. if(_WCD_UNPARSED_ARGUMENTS)
  262. message(FATAL_ERROR "Unparsed arguments: ${_WCD_UNPARSED_ARGUMENTS}")
  263. endif()
  264. if (prefix_arg STREQUAL "")
  265. message(FATAL_ERROR "A prefix must be specified")
  266. endif()
  267. string(MAKE_C_IDENTIFIER ${prefix_arg} cleaned_prefix)
  268. if (NOT prefix_arg STREQUAL cleaned_prefix)
  269. message(FATAL_ERROR "The prefix must be a valid C identifier.")
  270. endif()
  271. if(NOT _WCD_VERSION)
  272. set(_WCD_VERSION ${CMAKE_MINIMUM_REQUIRED_VERSION})
  273. endif()
  274. set(_min_version 3.1.0) # Version which introduced this function
  275. if (_WCD_VERSION VERSION_LESS _min_version)
  276. set(err "VERSION compatibility for write_compiler_detection_header is set to ${_WCD_VERSION}, which is too low.")
  277. set(err "${err} It must be set to at least ${_min_version}. ")
  278. set(err "${err} Either set the VERSION parameter to the write_compiler_detection_header function, or update")
  279. set(err "${err} your minimum required CMake version with the cmake_minimum_required command.")
  280. message(FATAL_ERROR "${err}")
  281. endif()
  282. if(_WCD_OUTPUT_FILES_VAR)
  283. if(NOT _WCD_OUTPUT_DIR)
  284. message(FATAL_ERROR "If OUTPUT_FILES_VAR is specified, then OUTPUT_DIR must also be specified.")
  285. endif()
  286. endif()
  287. if(_WCD_OUTPUT_DIR)
  288. if(NOT _WCD_OUTPUT_FILES_VAR)
  289. message(FATAL_ERROR "If OUTPUT_DIR is specified, then OUTPUT_FILES_VAR must also be specified.")
  290. endif()
  291. get_filename_component(main_file_dir ${file_arg} DIRECTORY)
  292. if (NOT IS_ABSOLUTE ${main_file_dir})
  293. set(main_file_dir "${CMAKE_CURRENT_BINARY_DIR}/${main_file_dir}")
  294. endif()
  295. if (NOT IS_ABSOLUTE ${_WCD_OUTPUT_DIR})
  296. set(_WCD_OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/${_WCD_OUTPUT_DIR}")
  297. endif()
  298. get_filename_component(out_file_dir ${_WCD_OUTPUT_DIR} ABSOLUTE)
  299. string(FIND ${out_file_dir} ${main_file_dir} idx)
  300. if (NOT idx EQUAL 0)
  301. message(FATAL_ERROR "The compiler-specific output directory must be within the same directory as the main file.")
  302. endif()
  303. if (main_file_dir STREQUAL out_file_dir)
  304. unset(_WCD_OUTPUT_DIR)
  305. else()
  306. string(REPLACE "${main_file_dir}/" "" _WCD_OUTPUT_DIR "${out_file_dir}/")
  307. endif()
  308. endif()
  309. set(compilers
  310. GNU
  311. Clang
  312. AppleClang
  313. )
  314. set(_hex_compilers ADSP Borland Embarcadero SunPro)
  315. foreach(_comp ${_WCD_COMPILERS})
  316. list(FIND compilers ${_comp} idx)
  317. if (idx EQUAL -1)
  318. message(FATAL_ERROR "Unsupported compiler ${_comp}.")
  319. endif()
  320. if (NOT _need_hex_conversion)
  321. list(FIND _hex_compilers ${_comp} idx)
  322. if (NOT idx EQUAL -1)
  323. set(_need_hex_conversion TRUE)
  324. endif()
  325. endif()
  326. endforeach()
  327. set(file_content "
  328. // This is a generated file. Do not edit!
  329. #ifndef ${prefix_arg}_COMPILER_DETECTION_H
  330. #define ${prefix_arg}_COMPILER_DETECTION_H
  331. ")
  332. if (_WCD_PROLOG)
  333. set(file_content "${file_content}\n${_WCD_PROLOG}\n")
  334. endif()
  335. if (_need_hex_conversion)
  336. set(file_content "${file_content}
  337. #define ${prefix_arg}_DEC(X) (X)
  338. #define ${prefix_arg}_HEX(X) ( \\
  339. ((X)>>28 & 0xF) * 10000000 + \\
  340. ((X)>>24 & 0xF) * 1000000 + \\
  341. ((X)>>20 & 0xF) * 100000 + \\
  342. ((X)>>16 & 0xF) * 10000 + \\
  343. ((X)>>12 & 0xF) * 1000 + \\
  344. ((X)>>8 & 0xF) * 100 + \\
  345. ((X)>>4 & 0xF) * 10 + \\
  346. ((X) & 0xF) \\
  347. )\n")
  348. endif()
  349. foreach(feature ${_WCD_FEATURES})
  350. if (feature MATCHES "^cxx_")
  351. list(APPEND _langs CXX)
  352. list(APPEND CXX_features ${feature})
  353. elseif (feature MATCHES "^c_")
  354. list(APPEND _langs C)
  355. list(APPEND C_features ${feature})
  356. else()
  357. message(FATAL_ERROR "Unsupported feature ${feature}.")
  358. endif()
  359. endforeach()
  360. list(REMOVE_DUPLICATES _langs)
  361. if(_WCD_OUTPUT_FILES_VAR)
  362. get_filename_component(main_file_name ${file_arg} NAME)
  363. set(compiler_file_content_
  364. "#ifndef ${prefix_arg}_COMPILER_DETECTION_H
  365. # error This file may only be included from ${main_file_name}
  366. #endif\n")
  367. endif()
  368. foreach(_lang ${_langs})
  369. get_property(known_features GLOBAL PROPERTY CMAKE_${_lang}_KNOWN_FEATURES)
  370. foreach(feature ${${_lang}_features})
  371. list(FIND known_features ${feature} idx)
  372. if (idx EQUAL -1)
  373. message(FATAL_ERROR "Unsupported feature ${feature}.")
  374. endif()
  375. endforeach()
  376. if(_lang STREQUAL CXX)
  377. set(file_content "${file_content}\n#ifdef __cplusplus\n")
  378. else()
  379. set(file_content "${file_content}\n#ifndef __cplusplus\n")
  380. endif()
  381. compiler_id_detection(ID_CONTENT ${_lang} PREFIX ${prefix_arg}_
  382. ID_DEFINE
  383. )
  384. set(file_content "${file_content}${ID_CONTENT}\n")
  385. set(pp_if "if")
  386. foreach(compiler ${_WCD_COMPILERS})
  387. _load_compiler_variables(${compiler} ${_lang} ${${_lang}_features})
  388. set(file_content "${file_content}\n# ${pp_if} ${prefix_arg}_COMPILER_IS_${compiler}\n")
  389. if(_WCD_OUTPUT_FILES_VAR)
  390. set(compile_file_name "${_WCD_OUTPUT_DIR}${prefix_arg}_COMPILER_INFO_${compiler}.h")
  391. set(file_content "${file_content}\n# include \"${compile_file_name}\"\n")
  392. endif()
  393. if(_WCD_OUTPUT_FILES_VAR)
  394. set(compiler_file_content compiler_file_content_${compiler})
  395. else()
  396. set(compiler_file_content file_content)
  397. endif()
  398. set(${compiler_file_content} "${${compiler_file_content}}
  399. # if !(${_cmake_oldestSupported_${compiler}})
  400. # error Unsupported compiler version
  401. # endif\n")
  402. set(PREFIX ${prefix_arg}_)
  403. if (_need_hex_conversion)
  404. set(MACRO_DEC ${prefix_arg}_DEC)
  405. set(MACRO_HEX ${prefix_arg}_HEX)
  406. else()
  407. set(MACRO_DEC)
  408. set(MACRO_HEX)
  409. endif()
  410. string(CONFIGURE "${_compiler_id_version_compute_${compiler}}" VERSION_BLOCK @ONLY)
  411. set(${compiler_file_content} "${${compiler_file_content}}${VERSION_BLOCK}\n")
  412. set(PREFIX)
  413. set(MACRO_DEC)
  414. set(MACRO_HEX)
  415. set(pp_if "elif")
  416. foreach(feature ${${_lang}_features})
  417. string(TOUPPER ${feature} feature_upper)
  418. set(feature_PP "COMPILER_${feature_upper}")
  419. set(_define_item "\n# define ${prefix_arg}_${feature_PP} 0\n")
  420. if (_cmake_feature_test_${compiler}_${feature} STREQUAL "1")
  421. set(_define_item "\n# define ${prefix_arg}_${feature_PP} 1\n")
  422. elseif (_cmake_feature_test_${compiler}_${feature})
  423. set(_define_item "\n# define ${prefix_arg}_${feature_PP} 0\n")
  424. set(_define_item "\n# if ${_cmake_feature_test_${compiler}_${feature}}\n# define ${prefix_arg}_${feature_PP} 1\n# else${_define_item}# endif\n")
  425. endif()
  426. set(${compiler_file_content} "${${compiler_file_content}}${_define_item}")
  427. endforeach()
  428. endforeach()
  429. if(pp_if STREQUAL "elif")
  430. set(file_content "${file_content}
  431. # else
  432. # error Unsupported compiler
  433. # endif\n")
  434. endif()
  435. foreach(feature ${${_lang}_features})
  436. string(TOUPPER ${feature} feature_upper)
  437. set(feature_PP "COMPILER_${feature_upper}")
  438. set(def_name ${prefix_arg}_${feature_PP})
  439. if (feature STREQUAL c_restrict)
  440. set(def_value "${prefix_arg}_RESTRICT")
  441. set(file_content "${file_content}
  442. # if ${def_name}
  443. # define ${def_value} restrict
  444. # else
  445. # define ${def_value}
  446. # endif
  447. \n")
  448. endif()
  449. if (feature STREQUAL cxx_constexpr)
  450. set(def_value "${prefix_arg}_CONSTEXPR")
  451. set(file_content "${file_content}
  452. # if ${def_name}
  453. # define ${def_value} constexpr
  454. # else
  455. # define ${def_value}
  456. # endif
  457. \n")
  458. endif()
  459. if (feature STREQUAL cxx_final)
  460. set(def_value "${prefix_arg}_FINAL")
  461. set(file_content "${file_content}
  462. # if ${def_name}
  463. # define ${def_value} final
  464. # else
  465. # define ${def_value}
  466. # endif
  467. \n")
  468. endif()
  469. if (feature STREQUAL cxx_override)
  470. set(def_value "${prefix_arg}_OVERRIDE")
  471. set(file_content "${file_content}
  472. # if ${def_name}
  473. # define ${def_value} override
  474. # else
  475. # define ${def_value}
  476. # endif
  477. \n")
  478. endif()
  479. if (feature STREQUAL cxx_static_assert)
  480. set(def_value "${prefix_arg}_STATIC_ASSERT(X)")
  481. set(def_value_msg "${prefix_arg}_STATIC_ASSERT_MSG(X, MSG)")
  482. set(static_assert_struct "template<bool> struct ${prefix_arg}StaticAssert;\ntemplate<> struct ${prefix_arg}StaticAssert<true>{};\n")
  483. set(def_standard "# define ${def_value} static_assert(X, #X)\n# define ${def_value_msg} static_assert(X, MSG)")
  484. set(def_alternative "${static_assert_struct}# define ${def_value} sizeof(${prefix_arg}StaticAssert<X>)\n# define ${def_value_msg} sizeof(${prefix_arg}StaticAssert<X>)")
  485. set(file_content "${file_content}# if ${def_name}\n${def_standard}\n# else\n${def_alternative}\n# endif\n\n")
  486. endif()
  487. if (feature STREQUAL cxx_alignas)
  488. set(def_value "${prefix_arg}_ALIGNAS(X)")
  489. set(file_content "${file_content}
  490. # if ${def_name}
  491. # define ${def_value} alignas(X)
  492. # elif ${prefix_arg}_COMPILER_IS_GNU || ${prefix_arg}_COMPILER_IS_Clang || ${prefix_arg}_COMPILER_IS_AppleClang
  493. # define ${def_value} __attribute__ ((__aligned__(X)))
  494. # else
  495. # define ${def_value}
  496. # endif
  497. \n")
  498. endif()
  499. if (feature STREQUAL cxx_alignof)
  500. set(def_value "${prefix_arg}_ALIGNOF(X)")
  501. set(file_content "${file_content}
  502. # if ${def_name}
  503. # define ${def_value} alignof(X)
  504. # elif ${prefix_arg}_COMPILER_IS_GNU || ${prefix_arg}_COMPILER_IS_Clang || ${prefix_arg}_COMPILER_IS_AppleClang
  505. # define ${def_value} __alignof__(X)
  506. # endif
  507. \n")
  508. endif()
  509. if (feature STREQUAL cxx_deleted_functions)
  510. set(def_value "${prefix_arg}_DELETED_FUNCTION")
  511. set(file_content "${file_content}
  512. # if ${def_name}
  513. # define ${def_value} = delete
  514. # else
  515. # define ${def_value}
  516. # endif
  517. \n")
  518. endif()
  519. if (feature STREQUAL cxx_extern_templates)
  520. set(def_value "${prefix_arg}_EXTERN_TEMPLATE")
  521. set(file_content "${file_content}
  522. # if ${def_name}
  523. # define ${def_value} extern
  524. # else
  525. # define ${def_value}
  526. # endif
  527. \n")
  528. endif()
  529. if (feature STREQUAL cxx_noexcept)
  530. set(def_value "${prefix_arg}_NOEXCEPT")
  531. set(file_content "${file_content}
  532. # if ${def_name}
  533. # define ${def_value} noexcept
  534. # define ${def_value}_EXPR(X) noexcept(X)
  535. # else
  536. # define ${def_value}
  537. # define ${def_value}_EXPR(X)
  538. # endif
  539. \n")
  540. endif()
  541. if (feature STREQUAL cxx_nullptr)
  542. set(def_value "${prefix_arg}_NULLPTR")
  543. set(file_content "${file_content}
  544. # if ${def_name}
  545. # define ${def_value} nullptr
  546. # else
  547. # define ${def_value} static_cast<void*>(0)
  548. # endif
  549. \n")
  550. endif()
  551. if (feature STREQUAL cxx_thread_local)
  552. set(def_value "${prefix_arg}_THREAD_LOCAL")
  553. set(file_content "${file_content}
  554. # if ${def_name}
  555. # define ${def_value} thread_local
  556. # elif ${prefix_arg}_COMPILER_IS_GNU || ${prefix_arg}_COMPILER_IS_Clang || ${prefix_arg}_COMPILER_IS_AppleClang
  557. # define ${def_value} __thread
  558. # elif ${prefix_arg}_COMPILER_IS_MSVC
  559. # define ${def_value} __declspec(thread)
  560. # else
  561. // ${def_value} not defined for this configuration.
  562. # endif
  563. \n")
  564. endif()
  565. if (feature STREQUAL cxx_attribute_deprecated)
  566. set(def_name ${prefix_arg}_${feature_PP})
  567. set(def_value "${prefix_arg}_DEPRECATED")
  568. set(file_content "${file_content}
  569. # ifndef ${def_value}
  570. # if ${def_name}
  571. # define ${def_value} [[deprecated]]
  572. # define ${def_value}_MSG(MSG) [[deprecated(MSG)]]
  573. # elif ${prefix_arg}_COMPILER_IS_GNU || ${prefix_arg}_COMPILER_IS_Clang
  574. # define ${def_value} __attribute__((__deprecated__))
  575. # define ${def_value}_MSG(MSG) __attribute__((__deprecated__(MSG)))
  576. # elif ${prefix_arg}_COMPILER_IS_MSVC
  577. # define ${def_value} __declspec(deprecated)
  578. # define ${def_value}_MSG(MSG) __declspec(deprecated(MSG))
  579. # else
  580. # define ${def_value}
  581. # define ${def_value}_MSG(MSG)
  582. # endif
  583. # endif
  584. \n")
  585. endif()
  586. endforeach()
  587. set(file_content "${file_content}#endif\n")
  588. endforeach()
  589. if(_WCD_OUTPUT_FILES_VAR)
  590. foreach(compiler ${_WCD_COMPILERS})
  591. set(CMAKE_CONFIGURABLE_FILE_CONTENT "${compiler_file_content_}")
  592. set(CMAKE_CONFIGURABLE_FILE_CONTENT "${CMAKE_CONFIGURABLE_FILE_CONTENT}${compiler_file_content_${compiler}}")
  593. set(compile_file_name "${_WCD_OUTPUT_DIR}${prefix_arg}_COMPILER_INFO_${compiler}.h")
  594. set(full_path "${main_file_dir}/${compile_file_name}")
  595. list(APPEND ${_WCD_OUTPUT_FILES_VAR} ${full_path})
  596. configure_file("${CMAKE_ROOT}/Modules/CMakeConfigurableFile.in"
  597. "${full_path}"
  598. @ONLY
  599. )
  600. endforeach()
  601. set(${_WCD_OUTPUT_FILES_VAR} ${${_WCD_OUTPUT_FILES_VAR}} PARENT_SCOPE)
  602. endif()
  603. if (_WCD_EPILOG)
  604. set(file_content "${file_content}\n${_WCD_EPILOG}\n")
  605. endif()
  606. set(file_content "${file_content}\n#endif")
  607. set(CMAKE_CONFIGURABLE_FILE_CONTENT ${file_content})
  608. configure_file("${CMAKE_ROOT}/Modules/CMakeConfigurableFile.in"
  609. "${file_arg}"
  610. @ONLY
  611. )
  612. endfunction()