| # Distributed under the OSI-approved BSD 3-Clause License. See accompanying |
| # file LICENSE.rst or https://cmake.org/licensing for details. |
| |
| #[=======================================================================[.rst: |
| GenerateExportHeader |
| -------------------- |
| |
| This module provides commands for generating a header file containing |
| preprocessor macro definitions to control C/C++ symbol visibility. |
| |
| Load this module in a CMake project with: |
| |
| .. code-block:: cmake |
| |
| include(GenerateExportHeader) |
| |
| .. versionadded:: 3.12 |
| Support for C projects. Previous versions supported C++ projects only. |
| |
| When developing C or C++ projects, especially for cross-platform use, symbol |
| visibility determines which functions, classes, global variables, templates, |
| and other symbols are made visible to users of the library. |
| |
| For example, on Windows, symbols must be explicitly marked with |
| ``__declspec(dllexport)`` when building a shared library, and |
| ``__declspec(dllimport)`` when using it. Other platforms may use attributes |
| like ``__attribute__((visibility("default")))``. |
| |
| This module simplifies the creation and usage of preprocessor macros to |
| manage these requirements, avoiding repetitive and error-prone ``#ifdef`` |
| blocks in source code. |
| |
| Some symbol visibility can also be controlled with compiler options. In |
| CMake, target properties such as :prop_tgt:`<LANG>_VISIBILITY_PRESET` and |
| :prop_tgt:`VISIBILITY_INLINES_HIDDEN` enable compiler visibility flags, |
| where appropriate. See also related convenience variables |
| :variable:`CMAKE_<LANG>_VISIBILITY_PRESET` and |
| :variable:`CMAKE_VISIBILITY_INLINES_HIDDEN` to enable it for all targets in |
| current scope. These are commonly used in combination with this module to |
| further simplify C/C++ code, removing the need for some of the preprocessor |
| macros in the source code. |
| |
| Commands |
| ^^^^^^^^ |
| |
| This module provides the following commands: |
| |
| Generating Export Header |
| """""""""""""""""""""""" |
| |
| .. command:: generate_export_header |
| |
| Generates a header file suitable for inclusion in source code, containing |
| preprocessor *export* macros for controlling the visibility of symbols: |
| |
| .. code-block:: cmake |
| |
| generate_export_header( |
| <target> |
| [BASE_NAME <base-name>] |
| [EXPORT_FILE_NAME <export-file-name>] |
| [EXPORT_MACRO_NAME <export-macro-name>] |
| [NO_EXPORT_MACRO_NAME <no-export-macro-name>] |
| [DEPRECATED_MACRO_NAME <deprecated-macro-name>] |
| [DEFINE_NO_DEPRECATED] |
| [NO_DEPRECATED_MACRO_NAME <no-deprecated-macro-name>] |
| [STATIC_DEFINE <static-define>] |
| [PREFIX_NAME <prefix>] |
| [CUSTOM_CONTENT_FROM_VARIABLE <variable>] |
| [INCLUDE_GUARD_NAME <include-guard-name>] |
| ) |
| |
| By default, this command generates a header file named |
| ``<target-name-lowercase>_export.h`` in the current binary directory |
| (:variable:`CMAKE_CURRENT_BINARY_DIR`). This header defines a set of |
| preprocessor macros used to mark API symbols as exported, hidden, or |
| deprecated across different platforms and build types (e.g., static or |
| shared builds), and is intended to be installed along with the library's |
| public headers, because it affects public API declarations: |
| |
| * ``<MACRO>_EXPORT``: Marks symbols for export or import, making them |
| visible as part of the public API when building or consuming a shared |
| library. |
| |
| * ``<MACRO>_NO_EXPORT``: Marks symbols that should not be exported. |
| If the :prop_tgt:`<LANG>_VISIBILITY_PRESET` target property is set to |
| ``hidden``, using this macro in source code is typically redundant. |
| |
| * ``<MACRO>_DEPRECATED``: Marks symbols as deprecated. When such symbols |
| are used, the compiler emits a warning at compile-time. |
| |
| * ``<MACRO>_DEPRECATED_EXPORT``: Combines export/import and deprecation |
| markers for a symbol that is both part of the public API and deprecated. |
| |
| * ``<MACRO>_DEPRECATED_NO_EXPORT``: Marks a deprecated symbol that should |
| not be exported (internal and deprecated). |
| |
| * ``<MACRO>_NO_DEPRECATED``: A macro that can be used in source code to |
| conditionally exclude deprecated code parts from the build via |
| preprocessor logic. |
| |
| The ``<MACRO>`` part is derived by default from the uppercase name of the |
| target or the explicitly provided ``<base-name>``. All macro names can be |
| customized using the optional arguments. |
| |
| .. rubric:: The arguments are: |
| |
| ``<target>`` |
| Name of a target for which the export header will be generated. |
| Supported target types: |
| |
| * ``STATIC`` library (in this case, export-related macros are defined |
| without values) |
| * ``SHARED`` library |
| * ``MODULE`` library |
| * .. versionadded:: 3.1 |
| ``OBJECT`` library |
| |
| ``BASE_NAME <base-name>`` |
| If specified, it overrides the default file name and macro names. |
| |
| ``EXPORT_FILE_NAME <export-file-name>`` |
| If specified, it overrides the full path and the name of the generated |
| export header file (``<base-name-lowercase>_export.h``) to |
| ``<export-file-name>``. If given as a relative path, it will be |
| interpreted relative to the current binary directory |
| (:variable:`CMAKE_CURRENT_BINARY_DIR`). |
| |
| ``EXPORT_MACRO_NAME <export-macro-name>`` |
| If specified, it overrides the default macro name for the export |
| directive. |
| |
| ``NO_EXPORT_MACRO_NAME <no-export-macro-name>`` |
| If specified, the ``<no-export-macro-name>`` will be used for the macro |
| name that designates the attribute for items that shouldn't be exported. |
| |
| ``DEPRECATED_MACRO_NAME <deprecated-macro-name>`` |
| If specified, the following names will be used: |
| |
| * ``<deprecated-macro-name>`` (macro for marking deprecated symbols) |
| * ``<deprecated-macro-name>_EXPORT`` (macro for deprecated symbols with |
| export markers) |
| * ``<deprecated-macro-name>_NO_EXPORT`` (macro for deprecated symbols |
| with no-export markers) |
| |
| instead of the default names in format of |
| ``<MACRO>_DEPRECATED{,_EXPORT,_NO_EXPORT}``. |
| |
| ``DEFINE_NO_DEPRECATED`` |
| If specified, this will define a macro named ``<MACRO>_NO_DEPRECATED``. |
| |
| ``NO_DEPRECATED_MACRO_NAME <no-deprecated-macro-name>`` |
| Used in combination with ``DEFINE_NO_DEPRECATED`` option. If specified, |
| then a macro named ``<no-deprecated-macro-name>`` is used instead of the |
| default ``<MACRO>_NO_DEPRECATED``. |
| |
| ``STATIC_DEFINE <static-define>`` |
| If specified, the ``<static-define>`` macro name will be used instead |
| of the default ``<MACRO>_STATIC_DEFINE``. This macro controls the |
| symbol export behavior in the generated header for static libraries. |
| It is typically used when building both shared and static variants of a |
| library from the same sources using a single generated export header. |
| When this macro is defined for static library, the export-related macros |
| will expand to nothing. This is important also on Windows, where symbol |
| decoration is required only for shared libraries, not for static ones. |
| |
| ``PREFIX_NAME <prefix>`` |
| If specified, the additional ``<prefix>`` is prepended to all generated |
| macro names. |
| |
| ``CUSTOM_CONTENT_FROM_VARIABLE <variable>`` |
| .. versionadded:: 3.7 |
| |
| If specified, the content from the ``<variable>`` value is appended to |
| the generated header file content after the preprocessor macros |
| definitions. |
| |
| ``INCLUDE_GUARD_NAME <include-guard-name>`` |
| .. versionadded:: 3.11 |
| |
| If specified, the ``<include-guard-name>`` is used as the preprocessor |
| macro name to guard multiple inclusions of the generated header instead |
| of the default name ``<export-macro-name>_H``. |
| |
| .. code-block:: c++ |
| :caption: ``<base-name-lowercase>_export.h`` |
| |
| #ifndef <include-guard-name> |
| #define <include-guard-name> |
| // ... |
| #endif /* <include-guard-name> */ |
| |
| Deprecated Command |
| """""""""""""""""" |
| |
| .. command:: add_compiler_export_flags |
| |
| .. deprecated:: 3.0 |
| |
| Set the target properties |
| :prop_tgt:`CXX_VISIBILITY_PRESET <<LANG>_VISIBILITY_PRESET>` and |
| :prop_tgt:`VISIBILITY_INLINES_HIDDEN` instead. |
| |
| Adds C++ compiler options ``-fvisibility=hidden`` (and |
| ``-fvisibility-inlines-hidden``, if supported) to hide all symbols by |
| default to either :variable:`CMAKE_CXX_FLAGS <CMAKE_<LANG>_FLAGS>` |
| variable or to a specified variable: |
| |
| .. code-block:: cmake |
| |
| add_compiler_export_flags([<output_variable>]) |
| |
| This command is a no-op on Windows which does not need extra compiler flags |
| for exporting support. |
| |
| ``<output-variable>`` |
| Optional variable name that will be populated with a string of |
| space-separated C++ compile options required to enable visibility |
| support for the compiler/architecture in use. If this argument is |
| specified, the :variable:`CMAKE_CXX_FLAGS <CMAKE_<LANG>_FLAGS>` variable |
| will not be modified. |
| |
| Examples |
| ^^^^^^^^ |
| |
| Example: Generating Export Header |
| """"""""""""""""""""""""""""""""" |
| |
| The following example demonstrates how to use this module to generate an |
| export header in the current binary directory (``example_export.h``) and use |
| it in a C++ library named ``example`` to control symbols visibility. The |
| generated header defines the preprocessor macros ``EXAMPLE_EXPORT``, |
| ``EXAMPLE_NO_EXPORT``, ``EXAMPLE_DEPRECATED``, ``EXAMPLE_DEPRECATED_EXPORT``, |
| and ``EXAMPLE_DEPRECATED_NO_EXPORT``, and is installed along with the |
| library's other public headers: |
| |
| .. code-block:: cmake |
| :caption: ``CMakeLists.txt`` |
| :emphasize-lines: 10,11 |
| |
| cmake_minimum_required(VERSION 3.24) |
| project(GenerateExportHeaderExample) |
| |
| # Set default visibility of all symbols to hidden |
| set(CMAKE_CXX_VISIBILITY_PRESET "hidden") |
| set(CMAKE_VISIBILITY_INLINES_HIDDEN TRUE) |
| |
| add_library(example) |
| |
| include(GenerateExportHeader) |
| generate_export_header(example) |
| |
| target_sources( |
| example |
| PRIVATE example.cxx |
| PUBLIC |
| FILE_SET HEADERS |
| FILES example.h |
| FILE_SET generated_headers |
| TYPE HEADERS |
| BASE_DIRS $<TARGET_PROPERTY:example,BINARY_DIR> |
| FILES ${CMAKE_CURRENT_BINARY_DIR}/example_export.h |
| ) |
| |
| target_include_directories(example PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) |
| |
| install( |
| TARGETS example |
| FILE_SET HEADERS |
| FILE_SET generated_headers |
| ) |
| |
| And in the ABI header files: |
| |
| .. code-block:: c++ |
| :caption: ``example.h`` |
| |
| #include "example_export.h" |
| |
| // This class is part of the public API and is exported |
| class EXAMPLE_EXPORT SomeClass |
| { |
| public: |
| SomeClass(); |
| void doSomething(); |
| |
| // This method is deprecated |
| EXAMPLE_DEPRECATED void legacyMethod(); |
| }; |
| |
| // This function is exported and deprecated |
| EXAMPLE_DEPRECATED_EXPORT void legacyPublicFunction(); |
| |
| // This function is deprecated but not exported |
| EXAMPLE_DEPRECATED void legacyInternalFunction(); |
| |
| .. code-block:: c++ |
| :caption: ``example.cxx`` |
| |
| #include <iostream> |
| #include "example.h" |
| |
| SomeClass::SomeClass() = default; |
| |
| void SomeClass::doSomething() |
| { |
| std::cout << "SomeClass::doSomething() called" << std::endl; |
| } |
| |
| void SomeClass::legacyMethod() |
| { |
| std::cout << "SomeClass::legacyMethod() is deprecated" << std::endl; |
| } |
| |
| void legacyPublicFunction() |
| { |
| std::cout << "legacyPublicFunction() is deprecated" << std::endl; |
| } |
| |
| void internalLegacyFunction() |
| { |
| std::cout << "legacyInternalFunction() is deprecated" << std::endl; |
| } |
| |
| Examples: Customizing Generated Header |
| """""""""""""""""""""""""""""""""""""" |
| |
| The ``BASE_NAME`` argument can be used to override the generated file name |
| and the names used for the macros. The following will generate a file |
| named ``other_name_export.h`` containing export-related macros such as |
| ``OTHER_NAME_EXPORT``, ``OTHER_NAME_NO_EXPORT``, ``OTHER_NAME_DEPRECATED``, |
| etc. |
| |
| .. code-block:: cmake |
| |
| add_library(example example.cxx) |
| include(GenerateExportHeader) |
| generate_export_header(example BASE_NAME "other_name") |
| |
| The ``BASE_NAME`` may be overridden by specifying other command options. |
| For example, the following creates a macro ``OTHER_NAME_EXPORT`` instead of |
| ``EXAMPLE_EXPORT``, but other macros and the generated header file name are |
| set to their default values: |
| |
| .. code-block:: cmake |
| |
| add_library(example example.cxx) |
| include(GenerateExportHeader) |
| generate_export_header(example EXPORT_MACRO_NAME "OTHER_NAME_EXPORT") |
| |
| The following example creates ``KDE_DEPRECATED`` macro instead of |
| default ``EXAMPLE_DEPRECATED``: |
| |
| .. code-block:: cmake |
| |
| add_library(example example.cxx) |
| include(GenerateExportHeader) |
| generate_export_header(example DEPRECATED_MACRO_NAME "KDE_DEPRECATED") |
| |
| The ``DEFINE_NO_DEPRECATED`` option can be used to define a macro which can |
| be used to remove deprecated code from preprocessor output: |
| |
| .. code-block:: cmake |
| |
| option(EXCLUDE_DEPRECATED "Exclude deprecated parts of the library") |
| if(EXCLUDE_DEPRECATED) |
| set(NO_BUILD_DEPRECATED DEFINE_NO_DEPRECATED) |
| endif() |
| |
| include(GenerateExportHeader) |
| generate_export_header(example ${NO_BUILD_DEPRECATED}) |
| |
| .. code-block:: c++ |
| :caption: ``example.h`` |
| |
| class EXAMPLE_EXPORT SomeClass |
| { |
| public: |
| #ifndef EXAMPLE_NO_DEPRECATED |
| EXAMPLE_DEPRECATED void legacyMethod(); |
| #endif |
| }; |
| |
| .. code-block:: c++ |
| :caption: ``example.cxx`` |
| |
| #ifndef EXAMPLE_NO_DEPRECATED |
| void SomeClass::legacyMethod() { } |
| #endif |
| |
| The ``PREFIX_NAME`` argument can be used to prepend all generated macro names |
| with some prefix. For example, the following will generate macros such as |
| ``VTK_SOMELIB_EXPORT``, etc. |
| |
| .. code-block:: cmake |
| |
| include(GenerateExportHeader) |
| generate_export_header(somelib PREFIX_NAME "VTK_") |
| |
| Appending additional content to generated header can be done with the |
| ``CUSTOM_CONTENT_FROM_VARIABLE`` argument: |
| |
| .. code-block:: cmake |
| |
| include(GenerateExportHeader) |
| set(content [[#include "project_api.h"]]) |
| generate_export_header(example CUSTOM_CONTENT_FROM_VARIABLE content) |
| |
| Example: Building Shared and Static Library |
| """"""""""""""""""""""""""""""""""""""""""" |
| |
| In the following example both a shared and a static library are built from |
| the same sources, and the ``<MACRO>_STATIC_DEFINE`` macro compile definition |
| is defined to ensure the same generated export header works for both: |
| |
| .. code-block:: cmake |
| |
| add_library(example_shared SHARED example.cxx) |
| add_library(example_static STATIC example.cxx) |
| |
| include(GenerateExportHeader) |
| generate_export_header(example_shared BASE_NAME "example") |
| |
| # Define macro to disable export attributes for static build |
| target_compile_definitions(example_static PRIVATE EXAMPLE_STATIC_DEFINE) |
| |
| Example: Upgrading Deprecated Command |
| """"""""""""""""""""""""""""""""""""" |
| |
| In earlier versions of CMake, ``add_compiler_export_flags()`` command was |
| used to add symbol visibility compile options: |
| |
| .. code-block:: cmake |
| :caption: ``CMakeLists.txt`` |
| |
| add_library(example example.cxx) |
| |
| include(GenerateExportHeader) |
| |
| add_compiler_export_flags(flags) |
| string(REPLACE " " ";" flags "${flags}") |
| set_property(TARGET example APPEND PROPERTY COMPILE_OPTIONS "${flags}") |
| |
| generate_export_header(example) |
| |
| In new code, the following target properties are used to achieve the same |
| functionality: |
| |
| .. code-block:: cmake |
| :caption: ``CMakeLists.txt`` |
| |
| add_library(example example.cxx) |
| |
| include(GenerateExportHeader) |
| |
| set_target_properties( |
| example |
| PROPERTIES |
| CXX_VISIBILITY_PRESET hidden |
| VISIBILITY_INLINES_HIDDEN TRUE |
| ) |
| |
| generate_export_header(example) |
| |
| See Also |
| ^^^^^^^^ |
| |
| * The :prop_tgt:`DEFINE_SYMBOL` target property to customize the preprocessor |
| macro name used by the generated header. This macro determines whether |
| the library header is being included during the library's own compilation |
| or when it is used by another project (e.g., after installation). |
| * The :prop_tgt:`ENABLE_EXPORTS` target property. |
| * The :prop_tgt:`WINDOWS_EXPORT_ALL_SYMBOLS` target property. |
| #]=======================================================================] |
| |
| include(CheckCompilerFlag) |
| include(CheckSourceCompiles) |
| |
| # TODO: Install this macro separately? |
| macro(_check_cxx_compiler_attribute _ATTRIBUTE _RESULT) |
| check_source_compiles(CXX "${_ATTRIBUTE} int somefunc() { return 0; } |
| int main() { return somefunc();}" ${_RESULT} |
| ) |
| endmacro() |
| |
| # TODO: Install this macro separately? |
| macro(_check_c_compiler_attribute _ATTRIBUTE _RESULT) |
| check_source_compiles(C "${_ATTRIBUTE} int somefunc(void) { return 0; } |
| int main(void) { return somefunc();}" ${_RESULT} |
| ) |
| endmacro() |
| |
| macro(_test_compiler_hidden_visibility) |
| |
| if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" |
| AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS "4.2") |
| set(GCC_TOO_OLD TRUE) |
| elseif(CMAKE_C_COMPILER_ID STREQUAL "GNU" |
| AND CMAKE_C_COMPILER_VERSION VERSION_LESS "4.2") |
| set(GCC_TOO_OLD TRUE) |
| elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Intel" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS "12.0") |
| set(_INTEL_TOO_OLD TRUE) |
| endif() |
| |
| # Exclude XL here because it misinterprets -fvisibility=hidden even though |
| # the check_compiler_flag passes |
| if(NOT GCC_TOO_OLD |
| AND NOT _INTEL_TOO_OLD |
| AND NOT WIN32 |
| AND NOT CYGWIN |
| AND NOT CMAKE_CXX_COMPILER_ID MATCHES "^(IBMClang|XLClang|XL)$" |
| AND NOT CMAKE_CXX_COMPILER_ID MATCHES "^(PGI|NVHPC)$" |
| AND NOT CMAKE_CXX_COMPILER_ID MATCHES Watcom) |
| if (CMAKE_CXX_COMPILER_LOADED) |
| check_compiler_flag(CXX -fvisibility=hidden COMPILER_HAS_HIDDEN_VISIBILITY) |
| check_compiler_flag(CXX -fvisibility-inlines-hidden |
| COMPILER_HAS_HIDDEN_INLINE_VISIBILITY) |
| else() |
| check_compiler_flag(C -fvisibility=hidden COMPILER_HAS_HIDDEN_VISIBILITY) |
| check_compiler_flag(C -fvisibility-inlines-hidden |
| COMPILER_HAS_HIDDEN_INLINE_VISIBILITY) |
| endif() |
| endif() |
| endmacro() |
| |
| macro(_test_compiler_has_deprecated) |
| # NOTE: Some Embarcadero compilers silently compile __declspec(deprecated) |
| # without error, but this is not a documented feature and the attribute does |
| # not actually generate any warnings. |
| if(CMAKE_CXX_COMPILER_ID MATCHES Borland |
| OR CMAKE_CXX_COMPILER_ID MATCHES Embarcadero |
| OR CMAKE_CXX_COMPILER_ID MATCHES HP |
| OR GCC_TOO_OLD |
| OR CMAKE_CXX_COMPILER_ID MATCHES "^(PGI|NVHPC)$" |
| OR CMAKE_CXX_COMPILER_ID MATCHES Watcom) |
| set(COMPILER_HAS_DEPRECATED "" CACHE INTERNAL |
| "Compiler support for a deprecated attribute") |
| else() |
| if (CMAKE_CXX_COMPILER_LOADED) |
| _check_cxx_compiler_attribute("__attribute__((__deprecated__))" |
| COMPILER_HAS_DEPRECATED_ATTR) |
| if(COMPILER_HAS_DEPRECATED_ATTR) |
| set(COMPILER_HAS_DEPRECATED "${COMPILER_HAS_DEPRECATED_ATTR}" |
| CACHE INTERNAL "Compiler support for a deprecated attribute") |
| else() |
| _check_cxx_compiler_attribute("__declspec(deprecated)" |
| COMPILER_HAS_DEPRECATED) |
| endif() |
| else() |
| _check_c_compiler_attribute("__attribute__((__deprecated__))" |
| COMPILER_HAS_DEPRECATED_ATTR) |
| if(COMPILER_HAS_DEPRECATED_ATTR) |
| set(COMPILER_HAS_DEPRECATED "${COMPILER_HAS_DEPRECATED_ATTR}" |
| CACHE INTERNAL "Compiler support for a deprecated attribute") |
| else() |
| _check_c_compiler_attribute("__declspec(deprecated)" |
| COMPILER_HAS_DEPRECATED) |
| endif() |
| |
| endif() |
| endif() |
| endmacro() |
| |
| macro(_DO_SET_MACRO_VALUES TARGET_LIBRARY) |
| set(DEFINE_DEPRECATED) |
| set(DEFINE_EXPORT) |
| set(DEFINE_IMPORT) |
| set(DEFINE_NO_EXPORT) |
| |
| if (COMPILER_HAS_DEPRECATED_ATTR AND NOT WIN32) |
| set(DEFINE_DEPRECATED "__attribute__ ((__deprecated__))") |
| elseif(COMPILER_HAS_DEPRECATED) |
| set(DEFINE_DEPRECATED "__declspec(deprecated)") |
| endif() |
| |
| get_property(type TARGET ${TARGET_LIBRARY} PROPERTY TYPE) |
| |
| if(NOT ${type} STREQUAL "STATIC_LIBRARY") |
| if(WIN32 OR CYGWIN) |
| set(DEFINE_EXPORT "__declspec(dllexport)") |
| set(DEFINE_IMPORT "__declspec(dllimport)") |
| elseif(COMPILER_HAS_HIDDEN_VISIBILITY) |
| set(DEFINE_EXPORT "__attribute__((visibility(\"default\")))") |
| set(DEFINE_IMPORT "__attribute__((visibility(\"default\")))") |
| set(DEFINE_NO_EXPORT "__attribute__((visibility(\"hidden\")))") |
| endif() |
| endif() |
| endmacro() |
| |
| function(_DO_GENERATE_EXPORT_HEADER TARGET_LIBRARY) |
| # Option overrides |
| set(options DEFINE_NO_DEPRECATED) |
| set(oneValueArgs PREFIX_NAME BASE_NAME EXPORT_MACRO_NAME EXPORT_FILE_NAME |
| DEPRECATED_MACRO_NAME NO_EXPORT_MACRO_NAME STATIC_DEFINE |
| NO_DEPRECATED_MACRO_NAME CUSTOM_CONTENT_FROM_VARIABLE INCLUDE_GUARD_NAME) |
| set(multiValueArgs) |
| |
| cmake_parse_arguments(_GEH "${options}" "${oneValueArgs}" "${multiValueArgs}" |
| ${ARGN}) |
| |
| set(BASE_NAME "${TARGET_LIBRARY}") |
| |
| if(_GEH_BASE_NAME) |
| set(BASE_NAME ${_GEH_BASE_NAME}) |
| endif() |
| |
| string(TOUPPER ${BASE_NAME} BASE_NAME_UPPER) |
| string(TOLOWER ${BASE_NAME} BASE_NAME_LOWER) |
| |
| # Default options |
| set(EXPORT_MACRO_NAME "${_GEH_PREFIX_NAME}${BASE_NAME_UPPER}_EXPORT") |
| set(NO_EXPORT_MACRO_NAME "${_GEH_PREFIX_NAME}${BASE_NAME_UPPER}_NO_EXPORT") |
| set(EXPORT_FILE_NAME "${CMAKE_CURRENT_BINARY_DIR}/${BASE_NAME_LOWER}_export.h") |
| set(DEPRECATED_MACRO_NAME "${_GEH_PREFIX_NAME}${BASE_NAME_UPPER}_DEPRECATED") |
| set(STATIC_DEFINE "${_GEH_PREFIX_NAME}${BASE_NAME_UPPER}_STATIC_DEFINE") |
| set(NO_DEPRECATED_MACRO_NAME |
| "${_GEH_PREFIX_NAME}${BASE_NAME_UPPER}_NO_DEPRECATED") |
| |
| if(_GEH_UNPARSED_ARGUMENTS) |
| message(FATAL_ERROR "Unknown keywords given to generate_export_header(): \"${_GEH_UNPARSED_ARGUMENTS}\"") |
| endif() |
| |
| if(_GEH_EXPORT_MACRO_NAME) |
| set(EXPORT_MACRO_NAME ${_GEH_PREFIX_NAME}${_GEH_EXPORT_MACRO_NAME}) |
| endif() |
| string(MAKE_C_IDENTIFIER ${EXPORT_MACRO_NAME} EXPORT_MACRO_NAME) |
| if(_GEH_EXPORT_FILE_NAME) |
| if(IS_ABSOLUTE ${_GEH_EXPORT_FILE_NAME}) |
| set(EXPORT_FILE_NAME ${_GEH_EXPORT_FILE_NAME}) |
| else() |
| set(EXPORT_FILE_NAME "${CMAKE_CURRENT_BINARY_DIR}/${_GEH_EXPORT_FILE_NAME}") |
| endif() |
| endif() |
| if(_GEH_DEPRECATED_MACRO_NAME) |
| set(DEPRECATED_MACRO_NAME ${_GEH_PREFIX_NAME}${_GEH_DEPRECATED_MACRO_NAME}) |
| endif() |
| string(MAKE_C_IDENTIFIER ${DEPRECATED_MACRO_NAME} DEPRECATED_MACRO_NAME) |
| if(_GEH_NO_EXPORT_MACRO_NAME) |
| set(NO_EXPORT_MACRO_NAME ${_GEH_PREFIX_NAME}${_GEH_NO_EXPORT_MACRO_NAME}) |
| endif() |
| string(MAKE_C_IDENTIFIER ${NO_EXPORT_MACRO_NAME} NO_EXPORT_MACRO_NAME) |
| if(_GEH_STATIC_DEFINE) |
| set(STATIC_DEFINE ${_GEH_PREFIX_NAME}${_GEH_STATIC_DEFINE}) |
| endif() |
| string(MAKE_C_IDENTIFIER ${STATIC_DEFINE} STATIC_DEFINE) |
| |
| if(_GEH_DEFINE_NO_DEPRECATED) |
| set(DEFINE_NO_DEPRECATED 1) |
| else() |
| set(DEFINE_NO_DEPRECATED 0) |
| endif() |
| |
| if(_GEH_NO_DEPRECATED_MACRO_NAME) |
| set(NO_DEPRECATED_MACRO_NAME |
| ${_GEH_PREFIX_NAME}${_GEH_NO_DEPRECATED_MACRO_NAME}) |
| endif() |
| string(MAKE_C_IDENTIFIER ${NO_DEPRECATED_MACRO_NAME} NO_DEPRECATED_MACRO_NAME) |
| |
| if(_GEH_INCLUDE_GUARD_NAME) |
| set(INCLUDE_GUARD_NAME ${_GEH_INCLUDE_GUARD_NAME}) |
| else() |
| set(INCLUDE_GUARD_NAME "${EXPORT_MACRO_NAME}_H") |
| endif() |
| |
| get_target_property(EXPORT_IMPORT_CONDITION ${TARGET_LIBRARY} DEFINE_SYMBOL) |
| |
| if(NOT EXPORT_IMPORT_CONDITION) |
| set(EXPORT_IMPORT_CONDITION ${TARGET_LIBRARY}_EXPORTS) |
| endif() |
| string(MAKE_C_IDENTIFIER ${EXPORT_IMPORT_CONDITION} EXPORT_IMPORT_CONDITION) |
| |
| if(_GEH_CUSTOM_CONTENT_FROM_VARIABLE) |
| if(DEFINED "${_GEH_CUSTOM_CONTENT_FROM_VARIABLE}") |
| set(CUSTOM_CONTENT "${${_GEH_CUSTOM_CONTENT_FROM_VARIABLE}}") |
| else() |
| set(CUSTOM_CONTENT "") |
| endif() |
| endif() |
| |
| configure_file("${CMAKE_CURRENT_FUNCTION_LIST_DIR}/exportheader.cmake.in" |
| "${EXPORT_FILE_NAME}" @ONLY) |
| endfunction() |
| |
| function(GENERATE_EXPORT_HEADER TARGET_LIBRARY) |
| get_property(type TARGET ${TARGET_LIBRARY} PROPERTY TYPE) |
| if(NOT ${type} STREQUAL "STATIC_LIBRARY" |
| AND NOT ${type} STREQUAL "SHARED_LIBRARY" |
| AND NOT ${type} STREQUAL "OBJECT_LIBRARY" |
| AND NOT ${type} STREQUAL "MODULE_LIBRARY") |
| message(WARNING "This macro can only be used with libraries") |
| return() |
| endif() |
| _test_compiler_hidden_visibility() |
| _test_compiler_has_deprecated() |
| _do_set_macro_values(${TARGET_LIBRARY}) |
| _do_generate_export_header(${TARGET_LIBRARY} ${ARGN}) |
| endfunction() |
| |
| function(add_compiler_export_flags) |
| if(NOT CMAKE_MINIMUM_REQUIRED_VERSION VERSION_LESS 2.8.12) |
| message(DEPRECATION "The add_compiler_export_flags function is obsolete. Use the CXX_VISIBILITY_PRESET and VISIBILITY_INLINES_HIDDEN target properties instead.") |
| endif() |
| |
| _test_compiler_hidden_visibility() |
| _test_compiler_has_deprecated() |
| |
| option(USE_COMPILER_HIDDEN_VISIBILITY |
| "Use HIDDEN visibility support if available." ON) |
| mark_as_advanced(USE_COMPILER_HIDDEN_VISIBILITY) |
| if(NOT (USE_COMPILER_HIDDEN_VISIBILITY AND COMPILER_HAS_HIDDEN_VISIBILITY)) |
| # Just return if there are no flags to add. |
| return() |
| endif() |
| |
| set (EXTRA_FLAGS "-fvisibility=hidden") |
| |
| if(COMPILER_HAS_HIDDEN_INLINE_VISIBILITY) |
| set (EXTRA_FLAGS "${EXTRA_FLAGS} -fvisibility-inlines-hidden") |
| endif() |
| |
| # Either return the extra flags needed in the supplied argument, or to the |
| # CMAKE_CXX_FLAGS if no argument is supplied. |
| if(ARGC GREATER 0) |
| set(${ARGV0} "${EXTRA_FLAGS}" PARENT_SCOPE) |
| else() |
| string(APPEND CMAKE_CXX_FLAGS " ${EXTRA_FLAGS}") |
| set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}" PARENT_SCOPE) |
| endif() |
| endfunction() |
| |
| # FIXME(#24994): The following module(s) are included only for compatibility |
| # with projects that accidentally relied on them with CMake 3.26 and below. |
| include(CheckCCompilerFlag) |
| include(CheckCXXCompilerFlag) |