aminya / project_options

A general-purpose CMake library that provides functions that improve the CMake experience following the best practices.

Home Page:https://aminya.github.io/project_options/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

target_find_dependencies and pkg-config

ddassie-texa opened this issue · comments

I'm trying to use target_find_dependencies to add the dependencies for a STATIC library that depends on some libraries that can be found via pkg-config, I'm able to pass the PkgConfig package to target_find_dependencies but there doesn't seem to be an easy way to add the pkg_check_modules calls to the CMake package config, is there any way I can solve this situation?

My old Config.cmake.in file used to look like this:

@PACKAGE_INIT@

include(CMakeFindDependencyMacro)

find_dependency(Threads)
find_dependency(PkgConfig)

if(NOT TARGET PkgConfig::gio)
    pkg_check_modules(gio REQUIRED IMPORTED_TARGET gio-2.0)
endif()

if(NOT TARGET PkgConfig::dbus)
    pkg_check_modules(dbus REQUIRED IMPORTED_TARGET dbus-1)
endif()

include("${CMAKE_CURRENT_LIST_DIR}/@TARGET_NAME@Targets.cmake")

check_required_components(@TARGET_NAME@)

Upvote & Fund

@aminya is using Polar.sh so you can upvote and help fund this issue. The funding is received once the issue is completed & confirmed by you.

Thank you in advance for helping prioritize & fund our backlog!


Fund with Polar

I’m not quite sure what your question is. Are you trying to target_find_dependencies(<target> PUBLIC gio) in which gio is a library that should be found by pkg_check_modules?

If that's the case, there is an official way for cmake to custom find_package, which might be helpful. You can see an actual example here, which is the CMake dependency provider for the Conan C and C++ package manager.

Sure, so is there a way to inject a custom dependency provider into the project_options target_find_dependencies call?
Or does the custom provider have to be implemented on the users of the package instead of the provider? And in that case, won't it break conan?

The situation is that PkgConfig dosen't provide find_package provider, so you have to. I think this won't break conan as both cmake-conan and vcpkg use this approach and project_options works well while enabling both run_conan() and run_vcpkg().

What target_find_dependencies actually do is to

  • call find_package for the specified packages;
  • register them as a part of installation.

When running cmake --install, the corresponding cmake config file will insert a find_package(<package> [args]) for all the packages specifed in target_find_dependencies. That's how the function works.

To install pkg_check_modules dependency, you can

  • either pkg_check_modules by manual, and insert the code into cmake config file yourself at the same time.
  • or write a find_package provider which allows find_package to handle pkg_check_modules, and install the find_package provider file.

Is this fixed after #257?

Is this fixed after #257?

@aminya Possibly not. Instead of allowing custom find_package args like #257, this issue is about extending target_find_dependencies to be able to find dependencies that are imported by functions other than find_package, and install such a dependency when the target is required to install.

Without modifying the target_find_dependencies, this could be done by:

  • either pkg_check_modules by manual, and inserting the code into cmake config file yourself at the same time.
  • or writing a find_package provider which allows find_package to handle pkg_check_modules, and installing the find_package provider file.

Another option could be extending target_find_dependencies to have a custom mode:

target_find_dependencies(target
  PUBLIC
    # Syntax option 1
    CUSTOM "pkg_check_modules(gio REQUIRED IMPORTED_TARGET gio-2.0)"
    # Or syntax option 2?
    CUSTOM pkg_check_modules gio REQUIRED IMPORTED_TARGET gio-2.0
)

Please let me know if this is acceptable. If it is, which is the best syntax?

I think the most versatile solution would be to add a way to provide a CMake script as an extension point (maybe allow multiple files?), eg: target_find_dependencies(<target> CUSTOM MyInjectedDep.cmake), then it can be installed as part of the package and included after the other find_dependency() calls.

add a way to provide a CMake script as an extension point (maybe allow multiple files?), eg: target_find_dependencies(<target> CUSTOM MyInjectedDep.cmake)

After setting cmake_language(SET_DEPENDENCY_PROVIDER...), all find_package will try to use the provider, so this seems like a dependency for the whole project instead of the <target>, which violets the purpose of using target_find_dependencies (that is, bind the dependency to the target).

If setting the MyInjectedDep.cmake is the preferable way than CUSTOM pkg_check_modules gio REQUIRED IMPORTED_TARGET gio-2.0, I would prefer add a function like set_dependency_provider(<provider.cmake>) to both call cmake_language(SET_DEPENDENCY_PROVIDER...) and install it. But it is almost just a wrapper for a cmake_language(SET_DEPENDENCY_PROVIDER...) command and a install(FILES...) command, which is the solution describe before:

writing a find_package provider which allows find_package to handle pkg_check_modules, and installing the find_package provider file.

Another difference between setting dependency provider and just allowing CUSTOM any_function args is that you have to adapt the call to find_package style. For example, for pkg_check_modules(gio REQUIRED IMPORTED_TARGET gio-2.0), you have to adapt it to be find_package(gio) or something else, which is not implementable for some functions.

I'm also unsure about what will happen if a user has a custom Findgio.cmake module and a dependency provider is added, my idea with the MyInjectedDep.cmake was just so you could more easily write complex logic to find dependencies if needed, without dealing with a long string.

You could have MyInjectedDep.cmake without modifying target_find_dependencies. Just use include(MyInjectedDep.cmake) and install(FILES MyInjectedDep.cmake).

My question here is that target_find_dependencies is to set dependencies for a single target, so maybe a function like set_dependency_provider(<provider.cmake>) is more suitable than allowing target_find_dependencies to set (possibly global) a file dependency.

Is this fixed after #257?

@aminya Possibly not. Instead of allowing custom find_package args like #257, this issue is about extending target_find_dependencies to be able to find dependencies that are imported by functions other than find_package, and install such a dependency when the target is required to install.

Without modifying the target_find_dependencies, this could be done by:

* either pkg_check_modules by manual, and inserting the code into cmake config file yourself at the same time.

* or writing a find_package provider which allows find_package to handle pkg_check_modules, and installing the find_package provider file.

Another option could be extending target_find_dependencies to have a custom mode:

target_find_dependencies(target
  PUBLIC
    # Syntax option 1
    CUSTOM "pkg_check_modules(gio REQUIRED IMPORTED_TARGET gio-2.0)"
    # Or syntax option 2?
    CUSTOM pkg_check_modules gio REQUIRED IMPORTED_TARGET gio-2.0
)

Please let me know if this is acceptable. If it is, which is the best syntax?

I guess the syntax on option 2 would be the best in this case than.