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)