Created
October 30, 2018 15:22
-
-
Save shlomif/34da786a40386fe3b7e381beb2835dd7 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#.rst: | |
# ECMExportSymbols | |
# ---------------- | |
# | |
# This module provides the ``ecm_export_symbols`` function for providing | |
# versioned symbols within libraries. | |
# | |
# :: | |
# | |
# ecm_export_symbols(<target_name> | |
# [UNSTABLE_ABI] | |
# [FIRST_STABLE_VERSION <version_number>] | |
# ) | |
# | |
# If GNU LD is detected, this function creates a file called <target_name>.map | |
# which will be used when linking shared libraries. | |
# | |
# ``<target_name>`` may be a library name or an alias. | |
# | |
# ``UNSTABLE_ABI`` may be used to signal this library ABI is not stable. The | |
# function will not append additional version to the mapping file. | |
# | |
# ``FIRST_STABLE_VERSION`` specifies the first version where the ABI is | |
# considered stable. | |
# | |
# <target_name>.map will contain at least an entry for the current library | |
# version. | |
# Unless ``UNSTABLE_ABI`` or ``FIRST_STABLE_VERSION`` are used, it will then | |
# create entries for each minor version, starting with 0. | |
# | |
# This function has no effect if ``target_name`` is not a SHARED library. | |
# | |
# Example usage: | |
# | |
# .. code-block:: cmake | |
# | |
# include(ECMExportSymbols) | |
# | |
# add_library (KF5Foo ${_SRCS}) | |
# set_target_properties(KF5Foo PROPERTIES | |
# VERSION ${KF5FOO_VERSION_STRING} | |
# SOVERSION ${KF5FOO_SOVERSION} | |
# EXPORT_NAME "Foo" | |
# ) | |
# ecm_export_symbols(KF5Foo) | |
# | |
# Since 5.49.0. | |
#============================================================================= | |
# Copyright 2018 Christophe Giboudeaux <christophe@krop.fr> | |
# | |
# Redistribution and use in source and binary forms, with or without | |
# modification, are permitted provided that the following conditions | |
# are met: | |
# | |
# 1. Redistributions of source code must retain the copyright | |
# notice, this list of conditions and the following disclaimer. | |
# 2. Redistributions in binary form must reproduce the copyright | |
# notice, this list of conditions and the following disclaimer in the | |
# documentation and/or other materials provided with the distribution. | |
# 3. The name of the author may not be used to endorse or promote products | |
# derived from this software without specific prior written permission. | |
# | |
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | |
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | |
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | |
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
include(CMakeParseArguments) | |
function(ecm_export_symbols target_name) | |
set(options UNSTABLE_ABI) | |
set(oneValueArgs) | |
set(multiValueArgs FIRST_STABLE_VERSION) | |
cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) | |
if(NOT TARGET ${target_name}) | |
message(FATAL_ERROR "ecm_export_symbols was invoked with a non-existent target name. Check your syntax.") | |
endif() | |
# -Wl,--version-script only works with GNU LD | |
if(NOT CMAKE_CXX_COMPILER_ID STREQUAL "GNU") | |
return() | |
endif() | |
# Don't do anything if the target is not a shared library | |
get_target_property(_target_type ${target_name} TYPE) | |
if(NOT "${_target_type}" STREQUAL "SHARED_LIBRARY") | |
return() | |
endif() | |
# If ``target_name`` is an alias, get the aliased target name | |
get_target_property(_real_target_name ${target_name} ALIASED_TARGET) | |
if(_real_target_name) | |
set(target_name "${_real_target_name}") | |
endif() | |
# The target exists and is valid, set the map file name | |
set(_target_map_file "${CMAKE_CURRENT_BINARY_DIR}/${target_name}.map") | |
# Split _target_version to get the major and minor version. | |
get_target_property(_target_version ${target_name} VERSION) | |
if(NOT _target_version) | |
message(FATAL_ERROR "ecm_export_symbols was called before setting the ${_real_target_name} version.") | |
endif() | |
string(REPLACE "." ";" _target_version_list ${_target_version}) | |
list(GET _target_version_list 0 _target_version_major) | |
list(GET _target_version_list 1 _target_version_minor) | |
# i.e: every symbol is 'global' | |
file(WRITE "${_target_map_file}" "${target_name}_${_target_version_major} { global: *; };") | |
# If the ABI is declared unstable, we don't have to call _ecm_generate_compatibility_list() | |
if(NOT ARG_UNSTABLE_ABI) | |
_ecm_generate_compatibility_list() | |
file(APPEND "${_target_map_file}" "${compatibility_list}\n") | |
endif() | |
set_target_properties(${target_name} PROPERTIES LINK_FLAGS "-Wl,--version-script=${CMAKE_CURRENT_BINARY_DIR}/${target_name}.map") | |
endfunction() | |
macro(_ecm_generate_compatibility_list) | |
if(DEFINED ARG_FIRST_STABLE_VERSION) | |
string(REPLACE "." ";" _first_stable_version ${ARG_FIRST_STABLE_VERSION}) | |
list(GET _first_stable_version 0 _first_stable_version_major) | |
list(GET _first_stable_version 1 _first_stable_version_minor) | |
if(NOT ${_target_version_major} EQUAL ${_first_stable_version_major}) | |
message(FATAL_ERROR "The ${target_name} major version and FIRST_STABLE_VERSION major version don't match.") | |
endif() | |
endif() | |
set(compatibility_list) | |
set(_index) | |
if(DEFINED _first_stable_version_minor) | |
set(_index "${_first_stable_version_minor}") | |
else() | |
set(_index "0") | |
endif() | |
set(compatibility_list "${compatibility_list}\n${target_name}_${_target_version_major}.${_index} {} ${target_name}_${_target_version_major};") | |
# The other items shall be backward compatible with the previous version | |
while(_index LESS _target_version_minor) | |
math(EXPR _next_index ${_index}+1) | |
set(compatibility_list "${compatibility_list}\n${target_name}_${_target_version_major}.${_next_index} {} ${target_name}_${_target_version_major}.${_index};") | |
math(EXPR _index "${_index}+1") | |
endwhile() | |
endmacro() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment