
1. Replace custom 'shared' option with the standard BUILD_SHARED_LIBS flag 2. Replace foreach() calls for source items with target_sources() and generator expression $<JOIN:>. 3. Remove build types definition: makes no sense for single-configuration generators, and is populated automatically for multi-configuration ones. 4. Add feature summary 5. Enahnce compiler flags management for static runtime by utilizing functions from the ucm project 6. Copy almost all options from the Jamfile. 7. If compiler supports C++14, use it. 8. Raise minimum required CMake version to 3.11 and drop bundled FindIconv.cmake
160 lines
6.2 KiB
CMake
160 lines
6.2 KiB
CMake
# This module provides generate_and_install_pkg_config_file() function.
|
|
# The function takes target name and expects a fully configured project, i.e. with set version and
|
|
# description. The function extracts interface libraries, include dirs, definitions and options
|
|
# from the target and generates pkg-config file with install() command
|
|
# The function expands imported targets and generator expressions
|
|
|
|
# save the current file dir for later use in the generate_and_install_pkg_config_file() function
|
|
set(_GeneratePkGConfigDir "${CMAKE_CURRENT_LIST_DIR}/GeneratePkgConfig")
|
|
|
|
include(GNUInstallDirs)
|
|
|
|
function(_get_target_property_merging_configs _var_name _target_name _propert_name)
|
|
get_target_property(vals ${_target_name} ${_propert_name})
|
|
if (NOT vals)
|
|
if (CMAKE_BUILD_TYPE)
|
|
list(APPEND configs ${CMAKE_BUILD_TYPE})
|
|
elseif()
|
|
list(APPEND configs ${CMAKE_CONFIGURATION_TYPES})
|
|
endif()
|
|
foreach(cfg ${configs})
|
|
string(TOUPPER "${cfg}" UPPERCFG)
|
|
get_target_property(mapped_configs ${_target_name} "MAP_IMPORTED_CONFIG_${UPPERCFG}")
|
|
if (mapped_configs)
|
|
list(GET "${mapped_configs}" 0 target_cfg)
|
|
else()
|
|
set(target_cfg "${UPPERCFG}")
|
|
endif()
|
|
get_target_property(val_for_cfg ${_target_name} "${_propert_name}_${target_cfg}")
|
|
if (val_for_cfg)
|
|
list(APPEND vals "$<$<CONFIG:${cfg}>:${val_for_cfg}>")
|
|
endif()
|
|
endforeach()
|
|
endif()
|
|
# HACK file(GENERATE), which we use foe expanding generator expressions, is BUILD_INTERFACE,
|
|
# but we need INSTALL_INTERFACE here. As such, let us inter-change them.
|
|
string(REPLACE "$<BUILD_INTERFACE:" "$<TMP_INTERFACE:" vals "${vals}")
|
|
string(REPLACE "$<INSTALL_INTERFACE:" "@CMAKE_INSTALL_PREFIX@/$<BUILD_INTERFACE:" vals "${vals}")
|
|
string(REPLACE "$<TMP_INTERFACE:" "$<INSTALL_INTERFACE:" vals "${vals}")
|
|
set(${_var_name} "${vals}" PARENT_SCOPE)
|
|
endfunction()
|
|
|
|
# This helper function expands imported targets from the provided targets list, collecting their
|
|
# interface link libraries and imported locations, include directories, compile options and definitions
|
|
# into the specified variables
|
|
function(_expand_targets _targets _libraries_var _include_dirs_var _compile_options_var _compile_definitions_var)
|
|
set(_any_target_was_expanded True)
|
|
set(_libs "${${_libraries_var}}")
|
|
set(_includes "${${_include_dirs_var}}")
|
|
set(_defs "${${_compile_definitions_var}}")
|
|
set(_options "${${_compile_options_var}}")
|
|
|
|
list(APPEND _libs "${_targets}")
|
|
|
|
while(_any_target_was_expanded)
|
|
set(_any_target_was_expanded False)
|
|
set(_new_libs "")
|
|
foreach (_dep ${_libs})
|
|
if (TARGET ${_dep})
|
|
set(_any_target_was_expanded True)
|
|
|
|
get_target_property(_type ${_dep} TYPE)
|
|
if ("${_type}" STREQUAL "INTERFACE_LIBRARY")
|
|
# this library may not have IMPORTED_LOCATION property
|
|
set(_imported_location "")
|
|
else()
|
|
_get_target_property_merging_configs(_imported_location ${_dep} IMPORTED_LOCATION)
|
|
endif()
|
|
|
|
_get_target_property_merging_configs(_iface_link_libraries ${_dep} INTERFACE_LINK_LIBRARIES)
|
|
_get_target_property_merging_configs(_iface_include_dirs ${_dep} INTERFACE_INCLUDE_DIRECTORIES)
|
|
_get_target_property_merging_configs(_iface_compile_options ${_dep} INTERFACE_COMPILE_OPTIONS)
|
|
_get_target_property_merging_configs(_iface_definitions ${_dep} INTERFACE_COMPILE_DEFINITIONS)
|
|
|
|
if (_imported_location)
|
|
list(APPEND _new_libs "${_imported_location}")
|
|
endif()
|
|
|
|
if (_iface_link_libraries)
|
|
list(APPEND _new_libs "${_iface_link_libraries}")
|
|
endif()
|
|
|
|
if(_iface_include_dirs)
|
|
list(APPEND _includes "${_iface_include_dirs}")
|
|
endif()
|
|
|
|
if(_iface_compile_options)
|
|
list(APPEND _options "${_iface_compile_options}")
|
|
endif()
|
|
|
|
if(_iface_definitions)
|
|
list(APPEND _defs "${_iface_definitions}")
|
|
endif()
|
|
|
|
list(REMOVE_DUPLICATES _new_libs)
|
|
list(REMOVE_DUPLICATES _includes)
|
|
# Options order is important, thus leave duplicates as they are, skipping duplicates removal
|
|
list(REMOVE_DUPLICATES _defs)
|
|
else()
|
|
list(APPEND _new_libs "${_dep}")
|
|
endif()
|
|
endforeach()
|
|
set(_libs "${_new_libs}")
|
|
endwhile()
|
|
set(${_libraries_var} "${_libs}" PARENT_SCOPE)
|
|
set(${_include_dirs_var} "${_includes}" PARENT_SCOPE)
|
|
set(${_compile_options_var} "${_options}" PARENT_SCOPE)
|
|
set(${_compile_definitions_var} "${_defs}" PARENT_SCOPE)
|
|
endfunction()
|
|
|
|
# Generates and installs a pkg-config file for a given target
|
|
function(generate_and_install_pkg_config_file _target)
|
|
# collect target properties
|
|
_expand_targets(${_target}
|
|
_interface_link_libraries _interface_include_dirs
|
|
_interface_compile_options _interface_definitions)
|
|
|
|
get_target_property(_output_name ${_target} OUTPUT_NAME)
|
|
if (NOT _output_name)
|
|
set(_output_name "${_target}")
|
|
endif()
|
|
|
|
# TODO make it robust
|
|
set(_output_name "lib${_output_name}")
|
|
|
|
# remove standard include directories
|
|
foreach(d IN LISTS CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES)
|
|
list(REMOVE_ITEM _interface_include_dirs "${d}")
|
|
endforeach()
|
|
|
|
set(_generate_target_dir "${CMAKE_CURRENT_BINARY_DIR}/${_target}-pkgconfig")
|
|
set(_pkg_config_file_template_filename "${_GeneratePkGConfigDir}/pkg-config.cmake.in")
|
|
|
|
# put target and project properties into a file
|
|
configure_file("${_GeneratePkGConfigDir}/target-compile-settings.cmake.in"
|
|
"${_generate_target_dir}/compile-settings.cmake" @ONLY)
|
|
|
|
get_property(_isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
|
|
if (NOT _isMultiConfig)
|
|
set(_variables_file_name "${_generate_target_dir}/compile-settings-expanded.cmake")
|
|
|
|
file(GENERATE OUTPUT "${_variables_file_name}" INPUT "${_generate_target_dir}/compile-settings.cmake")
|
|
|
|
configure_file("${_GeneratePkGConfigDir}/generate-pkg-config.cmake.in"
|
|
"${_generate_target_dir}/generate-pkg-config.cmake" @ONLY)
|
|
|
|
install(SCRIPT "${_generate_target_dir}/generate-pkg-config.cmake")
|
|
else()
|
|
foreach(cfg IN LISTS CMAKE_CONFIGURATION_TYPES)
|
|
set(_variables_file_name "${_generate_target_dir}/${cfg}/compile-settings-expanded.cmake")
|
|
|
|
file(GENERATE OUTPUT "${_variables_file_name}" INPUT "${_generate_target_dir}/compile-settings.cmake" CONDITION "$<CONFIG:${cfg}>")
|
|
|
|
configure_file("${_GeneratePkGConfigDir}/generate-pkg-config.cmake.in"
|
|
"${_generate_target_dir}/${cfg}/generate-pkg-config.cmake" @ONLY)
|
|
|
|
install(SCRIPT "${_generate_target_dir}/${cfg}/generate-pkg-config.cmake")
|
|
endforeach()
|
|
endif()
|
|
endfunction()
|