Warning, /frameworks/extra-cmake-modules/modules/ECMGenerateExportHeader.cmake is written in an unsupported language. File is not indexed.
0001 # SPDX-FileCopyrightText: 2019 Friedrich W. H. Kossebau <kossebau@kde.org> 0002 # 0003 # SPDX-License-Identifier: BSD-3-Clause 0004 0005 #[=======================================================================[.rst: 0006 ECMGenerateExportHeader 0007 ----------------------- 0008 0009 This module provides the ``ecm_generate_export_header`` function for 0010 generating export macros for libraries with version-based control over 0011 visibility of and compiler warnings for deprecated API for the library user, 0012 as well as over excluding deprecated API and their implementation when 0013 building the library itself. 0014 0015 For preparing some values useful in the context it also provides a function 0016 ``ecm_export_header_format_version``. 0017 0018 :: 0019 0020 ecm_generate_export_header(<library_target_name> 0021 VERSION <version> 0022 [BASE_NAME <base_name>] 0023 [GROUP_BASE_NAME <group_base_name>] 0024 [EXPORT_MACRO_NAME <export_macro_name>] 0025 [EXPORT_FILE_NAME <export_file_name>] 0026 [DEPRECATED_MACRO_NAME <deprecated_macro_name>] 0027 [NO_EXPORT_MACRO_NAME <no_export_macro_name>] 0028 [INCLUDE_GUARD_NAME <include_guard_name>] 0029 [STATIC_DEFINE <static_define>] 0030 [PREFIX_NAME <prefix_name>] 0031 [DEPRECATED_BASE_VERSION <deprecated_base_version>] 0032 [DEPRECATION_VERSIONS <deprecation_version> [<deprecation_version2> [...]]] 0033 [EXCLUDE_DEPRECATED_BEFORE_AND_AT <exclude_deprecated_before_and_at_version>] 0034 [NO_BUILD_SET_DEPRECATED_WARNINGS_SINCE] 0035 [NO_DEFINITION_EXPORT_TO_BUILD_INTERFACE] 0036 [USE_VERSION_HEADER [<version_file_name>]] # Since 5.106 0037 [VERSION_BASE_NAME <version_base_name>] # Since 5.106 0038 [VERSION_MACRO_NAME <version_macro_name>] # Since 5.106 0039 [CUSTOM_CONTENT_FROM_VARIABLE <variable>] 0040 ) 0041 0042 ``VERSION`` specifies the version of the library, given in the format 0043 "<major>.<minor>.<patchlevel>". 0044 0045 ``GROUP_BASE_NAME`` specifies the name to use for the macros defining 0046 library group default values. If set, this will generate code supporting 0047 ``<group_base_name>_NO_DEPRECATED_WARNINGS``, 0048 ``<group_base_name>_DISABLE_DEPRECATED_BEFORE_AND_AT``, 0049 ``<group_base_name>_DEPRECATED_WARNINGS_SINCE`` and 0050 ``<group_base_name>_NO_DEPRECATED`` (see below). 0051 If not set, the generated code will ignore any such macros. 0052 0053 ``DEPRECATED_BASE_VERSION`` specifies the default version before and at which 0054 deprecated API is disabled. Possible values are "0", "CURRENT" (which 0055 resolves to <version>) and a version string in the format 0056 "<major>.<minor>.<patchlevel>". The default is the value of 0057 "<exclude_deprecated_before_and_at_version>" if set, or "<major>.0.0", with 0058 <major> taken from <version>. 0059 0060 ``DEPRECATION_VERSIONS`` specifies versions in "<major>.<minor>" format in 0061 which API was declared deprecated. Any version used with the generated 0062 macro ``<prefix_name><base_name>_DEPRECATED_VERSION(major, minor, text)`` 0063 or ``<prefix_name><base_name>_DEPRECATED_VERSION_BELATED(major, minor, textmajor, textminor, text)`` 0064 needs to be listed here, otherwise the macro will fail to work. 0065 0066 ``EXCLUDE_DEPRECATED_BEFORE_AND_AT`` specifies the version for which all API 0067 deprecated before and at should be excluded from the build completely. 0068 Possible values are "0" (default), "CURRENT" (which resolves to <version>) 0069 and a version string in the format "<major>.<minor>.<patchlevel>". 0070 0071 ``NO_BUILD_SET_DEPRECATED_WARNINGS_SINCE`` specifies that the definition 0072 ``<prefix_name><uppercase_base_name>_DEPRECATED_WARNINGS_SINCE`` will 0073 not be set for the library inside its own build, and thus will be defined 0074 by either explicit definition in the build system configuration or by the 0075 default value mechanism (see below). 0076 The default is that it is set for the build, to the version specified by 0077 ``EXCLUDE_DEPRECATED_BEFORE_AND_AT``, so no deprecation warnings are 0078 done for any own deprecated API used in the library implementation itself. 0079 0080 ``NO_DEFINITION_EXPORT_TO_BUILD_INTERFACE`` specifies that the definition 0081 ``<prefix_name><uppercase_base_name>_DISABLE_DEPRECATED_BEFORE_AND_AT`` will 0082 not be set in the public interface of the library inside its own build, and 0083 the same for the definition 0084 ``<prefix_name><uppercase_base_name>_DEPRECATED_WARNINGS_SINCE`` (if not 0085 disabled by ``NO_BUILD_SET_DEPRECATED_WARNINGS_SINCE`` already). 0086 The default is that they are set, to the version specified by 0087 ``EXCLUDE_DEPRECATED_BEFORE_AND_AT``, so e.g. test and examples part of the 0088 project automatically build against the full API included in the build and 0089 without any deprecation warnings for it. 0090 0091 ``USE_VERSION_HEADER`` defines whether a given header file 0092 ``<version_file_name>`` providing macros specifying the library version should 0093 be included in the generated header file. By default angle-brackets are used 0094 for the include statement. To generate includes with double quotes, add 0095 double quotes to the argument string (needs escaping), e.g. ``\"version.h\"``. 0096 The macro from the included version header holding the library version is 0097 given as ``<version_macro_name>`` by the argument ``VERSION_MACRO_NAME`` and 0098 used in the generated code for calculating defaults. If not specified, the 0099 defaults for the version file name and the version macro are derived from 0100 ``<version_base_name>`` as passed with ``VERSION_BASE_NAME``, which again 0101 defaults to ``<base_name>`` or otherwise ``<library_target_name>``. 0102 The macro name defaults to ``<uppercase_version_base_name>_VERSION``, 0103 the version file name to ``<lowercase_version_base_name>_version.h``. 0104 Since 5.106. 0105 0106 ``CUSTOM_CONTENT_FROM_VARIABLE`` specifies the name of a variable whose 0107 content will be appended at the end of the generated file, before any 0108 final inclusion guard closing. Note that before 5.98 this was broken and 0109 would only append the string passed as argument value. 0110 0111 The function ``ecm_generate_export_header`` defines C++ preprocessor macros 0112 in the generated export header, some for use in the sources of the library 0113 the header is generated for, other for use by projects linking agsinst the 0114 library. 0115 0116 The macros for use in the library C++ sources are these, next to those also 0117 defined by `GenerateExportHeader 0118 <https://cmake.org/cmake/help/latest/module/GenerateExportHeader.html>`_: 0119 0120 ``<prefix_name><uppercase_base_name>_DEPRECATED_VERSION(major, minor, text)`` 0121 to use to conditionally set a 0122 ``<prefix_name><uppercase_base_name>_DEPRECATED`` macro for a class, struct 0123 or function (other elements to be supported in future versions), depending 0124 on the visibility macro flags set (see below) 0125 0126 ``<prefix_name><uppercase_base_name>_DEPRECATED_VERSION_BELATED(major, minor, textmajor, textminor, text)`` 0127 to use to conditionally set a 0128 ``<prefix_name><uppercase_base_name>_DEPRECATED`` macro for a class, struct 0129 or function (other elements to be supported in future versions), depending 0130 on the visibility macro flags set (see below), with ``major`` & ``minor`` 0131 applied for the logic and ``textmajor`` & ``textminor`` for the warnings message. 0132 Useful for retroactive tagging of API for the compiler without injecting the 0133 API into the compiler warning conditions of already released versions. 0134 Since 5.71. 0135 0136 ``<prefix_name><uppercase_base_name>_ENUMERATOR_DEPRECATED_VERSION(major, minor, text)`` 0137 to use to conditionally set a 0138 ``<prefix_name><uppercase_base_name>_DEPRECATED`` macro for an enumerator, depending 0139 on the warnings macro flags set (see below). In builds using C++14 standard or earlier, 0140 where enumerator attributes are not yet supported, the macro will always yield an empty string. 0141 With MSVC it is also always an empty string for now. 0142 Since 5.82. 0143 0144 ``<prefix_name><uppercase_base_name>_ENUMERATOR_DEPRECATED_VERSION_BELATED(major, minor, textmajor, textminor, text)`` 0145 to use to conditionally set a 0146 ``<prefix_name><uppercase_base_name>_DEPRECATED`` macro for an enumerator, depending 0147 on the warnings macro flags set (see below), with ``major`` & ``minor`` 0148 applied for the logic and ``textmajor`` & ``textminor`` for the warnings message. 0149 In builds using C++14 standard or earlier, where enumerator attributes are not yet supported, 0150 the macro will always yield an empty string. 0151 Useful for retroactive tagging of API for the compiler without injecting the 0152 API into the compiler warning conditions of already released versions. 0153 With MSVC it is also always an empty string for now. 0154 Since 5.82. 0155 0156 ``<prefix_name><uppercase_base_name>_ENABLE_DEPRECATED_SINCE(major, minor)`` 0157 evaluates to ``TRUE`` or ``FALSE`` depending on the visibility macro flags 0158 set (see below). To be used mainly with ``#if``/``#endif`` to mark sections 0159 of code which should be included depending on the visibility requested. 0160 0161 ``<prefix_name><uppercase_base_name>_BUILD_DEPRECATED_SINCE(major, minor)`` 0162 evaluates to ``TRUE`` or ``FALSE`` depending on the value of 0163 ``EXCLUDE_DEPRECATED_BEFORE_AND_AT``. To be used mainly with 0164 ``#if``/``#endif`` to mark sections of two types of code: implementation 0165 code for deprecated API and declaration code of deprecated API which only 0166 may be disabled at build time of the library for BC reasons (e.g. virtual 0167 methods, see notes below). 0168 0169 ``<prefix_name><uppercase_base_name>_EXCLUDE_DEPRECATED_BEFORE_AND_AT`` 0170 holds the version used to exclude deprecated API at build time of the 0171 library. 0172 0173 The macros used to control visibility when building against the library are: 0174 0175 ``<prefix_name><uppercase_base_name>_DISABLE_DEPRECATED_BEFORE_AND_AT`` 0176 definition to set to a value in single hex number version notation 0177 (``0x<major><minor><patchlevel>``). 0178 0179 ``<prefix_name><uppercase_base_name>_NO_DEPRECATED`` 0180 flag to define to disable all deprecated API, being a shortcut for 0181 settings ``<prefix_name><uppercase_base_name>_DISABLE_DEPRECATED_BEFORE_AND_AT`` 0182 to the current version. If both are set, this flag overrules. 0183 0184 ``<prefix_name><uppercase_base_name>_DEPRECATED_WARNINGS_SINCE`` 0185 definition to set to a value in single hex number version notation 0186 (``0x<major><minor><patchlevel>``). Warnings will be only activated for 0187 API deprecated up to and including the version. If 0188 ``<prefix_name><uppercase_base_name>_DISABLE_DEPRECATED_BEFORE_AND_AT`` 0189 is set (directly or via the group default), it will default to that 0190 version, resulting in no warnings. Otherwise the default is the current 0191 version, resulting in warnings for all deprecated API. 0192 0193 ``<prefix_name><uppercase_base_name>_NO_DEPRECATED_WARNINGS`` 0194 flag to define to disable all deprecation warnings, being a shortcut for 0195 setting ``<prefix_name><uppercase_base_name>_DEPRECATED_WARNINGS_SINCE`` 0196 to "0". If both are set, this flag overrules. 0197 0198 When the ``GROUP_BASE_NAME`` has been used, the same macros but with the 0199 given ``<group_base_name>`` prefix are available to define the defaults of 0200 these macros, if not explicitly set. 0201 0202 .. warning:: 0203 The tricks applied here for hiding deprecated API to the compiler 0204 when building against a library do not work for all deprecated API: 0205 0206 * virtual methods need to stay visible to the compiler to build proper 0207 virtual method tables for subclasses 0208 * enumerators from enums cannot be simply removed, as this changes 0209 auto values of following enumerators, also can poke holes in enumerator 0210 series used as index into tables 0211 0212 In such cases the API can be only "hidden" at build time of the library, 0213 itself, by generated hard coded macro settings, using 0214 ``<prefix_name><uppercase_base_name>_BUILD_DEPRECATED_SINCE(major, minor)``. 0215 0216 Examples: 0217 0218 Preparing a library "Foo" created by target "foo", which is part of a group 0219 of libraries "Bar", where some API of "Foo" got deprecated at versions 0220 5.0 & 5.12: 0221 0222 .. code-block:: cmake 0223 0224 ecm_generate_export_header(foo 0225 GROUP_BASE_NAME BAR 0226 VERSION ${FOO_VERSION} 0227 DEPRECATION_VERSIONS 5.0 5.12 0228 ) 0229 0230 In the library "Foo" sources in the headers the API would be prepared like 0231 this, using the generated macros ``FOO_ENABLE_DEPRECATED_SINCE`` and 0232 ``FOO_DEPRECATED_VERSION``: 0233 0234 .. code-block:: cpp 0235 0236 #include <foo_export.h> 0237 0238 #if FOO_ENABLE_DEPRECATED_SINCE(5, 0) 0239 /** 0240 * @deprecated Since 5.0 0241 */ 0242 FOO_EXPORT 0243 FOO_DEPRECATED_VERSION(5, 0, "Use doFoo2()") 0244 void doFoo(); 0245 #endif 0246 0247 #if FOO_ENABLE_DEPRECATED_SINCE(5, 12) 0248 /** 0249 * @deprecated Since 5.12 0250 */ 0251 FOO_EXPORT 0252 FOO_DEPRECATED_VERSION(5, 12, "Use doBar2()") 0253 void doBar(); 0254 #endif 0255 0256 Projects linking against the "Foo" library can control which part of its 0257 deprecated API should be hidden to the compiler by adding a definition 0258 using the ``FOO_DISABLE_DEPRECATED_BEFORE_AND_AT`` macro variable set to the 0259 desired value (in version hex number notation): 0260 0261 .. code-block:: cmake 0262 0263 add_definitions(-DFOO_DISABLE_DEPRECATED_BEFORE_AND_AT=0x050000) 0264 0265 Or using the macro variable of the group: 0266 0267 .. code-block:: cmake 0268 0269 add_definitions(-DBAR_DISABLE_DEPRECATED_BEFORE_AND_AT=0x050000) 0270 0271 If both are specified, ``FOO_DISABLE_DEPRECATED_BEFORE_AND_AT`` will take 0272 precedence. 0273 0274 To build a variant of a library with some deprecated API completely left 0275 out from the build, not only optionally invisible to consumers, one uses the 0276 ``EXCLUDE_DEPRECATED_BEFORE_AND_AT`` parameter. This is best combined with a 0277 cached CMake variable. 0278 0279 .. code-block:: cmake 0280 0281 set(EXCLUDE_DEPRECATED_BEFORE_AND_AT 0 CACHE STRING "Control the range of deprecated API excluded from the build [default=0].") 0282 0283 ecm_generate_export_header(foo 0284 VERSION ${FOO_VERSION} 0285 EXCLUDE_DEPRECATED_BEFORE_AND_AT ${EXCLUDE_DEPRECATED_BEFORE_AND_AT} 0286 DEPRECATION_VERSIONS 5.0 5.12 0287 ) 0288 0289 The macros used in the headers for library consumers are reused for 0290 disabling the API excluded in the build of the library. For disabling the 0291 implementation of that API as well as for disabling deprecated API which 0292 only can be disabled at build time of the library for BC reasons, one 0293 uses the generated macro ``FOO_BUILD_DEPRECATED_SINCE``, like this: 0294 0295 .. code-block:: cpp 0296 0297 #include <foo_export.h> 0298 0299 enum Bars { 0300 One, 0301 #if FOO_BUILD_DEPRECATED_SINCE(5, 0) 0302 Two FOO_ENUMERATOR_DEPRECATED_VERSION(5, 0, "Use Three"), // macro available since 5.82 0303 #endif 0304 Three, 0305 }; 0306 0307 #if FOO_ENABLE_DEPRECATED_SINCE(5, 0) 0308 /** 0309 * @deprecated Since 5.0 0310 */ 0311 FOO_EXPORT 0312 FOO_DEPRECATED_VERSION(5, 0, "Use doFoo2()") 0313 void doFoo(); 0314 #endif 0315 0316 #if FOO_ENABLE_DEPRECATED_SINCE(5, 12) 0317 /** 0318 * @deprecated Since 5.12 0319 */ 0320 FOO_EXPORT 0321 FOO_DEPRECATED_VERSION(5, 12, "Use doBar2()") 0322 void doBar(); 0323 #endif 0324 0325 class FOO_EXPORT Foo { 0326 public: 0327 #if FOO_BUILD_DEPRECATED_SINCE(5, 0) 0328 /** 0329 * @deprecated Since 5.0 0330 */ 0331 FOO_DEPRECATED_VERSION(5, 0, "Feature removed") 0332 virtual void doWhat(); 0333 #endif 0334 }; 0335 0336 .. code-block:: cpp 0337 0338 #if FOO_BUILD_DEPRECATED_SINCE(5, 0) 0339 void doFoo() 0340 { 0341 // [...] 0342 } 0343 #endif 0344 0345 #if FOO_BUILD_DEPRECATED_SINCE(5, 12) 0346 void doBar() 0347 { 0348 // [...] 0349 } 0350 #endif 0351 0352 #if FOO_BUILD_DEPRECATED_SINCE(5, 0) 0353 void Foo::doWhat() 0354 { 0355 // [...] 0356 } 0357 #endif 0358 0359 So e.g. if ``EXCLUDE_DEPRECATED_BEFORE_AND_AT`` is set to "5.0.0", the 0360 enumerator ``Two`` as well as the methods ``::doFoo()`` and ``Foo::doWhat()`` 0361 will be not available to library consumers. The methods will not have been 0362 compiled into the library binary, and the declarations will be hidden to the 0363 compiler, ``FOO_DISABLE_DEPRECATED_BEFORE_AND_AT`` also cannot be used to 0364 reactivate them. 0365 0366 When using the ``NO_DEFINITION_EXPORT_TO_BUILD_INTERFACE`` and the project 0367 for the "Foo" library includes also tests and examples linking against the 0368 library and using deprecated API (like tests covering it), one better 0369 explicitly sets ``FOO_DISABLE_DEPRECATED_BEFORE_AND_AT`` for those targets 0370 to the version before and at which all deprecated API has been excluded from 0371 the build. 0372 Even more when building against other libraries from the same group "Bar" and 0373 disabling some deprecated API of those libraries using the group macro 0374 ``BAR_DISABLE_DEPRECATED_BEFORE_AND_AT``, which also works as default for 0375 ``FOO_DISABLE_DEPRECATED_BEFORE_AND_AT``. 0376 0377 To get the hex number style value the helper macro 0378 ``ecm_export_header_format_version()`` will be used: 0379 0380 .. code-block:: cmake 0381 0382 set(EXCLUDE_DEPRECATED_BEFORE_AND_AT 0 CACHE STRING "Control what part of deprecated API is excluded from build [default=0].") 0383 0384 ecm_generate_export_header(foo 0385 VERSION ${FOO_VERSION} 0386 GROUP_BASE_NAME BAR 0387 EXCLUDE_DEPRECATED_BEFORE_AND_AT ${EXCLUDE_DEPRECATED_BEFORE_AND_AT} 0388 NO_DEFINITION_EXPORT_TO_BUILD_INTERFACE 0389 DEPRECATION_VERSIONS 5.0 5.12 0390 ) 0391 0392 ecm_export_header_format_version(${EXCLUDE_DEPRECATED_BEFORE_AND_AT} 0393 CURRENT_VERSION ${FOO_VERSION} 0394 HEXNUMBER_VAR foo_no_deprecated_before_and_at 0395 ) 0396 0397 # disable all deprecated API up to 5.9.0 from all other libs of group "BAR" that we use ourselves 0398 add_definitions(-DBAR_DISABLE_DEPRECATED_BEFORE_AND_AT=0x050900) 0399 0400 add_executable(app app.cpp) 0401 target_link_libraries(app foo) 0402 target_compile_definitions(app 0403 PRIVATE "FOO_DISABLE_DEPRECATED_BEFORE_AND_AT=${foo_no_deprecated_before_and_at}") 0404 0405 Since 5.64.0. 0406 #]=======================================================================] 0407 0408 include(GenerateExportHeader) 0409 0410 cmake_policy(PUSH) 0411 cmake_policy(SET CMP0057 NEW) # if IN_LIST 0412 0413 # helper method 0414 function(_ecm_geh_generate_hex_number _var_name _version) 0415 set(_hexnumber 0) 0416 0417 set(version_regex "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$") 0418 string(REGEX REPLACE ${version_regex} "\\1" _version_major "${_version}") 0419 string(REGEX REPLACE ${version_regex} "\\2" _version_minor "${_version}") 0420 string(REGEX REPLACE ${version_regex} "\\3" _version_patch "${_version}") 0421 set(_outputformat) 0422 set(_outputformat OUTPUT_FORMAT HEXADECIMAL) 0423 math(EXPR _hexnumber "${_version_major}*65536 + ${_version_minor}*256 + ${_version_patch}" ${_outputformat}) 0424 set(${_var_name} ${_hexnumber} PARENT_SCOPE) 0425 endfunction() 0426 0427 function(ecm_export_header_format_version _version) 0428 set(options 0429 ) 0430 set(oneValueArgs 0431 CURRENT_VERSION 0432 STRING_VAR 0433 HEXNUMBER_VAR 0434 ) 0435 set(multiValueArgs 0436 ) 0437 cmake_parse_arguments(ARGS "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) 0438 0439 if (NOT ARGS_STRING_VAR AND NOT ARGS_HEXNUMBER_VAR) 0440 message(FATAL_ERROR "No STRING_VAR or HEXNUMBER_VAR passed when calling ecm_export_header_format_version().") 0441 endif() 0442 0443 if(_version STREQUAL "CURRENT") 0444 if (NOT ARGS_CURRENT_VERSION ) 0445 message(FATAL_ERROR "\"CURRENT\" as version value not supported when CURRENT_VERSION not passed on calling ecm_export_header_format_version().") 0446 endif() 0447 set(_version ${ARGS_CURRENT_VERSION}) 0448 endif() 0449 0450 if (ARGS_STRING_VAR) 0451 set(${ARGS_STRING_VAR} ${_version} PARENT_SCOPE) 0452 endif() 0453 0454 if (ARGS_HEXNUMBER_VAR) 0455 set(_hexnumber 0) # by default build all deprecated API 0456 if(_version) 0457 _ecm_geh_generate_hex_number(_hexnumber ${_version}) 0458 endif() 0459 set(${ARGS_HEXNUMBER_VAR} ${_hexnumber} PARENT_SCOPE) 0460 endif() 0461 endfunction() 0462 0463 0464 function(ecm_generate_export_header target) 0465 set(options 0466 NO_DEFINITION_EXPORT_TO_BUILD_INTERFACE 0467 NO_BUILD_SET_DEPRECATED_WARNINGS_SINCE 0468 ) 0469 set(oneValueArgs 0470 BASE_NAME 0471 GROUP_BASE_NAME 0472 EXPORT_FILE_NAME 0473 DEPRECATED_BASE_VERSION 0474 VERSION 0475 VERSION_BASE_NAME 0476 VERSION_MACRO_NAME 0477 EXCLUDE_DEPRECATED_BEFORE_AND_AT 0478 EXPORT_MACRO_NAME 0479 DEPRECATED_MACRO_NAME 0480 NO_EXPORT_MACRO_NAME 0481 INCLUDE_GUARD_NAME 0482 STATIC_DEFINE 0483 PREFIX_NAME 0484 CUSTOM_CONTENT_FROM_VARIABLE 0485 ) 0486 set(multiValueArgs 0487 DEPRECATION_VERSIONS 0488 USE_VERSION_HEADER 0489 ) 0490 cmake_parse_arguments(ARGS "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) 0491 0492 # helper string 0493 set(_version_triple_regexp "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$") 0494 # args sanity check 0495 if (NOT ARGS_VERSION) 0496 message(FATAL_ERROR "No VERSION passed when calling ecm_generate_export_header().") 0497 elseif(NOT ARGS_VERSION MATCHES ${_version_triple_regexp}) 0498 message(FATAL_ERROR "VERSION expected to be in x.y.z format when calling ecm_generate_export_header().") 0499 endif() 0500 if (NOT ARGS_EXCLUDE_DEPRECATED_BEFORE_AND_AT) 0501 set(ARGS_EXCLUDE_DEPRECATED_BEFORE_AND_AT 0) 0502 elseif(ARGS_EXCLUDE_DEPRECATED_BEFORE_AND_AT STREQUAL "CURRENT") 0503 set(ARGS_EXCLUDE_DEPRECATED_BEFORE_AND_AT ${ARGS_VERSION}) 0504 elseif(NOT ARGS_EXCLUDE_DEPRECATED_BEFORE_AND_AT MATCHES ${_version_triple_regexp} AND 0505 NOT ARGS_EXCLUDE_DEPRECATED_BEFORE_AND_AT STREQUAL "0") 0506 message(FATAL_ERROR "EXCLUDE_DEPRECATED_BEFORE_AND_AT expected to be in \"x.y.z\" format, \"0\" or \"CURRENT\" when calling ecm_generate_export_header().") 0507 endif() 0508 if (NOT DEFINED ARGS_DEPRECATED_BASE_VERSION) 0509 if (ARGS_EXCLUDE_DEPRECATED_BEFORE_AND_AT) 0510 set(ARGS_DEPRECATED_BASE_VERSION "${ARGS_EXCLUDE_DEPRECATED_BEFORE_AND_AT}") 0511 else() 0512 string(REGEX REPLACE ${_version_triple_regexp} "\\1" _version_major "${ARGS_VERSION}") 0513 set(ARGS_DEPRECATED_BASE_VERSION "${_version_major}.0.0") 0514 endif() 0515 else() 0516 if(ARGS_DEPRECATED_BASE_VERSION STREQUAL "CURRENT") 0517 set(ARGS_DEPRECATED_BASE_VERSION ${ARGS_VERSION}) 0518 elseif(NOT ARGS_DEPRECATED_BASE_VERSION MATCHES ${_version_triple_regexp} AND 0519 NOT ARGS_DEPRECATED_BASE_VERSION STREQUAL "0") 0520 message(FATAL_ERROR "DEPRECATED_BASE_VERSION expected to be in \"x.y.z\" format, \"0\" or \"CURRENT\" when calling ecm_generate_export_header().") 0521 endif() 0522 if (ARGS_DEPRECATED_BASE_VERSION VERSION_LESS ARGS_EXCLUDE_DEPRECATED_BEFORE_AND_AT) 0523 message(STATUS "DEPRECATED_BASE_VERSION (${ARGS_DEPRECATED_BASE_VERSION}) was lower than EXCLUDE_DEPRECATED_BEFORE_AND_AT (${ARGS_EXCLUDE_DEPRECATED_BEFORE_AND_AT}) when calling ecm_generate_export_header(), raising to that.") 0524 set(ARGS_DEPRECATED_BASE_VERSION "${ARGS_EXCLUDE_DEPRECATED_BEFORE_AND_AT}") 0525 endif() 0526 endif() 0527 if(NOT ARGS_BASE_NAME) 0528 set(ARGS_BASE_NAME "${target}") 0529 endif() 0530 if(NOT ARGS_VERSION_BASE_NAME) 0531 set(ARGS_VERSION_BASE_NAME "${ARGS_BASE_NAME}") 0532 endif() 0533 string(TOUPPER "${ARGS_BASE_NAME}" _upper_base_name) 0534 string(TOLOWER "${ARGS_BASE_NAME}" _lower_base_name) 0535 set(_version_header) 0536 if (USE_VERSION_HEADER IN_LIST ARGS_KEYWORDS_MISSING_VALUES) 0537 string(TOLOWER "${ARGS_VERSION_BASE_NAME}" _lower_version_base_name) 0538 set(_version_header "${_lower_version_base_name}_version.h") 0539 elseif (DEFINED ARGS_USE_VERSION_HEADER) 0540 list(LENGTH ARGS_USE_VERSION_HEADER _arg_count) 0541 if (_arg_count GREATER 1) 0542 message(FATAL_ERROR "USE_VERSION_HEADER only takes 1 or no arg when calling ecm_generate_export_header().") 0543 endif() 0544 set(_version_header ${ARGS_USE_VERSION_HEADER}) 0545 endif() 0546 if(_version_header) 0547 if(ARGS_VERSION_MACRO_NAME) 0548 set(_version_hexnumber "${ARGS_VERSION_MACRO_NAME}") 0549 else() 0550 string(TOUPPER "${ARGS_VERSION_BASE_NAME}" _upper_version_base_name) 0551 set(_version_hexnumber "${_upper_version_base_name}_VERSION") 0552 endif() 0553 else() 0554 _ecm_geh_generate_hex_number(_version_hexnumber "${ARGS_VERSION}") 0555 endif() 0556 0557 if(NOT ARGS_EXPORT_FILE_NAME) 0558 set(ARGS_EXPORT_FILE_NAME "${_lower_base_name}_export.h") 0559 endif() 0560 if (ARGS_DEPRECATED_BASE_VERSION STREQUAL "0") 0561 set(_default_disabled_deprecated_version_hexnumber "0") 0562 else() 0563 _ecm_geh_generate_hex_number(_default_disabled_deprecated_version_hexnumber "${ARGS_DEPRECATED_BASE_VERSION}") 0564 endif() 0565 0566 set(_macro_base_name "${ARGS_PREFIX_NAME}${_upper_base_name}") 0567 if (ARGS_EXPORT_MACRO_NAME) 0568 set(_export_macro_name "${ARGS_EXPORT_MACRO_NAME}") 0569 else() 0570 set(_export_macro_name "${_macro_base_name}_EXPORT") 0571 endif() 0572 if (ARGS_NO_EXPORT_MACRO_NAME) 0573 set(_no_export_macro_name "${ARGS_NO_EXPORT_MACRO_NAME}") 0574 else() 0575 set(_no_export_macro_name "${_macro_base_name}_NO_EXPORT") 0576 endif() 0577 if (ARGS_DEPRECATED_MACRO_NAME) 0578 set(_deprecated_macro_name "${ARGS_DEPRECATED_MACRO_NAME}") 0579 else() 0580 set(_deprecated_macro_name "${_macro_base_name}_DEPRECATED") 0581 endif() 0582 0583 if(NOT IS_ABSOLUTE ${ARGS_EXPORT_FILE_NAME}) 0584 set(ARGS_EXPORT_FILE_NAME "${CMAKE_CURRENT_BINARY_DIR}/${ARGS_EXPORT_FILE_NAME}") 0585 endif() 0586 0587 set_property(TARGET ${target} APPEND PROPERTY AUTOGEN_TARGET_DEPENDS "${ARGS_EXPORT_FILE_NAME}") 0588 # build with all the API not excluded, ensure all deprecated API is visible in the build itself 0589 _ecm_geh_generate_hex_number(_hexnumber ${ARGS_EXCLUDE_DEPRECATED_BEFORE_AND_AT}) 0590 set(_disabling_visibility_definition "${_macro_base_name}_DISABLE_DEPRECATED_BEFORE_AND_AT=${_hexnumber}") 0591 target_compile_definitions(${target} PRIVATE "${_disabling_visibility_definition}") 0592 if (NOT ARGS_NO_DEFINITION_EXPORT_TO_BUILD_INTERFACE) 0593 target_compile_definitions(${target} INTERFACE "$<BUILD_INTERFACE:${_disabling_visibility_definition}>") 0594 endif() 0595 if(NOT ARGS_NO_BUILD_SET_DEPRECATED_WARNINGS_SINCE) 0596 set(_enabling_warnings_definition "${_macro_base_name}_DEPRECATED_WARNINGS_SINCE=${_hexnumber}") 0597 target_compile_definitions(${target} PRIVATE "${_enabling_warnings_definition}") 0598 if (NOT ARGS_NO_DEFINITION_EXPORT_TO_BUILD_INTERFACE) 0599 target_compile_definitions(${target} INTERFACE "$<BUILD_INTERFACE:${_enabling_warnings_definition}>") 0600 endif() 0601 endif() 0602 0603 # for the set of compiler versions supported by ECM/KF we can assume those attributes supported 0604 # KF6: with C++17 as minimum standard planned, switch to always use [[deprecated(text)]] 0605 if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang") 0606 set(_decl_deprecated_text_definition "__attribute__ ((__deprecated__(text)))") 0607 elseif(MSVC) 0608 set(_decl_deprecated_text_definition "__declspec(deprecated(text))") 0609 else() 0610 set(_decl_deprecated_text_definition "${_macro_base_name}_DECL_DEPRECATED") 0611 endif() 0612 # generate header file 0613 set(_output) 0614 if(_version_header) 0615 if (_version_header MATCHES "^\".+\"$") 0616 string(APPEND _output "#include ${_version_header}\n") 0617 else() 0618 string(APPEND _output "#include <${_version_header}>\n") 0619 endif() 0620 endif() 0621 string(APPEND _output " 0622 #define ${_macro_base_name}_DECL_DEPRECATED_TEXT(text) ${_decl_deprecated_text_definition} 0623 " 0624 ) 0625 if (ARGS_GROUP_BASE_NAME) 0626 string(TOUPPER "${ARGS_GROUP_BASE_NAME}" _upper_group_name) 0627 string(APPEND _output " 0628 /* Take any defaults from group settings */ 0629 #if !defined(${_macro_base_name}_NO_DEPRECATED) && !defined(${_macro_base_name}_DISABLE_DEPRECATED_BEFORE_AND_AT) 0630 # ifdef ${_upper_group_name}_NO_DEPRECATED 0631 # define ${_macro_base_name}_NO_DEPRECATED 0632 # elif defined(${_upper_group_name}_DISABLE_DEPRECATED_BEFORE_AND_AT) 0633 # define ${_macro_base_name}_DISABLE_DEPRECATED_BEFORE_AND_AT ${_upper_group_name}_DISABLE_DEPRECATED_BEFORE_AND_AT 0634 # endif 0635 #endif 0636 #if !defined(${_macro_base_name}_DISABLE_DEPRECATED_BEFORE_AND_AT) && defined(${_upper_group_name}_DISABLE_DEPRECATED_BEFORE_AND_AT) 0637 # define ${_macro_base_name}_DISABLE_DEPRECATED_BEFORE_AND_AT ${_upper_group_name}_DISABLE_DEPRECATED_BEFORE_AND_AT 0638 #endif 0639 0640 #if !defined(${_macro_base_name}_NO_DEPRECATED_WARNINGS) && !defined(${_macro_base_name}_DEPRECATED_WARNINGS_SINCE) 0641 # ifdef ${_upper_group_name}_NO_DEPRECATED_WARNINGS 0642 # define ${_macro_base_name}_NO_DEPRECATED_WARNINGS 0643 # elif defined(${_upper_group_name}_DEPRECATED_WARNINGS_SINCE) 0644 # define ${_macro_base_name}_DEPRECATED_WARNINGS_SINCE ${_upper_group_name}_DEPRECATED_WARNINGS_SINCE 0645 # endif 0646 #endif 0647 #if !defined(${_macro_base_name}_DEPRECATED_WARNINGS_SINCE) && defined(${_upper_group_name}_DEPRECATED_WARNINGS_SINCE) 0648 # define ${_macro_base_name}_DEPRECATED_WARNINGS_SINCE ${_upper_group_name}_DEPRECATED_WARNINGS_SINCE 0649 #endif 0650 " 0651 ) 0652 endif() 0653 string(APPEND _output " 0654 #if defined(${_macro_base_name}_NO_DEPRECATED) 0655 # undef ${_deprecated_macro_name} 0656 # define ${_deprecated_macro_name}_EXPORT ${_export_macro_name} 0657 # define ${_deprecated_macro_name}_NO_EXPORT ${_no_export_macro_name} 0658 #elif defined(${_macro_base_name}_NO_DEPRECATED_WARNINGS) 0659 # define ${_deprecated_macro_name} 0660 # define ${_deprecated_macro_name}_EXPORT ${_export_macro_name} 0661 # define ${_deprecated_macro_name}_NO_EXPORT ${_no_export_macro_name} 0662 #else 0663 # define ${_deprecated_macro_name} ${_macro_base_name}_DECL_DEPRECATED 0664 # define ${_deprecated_macro_name}_EXPORT ${_macro_base_name}_DECL_DEPRECATED_EXPORT 0665 # define ${_deprecated_macro_name}_NO_EXPORT ${_macro_base_name}_DECL_DEPRECATED_NO_EXPORT 0666 #endif 0667 " 0668 ) 0669 if (ARGS_EXCLUDE_DEPRECATED_BEFORE_AND_AT) 0670 message(STATUS "Excluding from build all API deprecated before and at: ${ARGS_EXCLUDE_DEPRECATED_BEFORE_AND_AT}") 0671 # TODO: the generated code ideally would emit a warning if some consumer used a value 0672 # smaller then what the the build was done with 0673 _ecm_geh_generate_hex_number(_excluded_before_and_at_version_hexnumber "${ARGS_EXCLUDE_DEPRECATED_BEFORE_AND_AT}") 0674 string(APPEND _output " 0675 /* Build was done with the API removed deprecated before: ${ARGS_EXCLUDE_DEPRECATED_BEFORE_AND_AT} */ 0676 #define ${_macro_base_name}_EXCLUDE_DEPRECATED_BEFORE_AND_AT ${_excluded_before_and_at_version_hexnumber} 0677 0678 #ifdef ${_macro_base_name}_DISABLE_DEPRECATED_BEFORE_AND_AT 0679 # if ${_macro_base_name}_DISABLE_DEPRECATED_BEFORE_AND_AT < ${_macro_base_name}_EXCLUDE_DEPRECATED_BEFORE_AND_AT 0680 # undef ${_macro_base_name}_DISABLE_DEPRECATED_BEFORE_AND_AT 0681 # define ${_macro_base_name}_DISABLE_DEPRECATED_BEFORE_AND_AT ${_macro_base_name}_EXCLUDE_DEPRECATED_BEFORE_AND_AT 0682 # endif 0683 #endif 0684 0685 #define ${_macro_base_name}_BUILD_DEPRECATED_SINCE(major, minor) (((major<<16)|(minor<<8)) > ${_macro_base_name}_EXCLUDE_DEPRECATED_BEFORE_AND_AT) 0686 " 0687 ) 0688 else() 0689 string(APPEND _output " 0690 /* No deprecated API had been removed from build */ 0691 #define ${_macro_base_name}_EXCLUDE_DEPRECATED_BEFORE_AND_AT 0 0692 0693 #define ${_macro_base_name}_BUILD_DEPRECATED_SINCE(major, minor) 1 0694 " 0695 ) 0696 endif() 0697 string(APPEND _output " 0698 #ifdef ${_macro_base_name}_NO_DEPRECATED 0699 # define ${_macro_base_name}_DISABLE_DEPRECATED_BEFORE_AND_AT ${_version_hexnumber} 0700 #endif 0701 #ifdef ${_macro_base_name}_NO_DEPRECATED_WARNINGS 0702 # define ${_macro_base_name}_DEPRECATED_WARNINGS_SINCE 0 0703 #endif 0704 0705 #ifndef ${_macro_base_name}_DEPRECATED_WARNINGS_SINCE 0706 # ifdef ${_macro_base_name}_DISABLE_DEPRECATED_BEFORE_AND_AT 0707 # define ${_macro_base_name}_DEPRECATED_WARNINGS_SINCE ${_macro_base_name}_DISABLE_DEPRECATED_BEFORE_AND_AT 0708 # else 0709 # define ${_macro_base_name}_DEPRECATED_WARNINGS_SINCE ${_version_hexnumber} 0710 # endif 0711 #endif 0712 0713 #ifndef ${_macro_base_name}_DISABLE_DEPRECATED_BEFORE_AND_AT 0714 # define ${_macro_base_name}_DISABLE_DEPRECATED_BEFORE_AND_AT ${_default_disabled_deprecated_version_hexnumber} 0715 #endif 0716 0717 #ifdef ${_deprecated_macro_name} 0718 # define ${_macro_base_name}_ENABLE_DEPRECATED_SINCE(major, minor) (((major<<16)|(minor<<8)) > ${_macro_base_name}_DISABLE_DEPRECATED_BEFORE_AND_AT) 0719 #else 0720 # define ${_macro_base_name}_ENABLE_DEPRECATED_SINCE(major, minor) 0 0721 #endif 0722 " 0723 ) 0724 if (DEFINED ARGS_DEPRECATION_VERSIONS) 0725 set(_major_versions) 0726 foreach(_version ${ARGS_DEPRECATION_VERSIONS}) 0727 _ecm_geh_generate_hex_number(_version_hexnumber "${_version}.0") 0728 string(REPLACE "." "_" _underscored_version "${_version}") 0729 string(REGEX REPLACE "^([0-9]+)\\.([0-9]+)$" "\\1" 0730 _version_major "${_version}") 0731 # IN_LIST only since cmake 3.3 0732 set(_in_list FALSE) 0733 foreach(_v ${_major_versions}) 0734 if (_v STREQUAL _version_major) 0735 set(_in_list TRUE) 0736 break() 0737 endif() 0738 endforeach() 0739 if(NOT _in_list) 0740 list(APPEND _major_versions ${_version_major}) 0741 endif() 0742 0743 string(APPEND _output " 0744 #if ${_macro_base_name}_DEPRECATED_WARNINGS_SINCE >= ${_version_hexnumber} 0745 # define ${_macro_base_name}_DEPRECATED_VERSION_${_underscored_version}(text) ${_macro_base_name}_DECL_DEPRECATED_TEXT(text) 0746 #else 0747 # define ${_macro_base_name}_DEPRECATED_VERSION_${_underscored_version}(text) 0748 #endif 0749 " 0750 ) 0751 endforeach() 0752 foreach(_major_version ${_major_versions}) 0753 string(APPEND _output 0754 "#define ${_macro_base_name}_DEPRECATED_VERSION_${_major_version}(minor, text) ${_macro_base_name}_DEPRECATED_VERSION_${_major_version}_##minor(text) 0755 " 0756 ) 0757 endforeach() 0758 0759 string(APPEND _output 0760 "#define ${_macro_base_name}_DEPRECATED_VERSION(major, minor, text) ${_macro_base_name}_DEPRECATED_VERSION_##major(minor, \"Since \"#major\".\"#minor\". \" text) 0761 " 0762 ) 0763 string(APPEND _output 0764 "#define ${_macro_base_name}_DEPRECATED_VERSION_BELATED(major, minor, textmajor, textminor, text) ${_macro_base_name}_DEPRECATED_VERSION_##major(minor, \"Since \"#textmajor\".\"#textminor\". \" text) 0765 " 0766 ) 0767 # reusing the existing version-controlled deprecation macros for enumerator deprecation macros 0768 # to avoid having to repeat all the explicit version variants 0769 # TODO: MSVC seems to have issues with __declspec(deprecated) being used as enumerator attribute 0770 # and deals only with standard [[deprecated(text)]]. 0771 # But for now we have to keep the deprecation macros using the compiler-specific attributes, 0772 # because CMake's GenerateExportHeader uses the latter for the export macros and 0773 # at least GCC does not support both being used mixed e.g. on the same class or method. 0774 # Possibly needs to be solved by forking GenerateExportHeader to get complete control. 0775 if(NOT MSVC) 0776 string(APPEND _output 0777 "#if defined(__cpp_enumerator_attributes) && __cpp_enumerator_attributes >= 201411 0778 # define ${_macro_base_name}_ENUMERATOR_DEPRECATED_VERSION(major, minor, text) ${_macro_base_name}_DEPRECATED_VERSION(major, minor, text) 0779 # define ${_macro_base_name}_ENUMERATOR_DEPRECATED_VERSION_BELATED(major, minor, textmajor, textminor, text) ${_macro_base_name}_DEPRECATED_VERSION_BELATED(major, minor, textmajor, textminor, text) 0780 #else 0781 # define ${_macro_base_name}_ENUMERATOR_DEPRECATED_VERSION(major, minor, text) 0782 # define ${_macro_base_name}_ENUMERATOR_DEPRECATED_VERSION_BELATED(major, minor, textmajor, textminor, text) 0783 #endif 0784 " 0785 ) 0786 else() 0787 string(APPEND _output 0788 "// Not yet implemented for MSVC 0789 #define ${_macro_base_name}_ENUMERATOR_DEPRECATED_VERSION(major, minor, text) 0790 #define ${_macro_base_name}_ENUMERATOR_DEPRECATED_VERSION_BELATED(major, minor, textmajor, textminor, text) 0791 " 0792 ) 0793 endif() 0794 endif() 0795 if (ARGS_CUSTOM_CONTENT_FROM_VARIABLE) 0796 if(DEFINED "${ARGS_CUSTOM_CONTENT_FROM_VARIABLE}") 0797 string(APPEND _output "${${ARGS_CUSTOM_CONTENT_FROM_VARIABLE}}\n") 0798 else() 0799 message(DEPRECATION "Passing a value instead of a variable name with CUSTOM_CONTENT_FROM_VARIABLE. Since 5.98, use the name of a variable.") 0800 string(APPEND _output "${ARGS_CUSTOM_CONTENT_FROM_VARIABLE}\n") 0801 endif() 0802 endif() 0803 0804 # prepare optional arguments to pass through to generate_export_header 0805 set(_include_guard_name_args) 0806 if (ARGS_INCLUDE_GUARD_NAME) 0807 set(_include_guard_name_args INCLUDE_GUARD_NAME "${ARGS_INCLUDE_GUARD_NAME}") 0808 endif() 0809 set(_export_macro_name_args) 0810 if (ARGS_EXPORT_MACRO_NAME) 0811 set(_export_macro_name_args EXPORT_MACRO_NAME "${ARGS_EXPORT_MACRO_NAME}") 0812 endif() 0813 set(_no_export_macro_name_args) 0814 if (ARGS_NO_EXPORT_MACRO_NAME) 0815 set(_no_export_macro_name_args ARGS_NO_EXPORT_MACRO_NAME "${ARGS_NO_EXPORT_MACRO_NAME}") 0816 endif() 0817 set(_prefix_name_args) 0818 if (ARGS_PREFIX_NAME) 0819 set(_prefix_name_args PREFIX_NAME "${ARGS_PREFIX_NAME}") 0820 endif() 0821 set(_static_define_args) 0822 if (ARGS_STATIC_DEFINE) 0823 set(_static_define_args STATIC_DEFINE "${ARGS_STATIC_DEFINE}") 0824 endif() 0825 generate_export_header(${target} 0826 BASE_NAME ${ARGS_BASE_NAME} 0827 DEPRECATED_MACRO_NAME "${_macro_base_name}_DECL_DEPRECATED" 0828 ${_prefix_name_args} 0829 ${_export_macro_name_args} 0830 ${_no_export_macro_name_args} 0831 ${_static_define_args} 0832 EXPORT_FILE_NAME "${ARGS_EXPORT_FILE_NAME}" 0833 ${_include_guard_name_args} 0834 CUSTOM_CONTENT_FROM_VARIABLE _output 0835 ) 0836 endfunction() 0837 0838 cmake_policy(POP)