1a24b424ef
Currently "cmake -G Ninja" complains about "multiple rules generate src/libssh_dev.map", because the target has the same name as the output of the custom command. Signed-off-by: DDoSolitary <DDoSolitary@gmail.com> Reviewed-by: Jakub Jelen <jjelen@redhat.com> Reviewed-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
493 строки
15 KiB
CMake
493 строки
15 KiB
CMake
#
|
|
# Copyright (c) 2018 Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
|
|
#
|
|
# Redistribution and use is allowed according to the terms of the New
|
|
# BSD license.
|
|
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
|
#
|
|
|
|
#.rst:
|
|
# FindABIMap
|
|
# ----------
|
|
#
|
|
# This file provides functions to generate the symbol version script. It uses
|
|
# the ``abimap`` tool to generate and update the linker script file. It can be
|
|
# installed by calling::
|
|
#
|
|
# $ pip install abimap
|
|
#
|
|
# The ``function generate_map_file`` generates a symbol version script
|
|
# containing the provided symbols. It defines a custom command which sets
|
|
# ``target_name`` as its ``OUTPUT``.
|
|
#
|
|
# The experimental function ``extract_symbols()`` is provided as a simple
|
|
# parser to extract the symbols from C header files. It simply extracts symbols
|
|
# followed by an opening '``(``'. It is recommended to use a filter pattern to
|
|
# select the lines to be considered. It defines a custom command which sets
|
|
# ``target_name`` as its output.
|
|
#
|
|
# The helper function ``get_files_list()`` is provided to find files given a
|
|
# name pattern. It defines a custom command which sets ``target_name`` as its
|
|
# output.
|
|
#
|
|
# Functions provided
|
|
# ------------------
|
|
#
|
|
# ::
|
|
#
|
|
# generate_map_file(target_name
|
|
# RELEASE_NAME_VERSION release_name
|
|
# SYMBOLS symbols_target
|
|
# [CURRENT_MAP cur_map]
|
|
# [FINAL]
|
|
# [BREAK_ABI]
|
|
# [COPY_TO output]
|
|
# )
|
|
#
|
|
# ``target_name``:
|
|
# Required, expects the name of the file to receive the generated symbol
|
|
# version script. It should be added as a dependency for the library. Use the
|
|
# linker option ``--version-script filename`` to add the version information
|
|
# to the symbols when building the library.
|
|
#
|
|
# ``RELEASE_NAME_VERSION``:
|
|
# Required, expects a string containing the name and version information to be
|
|
# added to the symbols in the format ``lib_name_1_2_3``.
|
|
#
|
|
# ``SYMBOLS``:
|
|
# Required, expects a target with the property ``LIST_FILE`` containing a path
|
|
# to a file containing the list of symbols to be added to the symbol version
|
|
# script.
|
|
#
|
|
# ``CURRENT_MAP``:
|
|
# Optional. If given, the new set of symbols will be checked against the
|
|
# ones contained in the ``cur_map`` file and updated properly. If an
|
|
# incompatible change is detected and ``BREAK_ABI`` is not defined, the build
|
|
# will fail.
|
|
#
|
|
# ``FINAL``:
|
|
# Optional. If given, will provide the ``--final`` option to ``abimap`` tool,
|
|
# which will mark the modified release in the symbol version script with a
|
|
# special comment, preventing later changes. This option should be set when
|
|
# creating a library release and the resulting map file should be stored with
|
|
# the source code.
|
|
#
|
|
# ``BREAK_ABI``:
|
|
# Optional. If provided, will use ``abimap`` ``--allow-abi-break`` option, which
|
|
# accepts incompatible changes to the set of symbols. This is necessary if any
|
|
# previously existing symbol were removed.
|
|
#
|
|
# ``COPY_TO``:
|
|
# Optional, expects a string containing the path to where the generated
|
|
# map file will be copied.
|
|
#
|
|
# Example:
|
|
#
|
|
# .. code-block:: cmake
|
|
#
|
|
# find_package(ABIMap)
|
|
# generate_map_file("lib.map"
|
|
# RELEASE_NAME_VERSION "lib_1_0_0"
|
|
# SYMBOLS symbols
|
|
# )
|
|
#
|
|
# Where the target ``symbols`` has its property ``LIST_FILE`` set to the path to
|
|
# a file containing::
|
|
#
|
|
# ``symbol1``
|
|
# ``symbol2``
|
|
#
|
|
# This example would result in the symbol version script to be created in
|
|
# ``${CMAKE_CURRENT_BINARY_DIR}/lib.map`` containing the provided symbols.
|
|
#
|
|
# ::
|
|
#
|
|
# get_files_list(target_name
|
|
# DIRECTORIES dir1 [dir2 ...]
|
|
# FILES_PATTERNS exp1 [exp2 ...]
|
|
# [COPY_TO output]
|
|
# )
|
|
#
|
|
# ``target_name``:
|
|
# Required, expects the name of the target to be created. A file named as
|
|
# ``${target_name}.list`` will be created in
|
|
# ``${CMAKE_CURRENT_BINARY_DIR}`` to receive the list of files found.
|
|
#
|
|
# ``DIRECTORIES``:
|
|
# Required, expects a list of directories paths. Only absolute paths are
|
|
# supported.
|
|
#
|
|
# ``FILES_PATTERN``:
|
|
# Required, expects a list of matching expressions to find the files to be
|
|
# considered in the directories.
|
|
#
|
|
# ``COPY_TO``:
|
|
# Optional, expects a string containing the path to where the file containing
|
|
# the list of files will be copied.
|
|
#
|
|
# This command searches the directories provided in ``DIRECTORIES`` for files
|
|
# matching any of the patterns provided in ``FILES_PATTERNS``. The obtained list
|
|
# is written to the path specified by ``output``. A target named ``target_name``
|
|
# will be created and its property ``LIST_FILE`` will be set to contain
|
|
# ``${CMAKE_CURRENT_BINARY_DIR}/${target_name}.list``
|
|
#
|
|
# Example:
|
|
#
|
|
# .. code-block:: cmake
|
|
#
|
|
# find_package(ABIMap)
|
|
# get_files_list(target
|
|
# DIRECTORIES "/include/mylib"
|
|
# FILES_PATTERNS "*.h"
|
|
# COPY_TO "my_list.txt"
|
|
# )
|
|
#
|
|
# Consider that ``/include/mylib`` contains 3 files, ``h1.h``, ``h2.h``, and
|
|
# ``h3.hpp``
|
|
#
|
|
# Will result in a file ``my_list.txt`` containing::
|
|
#
|
|
# ``h1.h;h2.h``
|
|
#
|
|
# And the target ``target`` will have its property ``LIST_FILE`` set to contain
|
|
# ``${CMAKE_CURRENT_BINARY_DIR}/target.list``
|
|
#
|
|
# ::
|
|
#
|
|
# extract_symbols(target_name
|
|
# HEADERS_LIST headers_list_target
|
|
# [FILTER_PATTERN pattern]
|
|
# [COPY_TO output]
|
|
# )
|
|
#
|
|
# ``target_name``:
|
|
# Required, expects the name of the target to be created. A file named after
|
|
# the string given in ``target_name`` will be created in
|
|
# ``${CMAKE_CURRENT_BINARY_DIR}`` to receive the list of symbols.
|
|
#
|
|
# ``HEADERS_LIST``:
|
|
# Required, expects a target with the property ``LIST_FILE`` set, containing a
|
|
# file path. Such file must contain a list of files paths.
|
|
#
|
|
# ``FILTER_PATTERN``:
|
|
# Optional, expects a string. Only the lines containing the filter pattern
|
|
# will be considered.
|
|
#
|
|
# ``COPY_TO``:
|
|
# Optional, expects a string containing the path to where the file containing
|
|
# the found symbols will be copied.
|
|
#
|
|
# This command extracts the symbols from the files listed in
|
|
# ``headers_list`` and write them on the ``output`` file. If ``pattern``
|
|
# is provided, then only the lines containing the string given in ``pattern``
|
|
# will be considered. It is recommended to provide a ``FILTER_PATTERN`` to mark
|
|
# the lines containing exported function declaration, since this function is
|
|
# experimental and can return wrong symbols when parsing the header files. A
|
|
# target named ``target_name`` will be created with the property ``LIST_FILE``
|
|
# set to contain ``${CMAKE_CURRENT_BINARY_DIR}/${target_name}.list``.
|
|
#
|
|
# Example:
|
|
#
|
|
# .. code-block:: cmake
|
|
#
|
|
# find_package(ABIMap)
|
|
# extract_symbols("lib.symbols"
|
|
# HEADERS_LIST "headers_target"
|
|
# FILTER_PATTERN "API_FUNCTION"
|
|
# )
|
|
#
|
|
# Where ``LIST_FILE`` property in ``headers_target`` points to a file
|
|
# containing::
|
|
#
|
|
# header1.h;header2.h
|
|
#
|
|
# Where ``header1.h`` contains::
|
|
#
|
|
# API_FUNCTION int exported_func1(int a, int b);
|
|
#
|
|
# ``header2.h`` contains::
|
|
#
|
|
# API_FUNCTION int exported_func2(int a);
|
|
#
|
|
# int private_func2(int b);
|
|
#
|
|
# Will result in a file ``lib.symbols.list`` in ``${CMAKE_CURRENT_BINARY_DIR}``
|
|
# containing::
|
|
#
|
|
# ``exported_func1``
|
|
# ``exported_func2``
|
|
#
|
|
|
|
# Search for python which is required
|
|
if (ABIMap_FIND_REQURIED)
|
|
find_package(PythonInterp REQUIRED)
|
|
else()
|
|
find_package(PythonInterp)
|
|
endif()
|
|
|
|
|
|
if (PYTHONINTERP_FOUND)
|
|
# Search for abimap tool used to generate the map files
|
|
find_program(ABIMAP_EXECUTABLE NAMES abimap DOC "path to the abimap executable")
|
|
mark_as_advanced(ABIMAP_EXECUTABLE)
|
|
|
|
if (NOT ABIMAP_EXECUTABLE AND UNIX)
|
|
message(STATUS "Could not find `abimap` in PATH."
|
|
" It can be found in PyPI as `abimap`"
|
|
" (try `pip install abimap`)")
|
|
endif ()
|
|
|
|
if (ABIMAP_EXECUTABLE)
|
|
# Get the abimap version
|
|
execute_process(COMMAND ${ABIMAP_EXECUTABLE} version
|
|
OUTPUT_VARIABLE ABIMAP_VERSION_STRING
|
|
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
|
|
|
# If the version string starts with abimap-, strip it
|
|
if ("abimap" STRLESS_EQUAL ${ABIMAP_VERSION_STRING})
|
|
string(REGEX REPLACE "abimap-" "" ABIMAP_VERSION_STRING "${ABIMAP_VERSION_STRING}")
|
|
endif()
|
|
endif()
|
|
|
|
include(FindPackageHandleStandardArgs)
|
|
find_package_handle_standard_args(ABIMap
|
|
REQUIRED_VARS ABIMAP_EXECUTABLE
|
|
VERSION_VAR ABIMAP_VERSION_STRING)
|
|
endif()
|
|
|
|
|
|
if (ABIMAP_FOUND)
|
|
|
|
# Define helper scripts
|
|
set(_EXTRACT_SYMBOLS_SCRIPT ${CMAKE_CURRENT_LIST_DIR}/ExtractSymbols.cmake)
|
|
set(_GENERATE_MAP_SCRIPT ${CMAKE_CURRENT_LIST_DIR}/GenerateMap.cmake)
|
|
set(_GET_FILES_LIST_SCRIPT ${CMAKE_CURRENT_LIST_DIR}/GetFilesList.cmake)
|
|
|
|
function(get_file_list _TARGET_NAME)
|
|
|
|
set(one_value_arguments
|
|
COPY_TO
|
|
)
|
|
|
|
set(multi_value_arguments
|
|
DIRECTORIES
|
|
FILES_PATTERNS
|
|
)
|
|
|
|
cmake_parse_arguments(_get_files_list
|
|
""
|
|
"${one_value_arguments}"
|
|
"${multi_value_arguments}"
|
|
${ARGN}
|
|
)
|
|
|
|
# The DIRS argument is required
|
|
if (NOT DEFINED _get_files_list_DIRECTORIES)
|
|
message(FATAL_ERROR "No directories paths provided. Provide a list of"
|
|
" directories paths containing header files.")
|
|
endif()
|
|
|
|
# The FILES_PATTERNS argument is required
|
|
if (NOT DEFINED _get_files_list_FILES_PATTERNS)
|
|
message(FATAL_ERROR "No matching expressions provided. Provide a list"
|
|
" of matching patterns for the header files.")
|
|
endif()
|
|
|
|
set(_FILES_LIST_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR}/${_TARGET_NAME}.list)
|
|
|
|
get_filename_component(_get_files_list_OUTPUT_PATH
|
|
"${_FILES_LIST_OUTPUT_PATH}"
|
|
ABSOLUTE)
|
|
|
|
add_custom_target(
|
|
${_TARGET_NAME}_int ALL
|
|
COMMAND ${CMAKE_COMMAND}
|
|
-DOUTPUT_PATH=${_get_files_list_OUTPUT_PATH}
|
|
-DDIRECTORIES=${_get_files_list_DIRECTORIES}
|
|
-DFILES_PATTERNS=${_get_files_list_FILES_PATTERNS}
|
|
-P ${_GET_FILES_LIST_SCRIPT}
|
|
COMMENT
|
|
"Searching for files"
|
|
VERBATIM
|
|
)
|
|
|
|
if (DEFINED _get_files_list_COPY_TO)
|
|
# Copy the generated file back to the COPY_TO
|
|
add_custom_target(${_TARGET_NAME} ALL
|
|
COMMAND
|
|
${CMAKE_COMMAND} -E copy_if_different
|
|
${_FILES_LIST_OUTPUT_PATH} ${_get_files_list_COPY_TO}
|
|
DEPENDS ${_TARGET_NAME}_int
|
|
COMMENT "Copying ${_TARGET_NAME} to ${_get_files_list_COPY_TO}"
|
|
VERBATIM
|
|
)
|
|
else()
|
|
add_custom_target(${_TARGET_NAME} ALL
|
|
DEPENDS ${_TARGET_NAME}_int
|
|
)
|
|
endif()
|
|
|
|
set_target_properties(${_TARGET_NAME}
|
|
PROPERTIES LIST_FILE ${_FILES_LIST_OUTPUT_PATH}
|
|
)
|
|
|
|
endfunction()
|
|
|
|
function(extract_symbols _TARGET_NAME)
|
|
|
|
set(one_value_arguments
|
|
FILTER_PATTERN
|
|
HEADERS_LIST
|
|
COPY_TO
|
|
)
|
|
|
|
set(multi_value_arguments
|
|
)
|
|
|
|
cmake_parse_arguments(_extract_symbols
|
|
""
|
|
"${one_value_arguments}"
|
|
"${multi_value_arguments}"
|
|
${ARGN}
|
|
)
|
|
|
|
# The HEADERS_LIST_FILE argument is required
|
|
if (NOT DEFINED _extract_symbols_HEADERS_LIST)
|
|
message(FATAL_ERROR "No target provided in HEADERS_LIST. Provide a"
|
|
" target with the property LIST_FILE set as the"
|
|
" path to the file containing the list of headers.")
|
|
endif()
|
|
|
|
get_filename_component(_SYMBOLS_OUTPUT_PATH
|
|
"${CMAKE_CURRENT_BINARY_DIR}/${_TARGET_NAME}.list"
|
|
ABSOLUTE
|
|
)
|
|
|
|
get_target_property(_HEADERS_LIST_FILE
|
|
${_extract_symbols_HEADERS_LIST}
|
|
LIST_FILE
|
|
)
|
|
|
|
add_custom_target(
|
|
${_TARGET_NAME}_int ALL
|
|
COMMAND ${CMAKE_COMMAND}
|
|
-DOUTPUT_PATH=${_SYMBOLS_OUTPUT_PATH}
|
|
-DHEADERS_LIST_FILE=${_HEADERS_LIST_FILE}
|
|
-DFILTER_PATTERN=${_extract_symbols_FILTER_PATTERN}
|
|
-P ${_EXTRACT_SYMBOLS_SCRIPT}
|
|
DEPENDS ${_extract_symbols_HEADERS_LIST}
|
|
COMMENT "Extracting symbols from headers"
|
|
VERBATIM
|
|
)
|
|
|
|
if (DEFINED _extract_symbols_COPY_TO)
|
|
# Copy the generated file back to the COPY_TO
|
|
add_custom_target(${_TARGET_NAME} ALL
|
|
COMMAND
|
|
${CMAKE_COMMAND} -E copy_if_different
|
|
${_SYMBOLS_OUTPUT_PATH} ${_extract_symbols_COPY_TO}
|
|
DEPENDS ${_TARGET_NAME}_int
|
|
COMMENT "Copying ${_TARGET_NAME} to ${_extract_symbols_COPY_TO}"
|
|
VERBATIM
|
|
)
|
|
else()
|
|
add_custom_target(${_TARGET_NAME} ALL
|
|
DEPENDS ${_TARGET_NAME}_int
|
|
)
|
|
endif()
|
|
|
|
set_target_properties(${_TARGET_NAME}
|
|
PROPERTIES LIST_FILE ${_SYMBOLS_OUTPUT_PATH}
|
|
)
|
|
|
|
endfunction()
|
|
|
|
function(generate_map_file _TARGET_NAME)
|
|
|
|
set(options
|
|
FINAL
|
|
BREAK_ABI
|
|
)
|
|
|
|
set(one_value_arguments
|
|
RELEASE_NAME_VERSION
|
|
SYMBOLS
|
|
CURRENT_MAP
|
|
COPY_TO
|
|
)
|
|
|
|
set(multi_value_arguments
|
|
)
|
|
|
|
cmake_parse_arguments(_generate_map_file
|
|
"${options}"
|
|
"${one_value_arguments}"
|
|
"${multi_value_arguments}"
|
|
${ARGN}
|
|
)
|
|
|
|
if (NOT DEFINED _generate_map_file_SYMBOLS)
|
|
message(FATAL_ERROR "No target provided in SYMBOLS. Provide a target"
|
|
" with the property LIST_FILE set as the path to"
|
|
" the file containing the list of symbols.")
|
|
endif()
|
|
|
|
if (NOT DEFINED _generate_map_file_RELEASE_NAME_VERSION)
|
|
message(FATAL_ERROR "Release name and version not provided."
|
|
" (e.g. libname_1_0_0)")
|
|
endif()
|
|
|
|
|
|
get_target_property(_SYMBOLS_FILE
|
|
${_generate_map_file_SYMBOLS}
|
|
LIST_FILE
|
|
)
|
|
|
|
# Set generated map file path
|
|
get_filename_component(_MAP_OUTPUT_PATH
|
|
"${CMAKE_CURRENT_BINARY_DIR}/${_TARGET_NAME}"
|
|
ABSOLUTE
|
|
)
|
|
|
|
add_custom_target(
|
|
${_TARGET_NAME}_int ALL
|
|
COMMAND ${CMAKE_COMMAND}
|
|
-DABIMAP_EXECUTABLE=${ABIMAP_EXECUTABLE}
|
|
-DSYMBOLS=${_SYMBOLS_FILE}
|
|
-DCURRENT_MAP=${_generate_map_file_CURRENT_MAP}
|
|
-DOUTPUT_PATH=${_MAP_OUTPUT_PATH}
|
|
-DFINAL=${_generate_map_file_FINAL}
|
|
-DBREAK_ABI=${_generate_map_file_BREAK_ABI}
|
|
-DRELEASE_NAME_VERSION=${_generate_map_file_RELEASE_NAME_VERSION}
|
|
-P ${_GENERATE_MAP_SCRIPT}
|
|
DEPENDS ${_generate_map_file_SYMBOLS}
|
|
COMMENT "Generating the map ${_TARGET_NAME}"
|
|
VERBATIM
|
|
)
|
|
|
|
# Add a custom command setting the map as OUTPUT to allow it to be added as
|
|
# a generated source
|
|
add_custom_command(
|
|
OUTPUT ${_MAP_OUTPUT_PATH}
|
|
DEPENDS ${_TARGET_NAME}_copy
|
|
)
|
|
|
|
if (DEFINED _generate_map_file_COPY_TO)
|
|
# Copy the generated map back to the COPY_TO
|
|
add_custom_target(${_TARGET_NAME}_copy ALL
|
|
COMMAND
|
|
${CMAKE_COMMAND} -E copy_if_different ${_MAP_OUTPUT_PATH}
|
|
${_generate_map_file_COPY_TO}
|
|
DEPENDS ${_TARGET_NAME}_int
|
|
COMMENT "Copying ${_MAP_OUTPUT_PATH} to ${_generate_map_file_COPY_TO}"
|
|
VERBATIM
|
|
)
|
|
else()
|
|
add_custom_target(${_TARGET_NAME}_copy ALL
|
|
DEPENDS ${_TARGET_NAME}_int
|
|
)
|
|
endif()
|
|
endfunction()
|
|
|
|
endif (ABIMAP_FOUND)
|