395 строки
12 KiB
CMake
395 строки
12 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_file
|
||
|
# [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 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 "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 after
|
||
|
# the string given in ``target_name`` 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.
|
||
|
#
|
||
|
# ``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``.
|
||
|
#
|
||
|
# 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``
|
||
|
#
|
||
|
# ::
|
||
|
#
|
||
|
# extract_symbols(target_name
|
||
|
# HEADERS_LIST_FILE headers_list
|
||
|
# [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_FILE``:
|
||
|
# Required, expects a path to a file containing the list of header files to be
|
||
|
# parsed.
|
||
|
#
|
||
|
# ``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.
|
||
|
#
|
||
|
# Example:
|
||
|
#
|
||
|
# .. code-block:: cmake
|
||
|
#
|
||
|
# find_package(ABIMap)
|
||
|
# extract_symbols("lib.symbols"
|
||
|
# HEADERS_LIST_FILE "headers_list"
|
||
|
# FILTER_PATTERN "API_FUNCTION"
|
||
|
# )
|
||
|
#
|
||
|
# Where headers_list contains::
|
||
|
#
|
||
|
# 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`` in ``${CMAKE_CURRENT_BINARY_DIR}`` containing::
|
||
|
#
|
||
|
# ``exported_func1;exported_func2``
|
||
|
#
|
||
|
|
||
|
# Search for python which is required
|
||
|
find_package(PythonInterp REQUIRED)
|
||
|
|
||
|
# 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`)")
|
||
|
else ()
|
||
|
set(ABIMAP_FOUND TRUE)
|
||
|
endif ()
|
||
|
|
||
|
# 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()
|
||
|
|
||
|
get_filename_component(_get_files_list_OUTPUT_PATH
|
||
|
"${CMAKE_CURRENT_BINARY_DIR}/${_TARGET_NAME}"
|
||
|
ABSOLUTE
|
||
|
)
|
||
|
|
||
|
add_custom_command(
|
||
|
OUTPUT ${_TARGET_NAME}
|
||
|
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"
|
||
|
)
|
||
|
|
||
|
if (DEFINED _get_files_list_COPY_TO)
|
||
|
# Copy the generated file back to the COPY_TO
|
||
|
add_custom_target(copy_headers_list_${TARGET_NAME} ALL
|
||
|
COMMAND
|
||
|
${CMAKE_COMMAND} -E copy_if_different ${_TARGET_NAME} ${_get_files_list_COPY_TO}
|
||
|
DEPENDS "${_TARGET_NAME}"
|
||
|
COMMENT "Copying ${_TARGET_NAME} to ${_get_files_list_COPY_TO}"
|
||
|
)
|
||
|
endif()
|
||
|
endfunction()
|
||
|
|
||
|
function(extract_symbols _TARGET_NAME)
|
||
|
|
||
|
set(one_value_arguments
|
||
|
FILTER_PATTERN
|
||
|
HEADERS_LIST_FILE
|
||
|
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_FILE)
|
||
|
message(FATAL_ERROR "No header files given. Provide a list of header"
|
||
|
" files containing exported symbols."
|
||
|
)
|
||
|
endif()
|
||
|
|
||
|
get_filename_component(_extract_symbols_OUTPUT_PATH
|
||
|
"${CMAKE_CURRENT_BINARY_DIR}/${_TARGET_NAME}"
|
||
|
ABSOLUTE
|
||
|
)
|
||
|
|
||
|
add_custom_target(${_TARGET_NAME}
|
||
|
COMMAND ${CMAKE_COMMAND}
|
||
|
-DOUTPUT_PATH="${_extract_symbols_OUTPUT_PATH}"
|
||
|
-DHEADERS_LIST_FILE="${_extract_symbols_HEADERS_LIST_FILE}"
|
||
|
-DFILTER_PATTERN=${_extract_symbols_FILTER_PATTERN}
|
||
|
-P ${_EXTRACT_SYMBOLS_SCRIPT}
|
||
|
DEPENDS ${_extract_symbols_HEADERS_LIST_FILE}
|
||
|
COMMENT "Extracting symbols from headers")
|
||
|
|
||
|
if (DEFINED _extract_symbols_COPY_TO)
|
||
|
file(READ "${CMAKE_CURRENT_BINARY_DIR}/${_TARGET_NAME}" SYMBOL_CONTENT)
|
||
|
string(REPLACE ";" "\n" SYMBOL_CONTENT_NEW "${SYMBOL_CONTENT}")
|
||
|
file(WRITE "${_extract_symbols_COPY_TO}" "${SYMBOL_CONTENT_NEW}")
|
||
|
endif()
|
||
|
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 symbols file provided."
|
||
|
)
|
||
|
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()
|
||
|
|
||
|
# Set generated map file path
|
||
|
get_filename_component(_generate_map_file_OUTPUT_PATH
|
||
|
"${CMAKE_CURRENT_BINARY_DIR}/${_TARGET_NAME}"
|
||
|
ABSOLUTE
|
||
|
)
|
||
|
|
||
|
add_custom_command(
|
||
|
OUTPUT ${_TARGET_NAME}
|
||
|
COMMAND ${CMAKE_COMMAND}
|
||
|
-DABIMAP_EXECUTABLE=${ABIMAP_EXECUTABLE}
|
||
|
-DSYMBOLS="${_generate_map_file_SYMBOLS}"
|
||
|
-DCURRENT_MAP=${_generate_map_file_CURRENT_MAP}
|
||
|
-DOUTPUT_PATH="${_generate_map_file_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}"
|
||
|
)
|
||
|
|
||
|
if (DEFINED _generate_map_file_COPY_TO)
|
||
|
# Copy the generated map back to the COPY_TO
|
||
|
add_custom_target(copy_map_${_TARGET_NAME} ALL
|
||
|
COMMAND
|
||
|
${CMAKE_COMMAND} -E copy_if_different ${_TARGET_NAME} ${_generate_map_file_COPY_TO}
|
||
|
DEPENDS "${_TARGET_NAME}"
|
||
|
COMMENT "Copying ${_TARGET_NAME} to ${_generate_map_file_COPY_TO}"
|
||
|
)
|
||
|
endif()
|
||
|
endfunction()
|