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)