diff options
author | Brad King <brad.king@kitware.com> | 2022-05-23 13:00:44 (GMT) |
---|---|---|
committer | Kitware Robot <kwrobot@kitware.com> | 2022-05-23 13:01:00 (GMT) |
commit | 1b30958719ea742d66fa97717f66382627472b1e (patch) | |
tree | 071744ca898099551f35062c2860b210eb44cf1d | |
parent | cf68f3eb8bd18ac53fbb95181f7f49e021f903bf (diff) | |
parent | 020976d637bc85ed688d57bb79828bc153a5369b (diff) | |
download | CMake-1b30958719ea742d66fa97717f66382627472b1e.zip CMake-1b30958719ea742d66fa97717f66382627472b1e.tar.gz CMake-1b30958719ea742d66fa97717f66382627472b1e.tar.bz2 |
Merge topic 'pkgconfig-static-libs'
020976d637 FindPkgConfig: Populate _STATIC_LINK_LIBRARIES. Add STATIC_TARGET.
3c5cc79adb Tests: De-duplicate some code in RunCMake.FindPkgConfig
5cfbc76371 FindPkgConfig: Fix parsing of backslash-escaped spaces in pkg-config output
Acked-by: Kitware Robot <kwrobot@kitware.com>
Acked-by: buildbot <buildbot@kitware.com>
Merge-request: !7070
9 files changed, 332 insertions, 136 deletions
diff --git a/Help/release/dev/pkgconfig-static-libs.rst b/Help/release/dev/pkgconfig-static-libs.rst new file mode 100644 index 0000000..8f7ab0e --- /dev/null +++ b/Help/release/dev/pkgconfig-static-libs.rst @@ -0,0 +1,7 @@ +pkgconfig-static-libs +--------------------- + +* The :module:`FindPkgConfig` module learned to find static libraries + in addition to the default search for shared libraries. + :command:`pkg_check_modules` gained a ``STATIC_TARGET`` option + to make the imported target reference static libraries. diff --git a/Modules/FindPkgConfig.cmake b/Modules/FindPkgConfig.cmake index ab8af3e..854e0e1 100644 --- a/Modules/FindPkgConfig.cmake +++ b/Modules/FindPkgConfig.cmake @@ -143,7 +143,9 @@ macro(_pkgconfig_invoke _pkglist _prefix _varname _regexp) string(REGEX REPLACE "${_regexp}" " " _pkgconfig_invoke_result "${_pkgconfig_invoke_result}") endif() - separate_arguments(_pkgconfig_invoke_result) + # pkg-config can represent "spaces within an argument" by backslash-escaping the space. + # UNIX_COMMAND mode treats backslash-escaped spaces as "not a space that delimits arguments". + separate_arguments(_pkgconfig_invoke_result UNIX_COMMAND "${_pkgconfig_invoke_result}") #message(STATUS " ${_varname} ... ${_pkgconfig_invoke_result}") set(_pkgconfig_${_varname} ${_pkgconfig_invoke_result}) @@ -167,13 +169,14 @@ macro(_pkgconfig_invoke_dyn _pkglist _prefix _varname cleanup_regexp) endmacro() # Splits given arguments into options and a package list -macro(_pkgconfig_parse_options _result _is_req _is_silent _no_cmake_path _no_cmake_environment_path _imp_target _imp_target_global) +macro(_pkgconfig_parse_options _result _is_req _is_silent _no_cmake_path _no_cmake_environment_path _imp_target _imp_target_global _static_target) set(${_is_req} 0) set(${_is_silent} 0) set(${_no_cmake_path} 0) set(${_no_cmake_environment_path} 0) set(${_imp_target} 0) set(${_imp_target_global} 0) + set(${_static_target} 0) if(DEFINED PKG_CONFIG_USE_CMAKE_PREFIX_PATH) if(NOT PKG_CONFIG_USE_CMAKE_PREFIX_PATH) set(${_no_cmake_path} 1) @@ -203,6 +206,9 @@ macro(_pkgconfig_parse_options _result _is_req _is_silent _no_cmake_path _no_cma if (_pkg STREQUAL "GLOBAL") set(${_imp_target_global} 1) endif() + if (_pkg STREQUAL "STATIC_TARGET") + set(${_static_target} 1) + endif() endforeach() if (${_imp_target_global} AND NOT ${_imp_target}) @@ -215,6 +221,7 @@ macro(_pkgconfig_parse_options _result _is_req _is_silent _no_cmake_path _no_cma list(REMOVE_ITEM ${_result} "NO_CMAKE_PATH") list(REMOVE_ITEM ${_result} "NO_CMAKE_ENVIRONMENT_PATH") list(REMOVE_ITEM ${_result} "IMPORTED_TARGET") + list(REMOVE_ITEM ${_result} "STATIC_TARGET") list(REMOVE_ITEM ${_result} "GLOBAL") endmacro() @@ -246,7 +253,7 @@ endfunction() # scan the LDFLAGS returned by pkg-config for library directories and # libraries, figure out the absolute paths of that libraries in the # given directories -function(_pkg_find_libs _prefix _no_cmake_path _no_cmake_environment_path) +function(_pkg_find_libs _prefix _no_cmake_path _no_cmake_environment_path _static) unset(_libs) unset(_find_opts) @@ -259,9 +266,23 @@ function(_pkg_find_libs _prefix _no_cmake_path _no_cmake_environment_path) list(APPEND _find_opts "NO_CMAKE_ENVIRONMENT_PATH") endif() + if(_static) + set(var_prefix ${_prefix}_STATIC) + set(pkgcfg_lib_prefix pkgcfg_static_lib_${_prefix}) + # reconfigure library prefixes/suffixes so that only static libraries can be found + set(CMAKE_FIND_LIBRARY_PREFIXES "${CMAKE_STATIC_LIBRARY_PREFIX}") + set(CMAKE_FIND_LIBRARY_SUFFIXES "${CMAKE_STATIC_LIBRARY_SUFFIX}") + else() + set(var_prefix ${_prefix}) + set(pkgcfg_lib_prefix pkgcfg_lib_${_prefix}) + # reconfigure library prefixes/suffixes so that only dynamic libraries can be found + set(CMAKE_FIND_LIBRARY_PREFIXES "${CMAKE_SHARED_LIBRARY_PREFIX}") + set(CMAKE_FIND_LIBRARY_SUFFIXES "${CMAKE_SHARED_LIBRARY_SUFFIX}") + endif() + unset(_search_paths) unset(_next_is_framework) - foreach (flag IN LISTS ${_prefix}_LDFLAGS) + foreach (flag IN LISTS ${var_prefix}_LDFLAGS) if (_next_is_framework) list(APPEND _libs "-framework ${flag}") unset(_next_is_framework) @@ -280,61 +301,78 @@ function(_pkg_find_libs _prefix _no_cmake_path _no_cmake_environment_path) continue() endif() + set(lib_var_name ${pkgcfg_lib_prefix}_${_pkg_search}) + if(_search_paths) # Firstly search in -L paths - find_library(pkgcfg_lib_${_prefix}_${_pkg_search} + find_library(${lib_var_name} NAMES ${_pkg_search} HINTS ${_search_paths} NO_DEFAULT_PATH) endif() - find_library(pkgcfg_lib_${_prefix}_${_pkg_search} + find_library(${lib_var_name} NAMES ${_pkg_search} ${_find_opts}) - mark_as_advanced(pkgcfg_lib_${_prefix}_${_pkg_search}) - if(pkgcfg_lib_${_prefix}_${_pkg_search}) - list(APPEND _libs "${pkgcfg_lib_${_prefix}_${_pkg_search}}") + + mark_as_advanced(${lib_var_name}) + if(${lib_var_name}) + list(APPEND _libs "${${lib_var_name}}") else() list(APPEND _libs ${_pkg_search}) endif() endforeach() - set(${_prefix}_LINK_LIBRARIES "${_libs}" PARENT_SCOPE) + set(${var_prefix}_LINK_LIBRARIES "${_libs}" PARENT_SCOPE) endfunction() # create an imported target from all the information returned by pkg-config -function(_pkg_create_imp_target _prefix _imp_target_global) - if (NOT TARGET PkgConfig::${_prefix}) +function(_pkg_create_imp_target _prefix _imp_target_global _var_qualifier) + set(tgt PkgConfig::${_prefix}) + set(var_prefix ${_prefix}${_var_qualifier}) + + if (NOT TARGET ${tgt}) if(${_imp_target_global}) set(_global_opt "GLOBAL") else() unset(_global_opt) endif() - add_library(PkgConfig::${_prefix} INTERFACE IMPORTED ${_global_opt}) + add_library(${tgt} INTERFACE IMPORTED ${_global_opt}) - if(${_prefix}_INCLUDE_DIRS) - set_property(TARGET PkgConfig::${_prefix} PROPERTY - INTERFACE_INCLUDE_DIRECTORIES "${${_prefix}_INCLUDE_DIRS}") + if(${var_prefix}_INCLUDE_DIRS) + set_property(TARGET ${tgt} PROPERTY + INTERFACE_INCLUDE_DIRECTORIES "${${var_prefix}_INCLUDE_DIRS}") endif() - if(${_prefix}_LINK_LIBRARIES) - set_property(TARGET PkgConfig::${_prefix} PROPERTY - INTERFACE_LINK_LIBRARIES "${${_prefix}_LINK_LIBRARIES}") + if(${var_prefix}_LINK_LIBRARIES) + set_property(TARGET ${tgt} PROPERTY + INTERFACE_LINK_LIBRARIES "${${var_prefix}_LINK_LIBRARIES}") endif() - if(${_prefix}_LDFLAGS_OTHER) - set_property(TARGET PkgConfig::${_prefix} PROPERTY - INTERFACE_LINK_OPTIONS "${${_prefix}_LDFLAGS_OTHER}") + if(${var_prefix}_LDFLAGS_OTHER) + set_property(TARGET ${tgt} PROPERTY + INTERFACE_LINK_OPTIONS "${${var_prefix}_LDFLAGS_OTHER}") endif() - if(${_prefix}_CFLAGS_OTHER) - set_property(TARGET PkgConfig::${_prefix} PROPERTY - INTERFACE_COMPILE_OPTIONS "${${_prefix}_CFLAGS_OTHER}") + if(${var_prefix}_CFLAGS_OTHER) + set_property(TARGET ${tgt} PROPERTY + INTERFACE_COMPILE_OPTIONS "${${var_prefix}_CFLAGS_OTHER}") endif() endif() endfunction() # recalculate the dynamic output # this is a macro and not a function so the result of _pkg_find_libs is automatically propagated -macro(_pkg_recalculate _prefix _no_cmake_path _no_cmake_environment_path _imp_target _imp_target_global) - _pkg_find_libs(${_prefix} ${_no_cmake_path} ${_no_cmake_environment_path}) +macro(_pkg_recalculate _prefix _no_cmake_path _no_cmake_environment_path _imp_target _imp_target_global _static_target) + # populate unqualified (shared) series of variables + _pkg_find_libs("${_prefix}" ${_no_cmake_path} ${_no_cmake_environment_path} FALSE) + # populate STATIC_ series of variables + _pkg_find_libs("${_prefix}" ${_no_cmake_path} ${_no_cmake_environment_path} TRUE) + if(${_imp_target}) - _pkg_create_imp_target(${_prefix} ${_imp_target_global}) + if (${_static_target}) + set(var_qualifier "_STATIC") + else() + set(var_qualifier "") + endif() + # create unqualified target, sourced from whichever series of variables is preferred. + # default: source target from unqualified (shared) variables. otherwise STATIC_ variables + _pkg_create_imp_target("${_prefix}" ${_imp_target_global} "${var_qualifier}") endif() endmacro() @@ -503,7 +541,7 @@ function(_pkgconfig_extract_isystem _prefix) endfunction() ### -macro(_pkg_check_modules_internal _is_required _is_silent _no_cmake_path _no_cmake_environment_path _imp_target _imp_target_global _prefix) +macro(_pkg_check_modules_internal _is_required _is_silent _no_cmake_path _no_cmake_environment_path _imp_target _imp_target_global _static_target _prefix) _pkgconfig_unset(${_prefix}_FOUND) _pkgconfig_unset(${_prefix}_VERSION) _pkgconfig_unset(${_prefix}_PREFIX) @@ -639,20 +677,21 @@ macro(_pkg_check_modules_internal _is_required _is_silent _no_cmake_path _no_cma _pkgconfig_invoke_dyn("${_pkg_check_modules_packages}" "${_prefix}" LIBRARY_DIRS "(^| )-L" --libs-only-L ) _pkgconfig_invoke_dyn("${_pkg_check_modules_packages}" "${_prefix}" LDFLAGS "" --libs ) _pkgconfig_invoke_dyn("${_pkg_check_modules_packages}" "${_prefix}" LDFLAGS_OTHER "" --libs-only-other ) - - if (APPLE AND "-framework" IN_LIST ${_prefix}_LDFLAGS_OTHER) - _pkgconfig_extract_frameworks("${_prefix}") - endif() - _pkgconfig_invoke_dyn("${_pkg_check_modules_packages}" "${_prefix}" INCLUDE_DIRS "(^| )(-I|-isystem ?)" --cflags-only-I ) _pkgconfig_invoke_dyn("${_pkg_check_modules_packages}" "${_prefix}" CFLAGS "" --cflags ) _pkgconfig_invoke_dyn("${_pkg_check_modules_packages}" "${_prefix}" CFLAGS_OTHER "" --cflags-only-other ) - if (${_prefix}_CFLAGS_OTHER MATCHES "-isystem") - _pkgconfig_extract_isystem("${_prefix}") - endif () + foreach (qualifier IN ITEMS "" "_STATIC") + set(qual_prefix ${_prefix}${qualifier}) + if (APPLE AND "-framework" IN_LIST ${qual_prefix}_LDFLAGS_OTHER) + _pkgconfig_extract_frameworks("${qual_prefix}") + endif() + if (${qual_prefix}_CFLAGS_OTHER MATCHES "-isystem") + _pkgconfig_extract_isystem("${qual_prefix}") + endif () + endforeach() - _pkg_recalculate("${_prefix}" ${_no_cmake_path} ${_no_cmake_environment_path} ${_imp_target} ${_imp_target_global}) + _pkg_recalculate("${_prefix}" ${_no_cmake_path} ${_no_cmake_environment_path} ${_imp_target} ${_imp_target_global} ${_static_target}) endif() _pkg_restore_path_internal() @@ -676,7 +715,7 @@ endmacro() [REQUIRED] [QUIET] [NO_CMAKE_PATH] [NO_CMAKE_ENVIRONMENT_PATH] - [IMPORTED_TARGET [GLOBAL]] + [IMPORTED_TARGET [GLOBAL] [STATIC_TARGET]] <moduleSpec> [<moduleSpec>...]) When the ``REQUIRED`` argument is given, the command will fail with an error @@ -707,6 +746,13 @@ endmacro() The ``GLOBAL`` argument will make the imported target available in global scope. + .. versionadded:: 3.24 + The ``STATIC_TARGET`` argument will make the + imported target reference the static libraries + reported in ``<XXX>_STATIC_LINK_LIBRARIES``. + Without this option, the imported target + references the ``<XXX>_LINK_LIBRARIES``. + .. versionadded:: 3.15 Non-library linker options reported by ``pkg-config`` are stored in the :prop_tgt:`INTERFACE_LINK_OPTIONS` target property. @@ -738,6 +784,10 @@ endmacro() only the libraries (without the '-l') ``<XXX>_LINK_LIBRARIES`` the libraries and their absolute paths + ``<XXX>_STATIC_LINK_LIBRARIES`` + .. versionadded:: 3.24 + + static libraries and their absolute paths ``<XXX>_LIBRARY_DIRS`` the paths of the libraries (without the '-L') ``<XXX>_LDFLAGS`` @@ -819,12 +869,12 @@ endmacro() XRENDER_STATIC_LIBRARIES=Xrender;X11;pthread;Xau;Xdmcp #]========================================] macro(pkg_check_modules _prefix _module0) - _pkgconfig_parse_options(_pkg_modules _pkg_is_required _pkg_is_silent _no_cmake_path _no_cmake_environment_path _imp_target _imp_target_global "${_module0}" ${ARGN}) + _pkgconfig_parse_options(_pkg_modules _pkg_is_required _pkg_is_silent _no_cmake_path _no_cmake_environment_path _imp_target _imp_target_global _static_target "${_module0}" ${ARGN}) # check cached value if (NOT DEFINED __pkg_config_checked_${_prefix} OR __pkg_config_checked_${_prefix} LESS ${PKG_CONFIG_VERSION} OR NOT ${_prefix}_FOUND OR (NOT "${ARGN}" STREQUAL "" AND NOT "${__pkg_config_arguments_${_prefix}}" STREQUAL "${_module0};${ARGN}") OR ( "${ARGN}" STREQUAL "" AND NOT "${__pkg_config_arguments_${_prefix}}" STREQUAL "${_module0}")) - _pkg_check_modules_internal("${_pkg_is_required}" "${_pkg_is_silent}" ${_no_cmake_path} ${_no_cmake_environment_path} ${_imp_target} ${_imp_target_global} "${_prefix}" ${_pkg_modules}) + _pkg_check_modules_internal("${_pkg_is_required}" "${_pkg_is_silent}" ${_no_cmake_path} ${_no_cmake_environment_path} ${_imp_target} ${_imp_target_global} ${_static_target} "${_prefix}" ${_pkg_modules}) _pkgconfig_set(__pkg_config_checked_${_prefix} ${PKG_CONFIG_VERSION}) if (${_prefix}_FOUND) @@ -832,7 +882,7 @@ macro(pkg_check_modules _prefix _module0) endif() else() if (${_prefix}_FOUND) - _pkg_recalculate("${_prefix}" ${_no_cmake_path} ${_no_cmake_environment_path} ${_imp_target} ${_imp_target_global}) + _pkg_recalculate("${_prefix}" ${_no_cmake_path} ${_no_cmake_environment_path} ${_imp_target} ${_imp_target_global} ${_static_target}) endif() endif() endmacro() @@ -866,7 +916,7 @@ endmacro() pkg_search_module (BAR libxml-2.0 libxml2 libxml>=2) #]========================================] macro(pkg_search_module _prefix _module0) - _pkgconfig_parse_options(_pkg_modules_alt _pkg_is_required _pkg_is_silent _no_cmake_path _no_cmake_environment_path _imp_target _imp_target_global "${_module0}" ${ARGN}) + _pkgconfig_parse_options(_pkg_modules_alt _pkg_is_required _pkg_is_silent _no_cmake_path _no_cmake_environment_path _imp_target _imp_target_global _static_target "${_module0}" ${ARGN}) # check cached value if (NOT DEFINED __pkg_config_checked_${_prefix} OR __pkg_config_checked_${_prefix} LESS ${PKG_CONFIG_VERSION} OR NOT ${_prefix}_FOUND) set(_pkg_modules_found 0) @@ -878,7 +928,7 @@ macro(pkg_search_module _prefix _module0) # iterate through all modules and stop at the first working one. foreach(_pkg_alt ${_pkg_modules_alt}) if(NOT _pkg_modules_found) - _pkg_check_modules_internal(0 1 ${_no_cmake_path} ${_no_cmake_environment_path} ${_imp_target} ${_imp_target_global} "${_prefix}" "${_pkg_alt}") + _pkg_check_modules_internal(0 1 ${_no_cmake_path} ${_no_cmake_environment_path} ${_imp_target} ${_imp_target_global} ${_static_target} "${_prefix}" "${_pkg_alt}") endif() if (${_prefix}_FOUND) @@ -895,7 +945,7 @@ macro(pkg_search_module _prefix _module0) _pkgconfig_set(__pkg_config_checked_${_prefix} ${PKG_CONFIG_VERSION}) elseif (${_prefix}_FOUND) - _pkg_recalculate("${_prefix}" ${_no_cmake_path} ${_no_cmake_environment_path} ${_imp_target} ${_imp_target_global}) + _pkg_recalculate("${_prefix}" ${_no_cmake_path} ${_no_cmake_environment_path} ${_imp_target} ${_imp_target_global} ${_static_target}) endif() endmacro() diff --git a/Tests/RunCMake/FindPkgConfig/FindPkgConfig_IMPORTED_TARGET.cmake b/Tests/RunCMake/FindPkgConfig/FindPkgConfig_IMPORTED_TARGET.cmake index d697fc6..04286cc 100644 --- a/Tests/RunCMake/FindPkgConfig/FindPkgConfig_IMPORTED_TARGET.cmake +++ b/Tests/RunCMake/FindPkgConfig/FindPkgConfig_IMPORTED_TARGET.cmake @@ -1,40 +1,59 @@ -cmake_minimum_required(VERSION 3.12) +cmake_minimum_required(VERSION 3.17) project(FindPkgConfig_IMPORTED_TARGET C) -find_package(PkgConfig REQUIRED) -pkg_check_modules(NCURSES IMPORTED_TARGET QUIET ncurses) +set(shared_lib_prefix "") +set(shared_lib_suffix ".lib") +set(static_lib_prefix "lib") +set(static_lib_suffix ".a") -message(STATUS "source: ${CMAKE_CURRENT_SOURCE_DIR} bin ${CMAKE_CURRENT_BINARY_DIR}") +set(CMAKE_SHARED_LIBRARY_PREFIX ${shared_lib_prefix}) +set(CMAKE_SHARED_LIBRARY_SUFFIX ${shared_lib_suffix}) +set(CMAKE_STATIC_LIBRARY_PREFIX ${static_lib_prefix}) +set(CMAKE_STATIC_LIBRARY_SUFFIX ${static_lib_suffix}) -if (NCURSES_FOUND) - set(tgt PkgConfig::NCURSES) - if (NOT TARGET ${tgt}) - message(FATAL_ERROR "FindPkgConfig found ncurses, but did not create an imported target for it") - endif () - set(prop_found FALSE) - foreach (prop IN ITEMS INTERFACE_INCLUDE_DIRECTORIES INTERFACE_LINK_LIBRARIES INTERFACE_COMPILE_OPTIONS) - get_target_property(value ${tgt} ${prop}) - if (value) - message(STATUS "Found property ${prop} on target: ${value}") - set(prop_found TRUE) +find_package(PkgConfig REQUIRED) + +# to test multiple variations, we must pick unique prefix names (same-named targets are cached for re-use) +set(prefix_uniquifiers 0 1) +# whether to apply STATIC_TARGET argument +set(static_target_args "" STATIC_TARGET) +foreach (prefix_uniquifier static_target_arg IN ZIP_LISTS prefix_uniquifiers static_target_args) + set(prefix "NCURSES${prefix_uniquifier}") + message(STATUS "static_target_arg: ${static_target_arg}") + pkg_check_modules(${prefix} IMPORTED_TARGET QUIET ${static_target_arg} ncurses) + + message(STATUS "source: ${CMAKE_CURRENT_SOURCE_DIR} bin ${CMAKE_CURRENT_BINARY_DIR}") + + if (${prefix}_FOUND) + set(tgt PkgConfig::${prefix}) + message(STATUS "Verifying target \"${tgt}\"") + if (NOT TARGET ${tgt}) + message(FATAL_ERROR "FindPkgConfig found ncurses, but did not create an imported target for it") endif () - endforeach () - if (NOT prop_found) - message(FATAL_ERROR "target ${tgt} found, but it has no properties") + set(prop_found FALSE) + foreach (prop IN ITEMS INTERFACE_INCLUDE_DIRECTORIES INTERFACE_LINK_LIBRARIES INTERFACE_COMPILE_OPTIONS) + get_target_property(value ${tgt} ${prop}) + if (value) + message(STATUS "Found property ${prop} on target: ${value}") + set(prop_found TRUE) + endif () + endforeach () + if (NOT prop_found) + message(FATAL_ERROR "target ${tgt} found, but it has no properties") + endif () + else () + message(STATUS "skipping test; ncurses not found") endif () -else () - message(STATUS "skipping test; ncurses not found") -endif () - +endforeach () # Setup for the remaining package tests below set(PKG_CONFIG_USE_CMAKE_PREFIX_PATH) set(fakePkgDir ${CMAKE_CURRENT_BINARY_DIR}/pc-fakepackage) foreach(i 1 2) set(pname cmakeinternalfakepackage${i}) - file(WRITE ${fakePkgDir}/lib/lib${pname}.a "") - file(WRITE ${fakePkgDir}/lib/${pname}.lib "") + file(WRITE ${fakePkgDir}/lib/${static_lib_prefix}${pname}${static_lib_suffix} "") + file(WRITE ${fakePkgDir}/lib/${shared_lib_prefix}${pname}${shared_lib_suffix} "") file(WRITE ${fakePkgDir}/lib/pkgconfig/${pname}.pc "Name: CMakeInternalFakePackage${i} Description: Dummy package (${i}) for FindPkgConfig IMPORTED_TARGET test @@ -49,12 +68,15 @@ set(ENV{PKG_CONFIG_PATH} ${fakePkgDir}/lib/pkgconfig) # find targets in subdir and check their visibility add_subdirectory(target_subdir) -if (TARGET PkgConfig::FakePackage1_dir) - message(FATAL_ERROR "imported target PkgConfig::FakePackage1_dir is visible outside it's directory") + +set(tgt PkgConfig::FakePackage1_dir) +if (TARGET ${tgt}) + message(FATAL_ERROR "imported target \"${tgt}\" is visible outside its directory") endif() -if (NOT TARGET PkgConfig::FakePackage1_global) - message(FATAL_ERROR "imported target PkgConfig::FakePackage1_global is not visible outside it's directory") +set(tgt PkgConfig::FakePackage1_global) +if (NOT TARGET ${tgt}) + message(FATAL_ERROR "imported target \"${tgt}\" is not visible outside its directory") endif() # And now do the same for the NO_CMAKE_ENVIRONMENT_PATH - ENV{CMAKE_PREFIX_PATH} @@ -63,35 +85,52 @@ unset(CMAKE_PREFIX_PATH) unset(ENV{CMAKE_PREFIX_PATH}) set(ENV{CMAKE_PREFIX_PATH} ${fakePkgDir}) -pkg_check_modules(FakePackage2 REQUIRED QUIET IMPORTED_TARGET cmakeinternalfakepackage2) -if (NOT TARGET PkgConfig::FakePackage2) - message(FATAL_ERROR "No import target for fake package 2 with prefix path") -endif() -# check that 2 library entries exist -list(LENGTH FakePackage2_LINK_LIBRARIES fp2_nlibs) -if (NOT fp2_nlibs EQUAL 2) - message(FATAL_ERROR "FakePackage2_LINK_LIBRARIES has ${fp2_nlibs} entries but should have exactly 2") -endif() - -# check that the full library path is also returned -list(GET FakePackage2_LINK_LIBRARIES 0 fp2_lib0) -if (NOT fp2_lib0 STREQUAL "${fakePkgDir}/lib/libcmakeinternalfakepackage2.a") - message(FATAL_ERROR "FakePackage2_LINK_LIBRARIES has bad content on first run: ${FakePackage2_LINK_LIBRARIES}") -endif() - -# check that the library that couldn't be found still shows up -list(GET FakePackage2_LINK_LIBRARIES 1 fp2_lib1) -if (NOT fp2_lib1 STREQUAL "cmakeinternalfakepackage2-doesnotexist") - message(FATAL_ERROR "FakePackage2_LINK_LIBRARIES has bad content on first run: ${FakePackage2_LINK_LIBRARIES}") -endif() +# to test multiple variations, we must pick unique prefix names (same-named targets are cached for re-use) +set(prefix_uniquifiers 0 1) +# whether to apply STATIC_TARGET argument +set(static_target_args "" STATIC_TARGET) +# whether target properties are populated from the unqualified (i.e. shared library) series of vars, or the STATIC_ series of vars +set(target_var_qualifiers "" STATIC_) +set(lib_types shared static) +foreach (prefix_uniquifier static_target_arg target_var_qualifier lib_type IN ZIP_LISTS prefix_uniquifiers static_target_args target_var_qualifiers lib_types) + set(prefix "FakePackage2${prefix_uniquifier}") + set(tgt "PkgConfig::${prefix}") + pkg_check_modules(${prefix} REQUIRED QUIET IMPORTED_TARGET ${static_target_arg} cmakeinternalfakepackage2) -# the information in *_LINK_LIBRARIES is not cached, so ensure is also is present on second run -unset(FakePackage2_LINK_LIBRARIES) -pkg_check_modules(FakePackage2 REQUIRED QUIET IMPORTED_TARGET cmakeinternalfakepackage2) -if (NOT FakePackage2_LINK_LIBRARIES STREQUAL "${fakePkgDir}/lib/libcmakeinternalfakepackage2.a;cmakeinternalfakepackage2-doesnotexist") - message(FATAL_ERROR "FakePackage2_LINK_LIBRARIES has bad content on second run: ${FakePackage2_LINK_LIBRARIES}") -endif() + message(STATUS "Verifying library path resolution for lib type \"${lib_type}\"") + if (NOT TARGET ${tgt}) + message(FATAL_ERROR "No import target for fake package 2 with prefix path") + endif() + + set(link_libraries_var ${prefix}_${target_var_qualifier}LINK_LIBRARIES) + # check that 2 library entries exist + list(LENGTH ${link_libraries_var} fp2_nlibs) + if (NOT fp2_nlibs EQUAL 2) + message(FATAL_ERROR "${link_libraries_var} has ${fp2_nlibs} entries but should have exactly 2") + endif() + + set(lib_leafname ${${lib_type}_lib_prefix}cmakeinternalfakepackage2${${lib_type}_lib_suffix}) + message(STATUS "Expecting library leafname \"${lib_leafname}\"") + # check that the full library path is also returned + list(GET ${link_libraries_var} 0 fp2_lib0) + if (NOT fp2_lib0 STREQUAL "${fakePkgDir}/lib/${lib_leafname}") + message(FATAL_ERROR "${link_libraries_var} has bad content on first run: ${${link_libraries_var}}") + endif() + + # check that the library that couldn't be found still shows up + list(GET ${link_libraries_var} 1 fp2_lib1) + if (NOT fp2_lib1 STREQUAL "cmakeinternalfakepackage2-doesnotexist") + message(FATAL_ERROR "${link_libraries_var} has bad content on first run: ${${link_libraries_var}}") + endif() + + # the information in *_LINK_LIBRARIES is not cached, so ensure is also is present on second run + unset(${link_libraries_var}) + pkg_check_modules(${prefix} REQUIRED QUIET IMPORTED_TARGET ${static_target_arg} cmakeinternalfakepackage2) + if (NOT ${link_libraries_var} STREQUAL "${fakePkgDir}/lib/${lib_leafname};cmakeinternalfakepackage2-doesnotexist") + message(FATAL_ERROR "${link_libraries_var} has bad content on second run: ${${link_libraries_var}}") + endif() +endforeach() set(pname fakelinkoptionspackage) file(WRITE ${fakePkgDir}/lib/pkgconfig/${pname}.pc @@ -104,10 +143,13 @@ Cflags: -I/special -isystem /other -isystem/more -DA-isystem/foo set(expected_link_options -e dummy_main) pkg_check_modules(FakeLinkOptionsPackage REQUIRED QUIET IMPORTED_TARGET fakelinkoptionspackage) -if (NOT TARGET PkgConfig::FakeLinkOptionsPackage) + +set(tgt PkgConfig::FakeLinkOptionsPackage) +message(STATUS "Verifying target \"${tgt}\"") +if (NOT TARGET ${tgt}) message(FATAL_ERROR "No import target for fake link options package") endif() -get_target_property(link_options PkgConfig::FakeLinkOptionsPackage INTERFACE_LINK_OPTIONS) +get_target_property(link_options ${tgt} INTERFACE_LINK_OPTIONS) if (NOT link_options STREQUAL expected_link_options) message(FATAL_ERROR "Additional link options not present in INTERFACE_LINK_OPTIONS property\n" @@ -115,7 +157,7 @@ if (NOT link_options STREQUAL expected_link_options) ) endif() -get_target_property(inc_dirs PkgConfig::FakeLinkOptionsPackage INTERFACE_INCLUDE_DIRECTORIES) +get_target_property(inc_dirs ${tgt} INTERFACE_INCLUDE_DIRECTORIES) set(expected_inc_dirs "/special" "/other" "/more") if (NOT inc_dirs STREQUAL expected_inc_dirs) @@ -125,7 +167,7 @@ if (NOT inc_dirs STREQUAL expected_inc_dirs) ) endif () -get_target_property(c_opts PkgConfig::FakeLinkOptionsPackage INTERFACE_COMPILE_OPTIONS) +get_target_property(c_opts ${tgt} INTERFACE_COMPILE_OPTIONS) set(expected_c_opts "-DA-isystem/foo") # this is an invalid option, but a good testcase if (NOT c_opts STREQUAL expected_c_opts) message(FATAL_ERROR diff --git a/Tests/RunCMake/FindPkgConfig/FindPkgConfig_LIBRARY_PATH-stdout.txt b/Tests/RunCMake/FindPkgConfig/FindPkgConfig_LIBRARY_PATH-stdout.txt index 6615d80..8966ac3 100644 --- a/Tests/RunCMake/FindPkgConfig/FindPkgConfig_LIBRARY_PATH-stdout.txt +++ b/Tests/RunCMake/FindPkgConfig/FindPkgConfig_LIBRARY_PATH-stdout.txt @@ -1,3 +1,6 @@ -- ZOT_LIBRARIES='zot' --- ZOT_LINK_LIBRARIES='[^']*/Tests/RunCMake/FindPkgConfig/FindPkgConfig_LIBRARY_PATH-build/zot/lib/prefix-zot-suffix' --- ZOT_LDFLAGS='-L[^']*/Tests/RunCMake/FindPkgConfig/FindPkgConfig_LIBRARY_PATH-build/zot/lib;-lzot' +-- ZOT_LINK_LIBRARIES='[^']*/Tests/RunCMake/FindPkgConfig/FindPkgConfig_LIBRARY_PATH-build/root/lib/dyprefix-zot-dysuffix' +-- ZOT_LDFLAGS='-L[^']*/Tests/RunCMake/FindPkgConfig/FindPkgConfig_LIBRARY_PATH-build/root/lib;-lzot' +-- ZOT_STATIC_LIBRARIES='zot' +-- ZOT_STATIC_LINK_LIBRARIES='[^']*/Tests/RunCMake/FindPkgConfig/FindPkgConfig_LIBRARY_PATH-build/root/lib/stprefix-zot-stsuffix' +-- ZOT_STATIC_LDFLAGS='-L[^']*/Tests/RunCMake/FindPkgConfig/FindPkgConfig_LIBRARY_PATH-build/root/lib;-lzot' diff --git a/Tests/RunCMake/FindPkgConfig/FindPkgConfig_LIBRARY_PATH.cmake b/Tests/RunCMake/FindPkgConfig/FindPkgConfig_LIBRARY_PATH.cmake index 9f654b5..536addc 100644 --- a/Tests/RunCMake/FindPkgConfig/FindPkgConfig_LIBRARY_PATH.cmake +++ b/Tests/RunCMake/FindPkgConfig/FindPkgConfig_LIBRARY_PATH.cmake @@ -1,29 +1,47 @@ find_package(PkgConfig REQUIRED) -file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/zot/lib/pkgconfig/zot.pc" " -prefix=${CMAKE_CURRENT_BINARY_DIR}/zot +set(ROOT "${CMAKE_CURRENT_BINARY_DIR}/root") +string(REPLACE " " "\\ " ESCAPED_ROOT "${ROOT}") +set(LIB_DIR "${ROOT}/lib") +set(PKGCONFIG_DIR "${LIB_DIR}/pkgconfig") + +file(WRITE "${PKGCONFIG_DIR}/zot.pc" " +prefix=${ESCAPED_ROOT} libdir=\${prefix}/lib Name: Zot -Description: Dummy packaget to test LIBRARY_DIR support +Description: Dummy package to test LIBRARY_DIR support Version: 1.0 Libs: -L\${libdir} -lzot ") +set(shared_lib_prefix "dyprefix-") +set(shared_lib_suffix "-dysuffix") +set(static_lib_prefix "stprefix-") +set(static_lib_suffix "-stsuffix") + +set(CMAKE_SHARED_LIBRARY_PREFIX ${shared_lib_prefix}) +set(CMAKE_SHARED_LIBRARY_SUFFIX ${shared_lib_suffix}) +set(CMAKE_STATIC_LIBRARY_PREFIX ${static_lib_prefix}) +set(CMAKE_STATIC_LIBRARY_SUFFIX ${static_lib_suffix}) + # Create a "library" file to find in libdir. -set(CMAKE_FIND_LIBRARY_PREFIXES "prefix-") -set(CMAKE_FIND_LIBRARY_SUFFIXES "-suffix") -file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/zot/lib/prefix-zot-suffix") +foreach(variant shared static) + file(WRITE "${LIB_DIR}/${${variant}_lib_prefix}zot${${variant}_lib_suffix}") +endforeach() # 'pkg-config --libs' drops -L flags in PKG_CONFIG_SYSTEM_LIBRARY_PATH by default. -set(ENV{PKG_CONFIG_SYSTEM_LIBRARY_PATH} "${CMAKE_CURRENT_BINARY_DIR}/zot/lib") +set(ENV{PKG_CONFIG_SYSTEM_LIBRARY_PATH} "${LIB_DIR}") # 'pkgconf --libs' also drops -L flags in LIBRARY_PATH by default. -set(ENV{LIBRARY_PATH} "${CMAKE_CURRENT_BINARY_DIR}/zot/lib") +set(ENV{LIBRARY_PATH} "${LIB_DIR}") -set(ENV{PKG_CONFIG_PATH} "${CMAKE_CURRENT_BINARY_DIR}/zot/lib/pkgconfig") +set(ENV{PKG_CONFIG_PATH} "${PKGCONFIG_DIR}") pkg_check_modules(ZOT REQUIRED zot) message(STATUS "ZOT_LIBRARIES='${ZOT_LIBRARIES}'") message(STATUS "ZOT_LINK_LIBRARIES='${ZOT_LINK_LIBRARIES}'") message(STATUS "ZOT_LDFLAGS='${ZOT_LDFLAGS}'") +message(STATUS "ZOT_STATIC_LIBRARIES='${ZOT_STATIC_LIBRARIES}'") +message(STATUS "ZOT_STATIC_LINK_LIBRARIES='${ZOT_STATIC_LINK_LIBRARIES}'") +message(STATUS "ZOT_STATIC_LDFLAGS='${ZOT_STATIC_LDFLAGS}'") diff --git a/Tests/RunCMake/FindPkgConfig/FindPkgConfig_LINK_LIBRARIES-stdout.txt b/Tests/RunCMake/FindPkgConfig/FindPkgConfig_LINK_LIBRARIES-stdout.txt new file mode 100644 index 0000000..edf0262 --- /dev/null +++ b/Tests/RunCMake/FindPkgConfig/FindPkgConfig_LINK_LIBRARIES-stdout.txt @@ -0,0 +1,6 @@ +-- IMM_LIBRARIES='imm' +-- IMM_LINK_LIBRARIES='[^']*/Tests/RunCMake/FindPkgConfig/FindPkgConfig_LINK_LIBRARIES-build/root/lib/dyprefix-imm-dysuffix' +-- IMM_LDFLAGS='-L[^']*/Tests/RunCMake/FindPkgConfig/FindPkgConfig_LINK_LIBRARIES-build/root/lib;-limm' +-- IMM_STATIC_LIBRARIES='imm;trns' +-- IMM_STATIC_LINK_LIBRARIES='[^']*/Tests/RunCMake/FindPkgConfig/FindPkgConfig_LINK_LIBRARIES-build/root/lib/stprefix-imm-stsuffix;[^']*/Tests/RunCMake/FindPkgConfig/FindPkgConfig_LINK_LIBRARIES-build/root/lib/stprefix-trns-stsuffix' +-- IMM_STATIC_LDFLAGS='-L[^']*/Tests/RunCMake/FindPkgConfig/FindPkgConfig_LINK_LIBRARIES-build/root/lib;-limm;-ltrns' diff --git a/Tests/RunCMake/FindPkgConfig/FindPkgConfig_LINK_LIBRARIES.cmake b/Tests/RunCMake/FindPkgConfig/FindPkgConfig_LINK_LIBRARIES.cmake new file mode 100644 index 0000000..bf4ee1e --- /dev/null +++ b/Tests/RunCMake/FindPkgConfig/FindPkgConfig_LINK_LIBRARIES.cmake @@ -0,0 +1,53 @@ +find_package(PkgConfig REQUIRED) + +set(ROOT "${CMAKE_CURRENT_BINARY_DIR}/root") +string(REPLACE " " "\\ " ESCAPED_ROOT "${ROOT}") +set(LIB_DIR "${ROOT}/lib") +set(PKGCONFIG_DIR "${LIB_DIR}/pkgconfig") + +file(WRITE "${PKGCONFIG_DIR}/imm.pc" " +prefix=${ESCAPED_ROOT} +libdir=\${prefix}/lib + +Name: Immediate +Description: Dummy package to test *LINK_LIBRARIES support +Version: 1.0 +Libs: -L\${libdir} -limm +Libs.private: -ltrns +") +file(WRITE "${PKGCONFIG_DIR}/trns.pc" " +prefix=${ESCAPED_ROOT} +libdir=\${prefix}/lib + +Name: Transitive +Description: Dummy package to test *LINK_LIBRARIES support +Version: 1.0 +Libs: -L\${libdir} -ltrns +") + +set(shared_lib_prefix "dyprefix-") +set(shared_lib_suffix "-dysuffix") +set(static_lib_prefix "stprefix-") +set(static_lib_suffix "-stsuffix") + +set(CMAKE_SHARED_LIBRARY_PREFIX ${shared_lib_prefix}) +set(CMAKE_SHARED_LIBRARY_SUFFIX ${shared_lib_suffix}) +set(CMAKE_STATIC_LIBRARY_PREFIX ${static_lib_prefix}) +set(CMAKE_STATIC_LIBRARY_SUFFIX ${static_lib_suffix}) + +# Create "library" files to find in libdir. +foreach(lib imm trns) + foreach(variant shared static) + file(WRITE "${LIB_DIR}/${${variant}_lib_prefix}${lib}${${variant}_lib_suffix}") + endforeach() +endforeach() + +set(ENV{PKG_CONFIG_PATH} "${PKGCONFIG_DIR}") +pkg_check_modules(IMM REQUIRED imm) + +message(STATUS "IMM_LIBRARIES='${IMM_LIBRARIES}'") +message(STATUS "IMM_LINK_LIBRARIES='${IMM_LINK_LIBRARIES}'") +message(STATUS "IMM_LDFLAGS='${IMM_LDFLAGS}'") +message(STATUS "IMM_STATIC_LIBRARIES='${IMM_STATIC_LIBRARIES}'") +message(STATUS "IMM_STATIC_LINK_LIBRARIES='${IMM_STATIC_LINK_LIBRARIES}'") +message(STATUS "IMM_STATIC_LDFLAGS='${IMM_STATIC_LDFLAGS}'") diff --git a/Tests/RunCMake/FindPkgConfig/FindPkgConfig_extract_frameworks_target.cmake b/Tests/RunCMake/FindPkgConfig/FindPkgConfig_extract_frameworks_target.cmake index 5501d9f..6c838a9 100644 --- a/Tests/RunCMake/FindPkgConfig/FindPkgConfig_extract_frameworks_target.cmake +++ b/Tests/RunCMake/FindPkgConfig/FindPkgConfig_extract_frameworks_target.cmake @@ -1,3 +1,5 @@ +cmake_minimum_required(VERSION 3.17) + # Prepare environment to reuse bletch.pc file(TO_NATIVE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/pc-bletch/lib/pkgconfig" PC_PATH) if(UNIX) @@ -6,24 +8,41 @@ endif() set(ENV{PKG_CONFIG_PATH} "${PC_PATH}") find_package(PkgConfig REQUIRED) -pkg_check_modules(Bletch IMPORTED_TARGET REQUIRED bletch-framework) - -if (Bletch_LDFLAGS_OTHER) - message(SEND_ERROR "Bletch_LDFLAGS_OTHER should be empty, but is '${Bletch_LDFLAGS_OTHER}'") -endif () -if (NOT Bletch_LINK_LIBRARIES STREQUAL "-framework foo;-framework bar;bletch;-framework baz") - message(SEND_ERROR "Bletch_LINK_LIBRARIES has wrong value '${Bletch_LINK_LIBRARIES}'") -endif () +# to test multiple variations, we must pick unique prefix names (same-named targets are cached for re-use) +set(prefix_uniquifiers 0 1) +# whether to apply STATIC_TARGET argument +set(static_target_args "" STATIC_TARGET) +# whether target properties are populated from the unqualified (i.e. shared library) series of vars, or the STATIC_ series of vars +set(target_var_qualifiers "" STATIC_) +foreach (prefix_uniquifier static_target_arg target_var_qualifier IN ZIP_LISTS prefix_uniquifiers static_target_args target_var_qualifiers) + set(prefix "Bletch${prefix_uniquifier}") + set(tgt "PkgConfig::${prefix}") + pkg_check_modules(${prefix} IMPORTED_TARGET REQUIRED ${static_target_arg} bletch-framework) + foreach (prop IN ITEMS INTERFACE_INCLUDE_DIRECTORIES INTERFACE_LINK_OPTIONS INTERFACE_COMPILE_OPTIONS) + get_target_property(prop_value ${tgt} ${prop}) + if (prop_value) + message(SEND_ERROR "target property ${prop} should not be set, but is '${prop_value}'") + endif () + endforeach () -foreach (prop IN ITEMS INTERFACE_INCLUDE_DIRECTORIES INTERFACE_LINK_OPTIONS INTERFACE_COMPILE_OPTIONS) - get_target_property(prop_value PkgConfig::Bletch ${prop}) - if (prop_value) - message(SEND_ERROR "target property ${prop} should not be set, but is '${prop_value}'") + # there is 1 target yet 2 series of variables. + # if STATIC_TARGET is set, then the target will follow the STATIC_ qualified series of variables + # (otherwise will follow the unqualified series of variables). + get_target_property(prop_value ${tgt} INTERFACE_LINK_LIBRARIES) + if (NOT prop_value STREQUAL ${prefix}_${target_var_qualifier}LINK_LIBRARIES) + message(SEND_ERROR "target property INTERFACE_LINK_LIBRARIES has wrong value '${prop_value}'") endif () -endforeach () -get_target_property(prop_value PkgConfig::Bletch INTERFACE_LINK_LIBRARIES) -if (NOT prop_value STREQUAL Bletch_LINK_LIBRARIES) - message(SEND_ERROR "target property INTERFACE_LINK_LIBRARIES has wrong value '${prop_value}'") -endif () + foreach (var_qualifier IN ITEMS "" STATIC_) + set (ldflags_var ${prefix}_${var_qualifier}LDFLAGS_OTHER) + if (${ldflags_var}) + message(SEND_ERROR "${ldflags_var} should be empty, but is '${${ldflags_var}}'") + endif () + + set (linklibs_var ${prefix}_${var_qualifier}LINK_LIBRARIES) + if (NOT ${linklibs_var} STREQUAL "-framework foo;-framework bar;bletch;-framework baz") + message(SEND_ERROR "${linklibs_var} has wrong value '${${linklibs_var}}'") + endif () + endforeach() +endforeach() diff --git a/Tests/RunCMake/FindPkgConfig/RunCMakeTest.cmake b/Tests/RunCMake/FindPkgConfig/RunCMakeTest.cmake index f36d1eb..f89b3b3 100644 --- a/Tests/RunCMake/FindPkgConfig/RunCMakeTest.cmake +++ b/Tests/RunCMake/FindPkgConfig/RunCMakeTest.cmake @@ -29,11 +29,9 @@ if (PKG_CONFIG_FOUND) run_cmake(FindPkgConfig_GET_VARIABLE_PKGCONFIG_PATH) run_cmake(FindPkgConfig_cache_variables) run_cmake(FindPkgConfig_IMPORTED_TARGET) + run_cmake(FindPkgConfig_LINK_LIBRARIES) run_cmake(FindPkgConfig_VERSION_OPERATORS) run_cmake(FindPkgConfig_GET_MATCHING_MODULE_NAME) run_cmake(FindPkgConfig_empty_target) - - if(NOT RunCMake_BINARY_DIR MATCHES " ") - run_cmake(FindPkgConfig_LIBRARY_PATH) - endif() + run_cmake(FindPkgConfig_LIBRARY_PATH) endif () |