ament / ament/ament_cmake

ament_export_dependencies can't export all PkgConfig projects found in CMake

Open
#504 2 comments 0 reactions 0 assignees View on GitHub
enhancement more-information-needed
Dominant language
CMake
Stars
125
Forks
147
PR merge metrics
No merged PRs in 30d

Description

I'm refactoring a large repository to be installable with ament_cmake. It's a CMake project, and relies on library `libav`, which does not support CMake. `libav` only comes with Pkgconfig support. Gstreamer is pulled in through pkgconfig also.

I'm using CMake 3.28, so I have full access to the latest language features.

## Current Behavior

Thus, here's how the library `foo` brings it in with CMake's built in [PkgConfig](https://cmake.org/cmake/help/latest/module/FindPkgConfig.html) support.

Some details omitted for brevity.

```cmake
pkg_check_modules(LIBAV REQUIRED IMPORTED_TARGET libavcodec>=50)
pkg_check_modules(GST REQUIRED IMPORTED_TARGET gstreamer-1.0>=1.2)

add_executable(my_node)
target_link_libraries(my_node PRIVATE PkgConfig::LIBAV PkgConfig::GST)

ament_export_dependencies(
LIBAV
GST
)
ament_package()
```

This builds fine. But, a consuming package `bar` can't use the exported dependencies.
```
--- stderr: bar
CMake Error at /ws/install/foo/share/foo/cmake/ament_cmake_export_dependencies-extras.cmake:21 (find_package):
By not providing "FindLIBAV.cmake" in CMAKE_MODULE_PATH this project has
asked CMake to find a package configuration file provided by "LIBAV", but
CMake did not find one.

Could not find a package configuration file provided by "LIBAV" with any of
the following names:

LIBAVConfig.cmake
libav-config.cmake

Add the installation prefix of "LIBAV" to CMAKE_PREFIX_PATH or set
"LIBAV_DIR" to a directory containing one of the above files. If "LIBAV"
provides a separate development package or SDK, be sure it has been
installed.
Call Stack (most recent call first):
/ws/install/foo/share/foo/cmake/fooConfig.cmake:41 (include)
CMakeLists.txt:84 (find_package)
```

Library `foo` has this as the INTERFACE_INCLUDE_DIRECTORIES: `INTERFACE_LINK_LIBRARIES "PkgConfig::GST;PkgConfig::LIBAV" in the export.

And, in ament_cmake_export_dependencies-extras.cmake
```
set(_exported_dependencies "GST;LIBAV")
```

## Expected Behavior

ament_export_dependencies can support and recognize targets created with `PkgConfig` and support downstream packages with PkgConfig.

## Workarounds

* Write my own find script for the library and install that with config-extras.
* Vendor the package and add CMake support
* Wait for CMake to add a maintained find script: https://gitlab.kitware.com/cmake/cmake/-/issues/24064
* Wait for ffmpeg devs to cave in to CMake: https://trac.ffmpeg.org/ticket/9881

## Proposal

Amend `ament_cmake_export_dependencies-extras.cmake` to also try to find PkgConfig projects as a backup using `pkg_check_modules`. Note that the flag `IMPORTED_TARGET` means that users of this will have to use that also.
```cmake
set(_exported_dependencies "LIBAV;GST")

find_package(ament_cmake_libraries QUIET REQUIRED)

if(NOT _exported_dependencies STREQUAL "")
find_package(ament_cmake_core QUIET REQUIRED)
set(Foo_DEPENDENCIES ${_exported_dependencies})
set(Foo_RECURSIVE_DEPENDENCIES ${_exported_dependencies})
set(_libraries)
foreach(_dep ${_exported_dependencies})
if(NOT ${_dep}_FOUND)
find_package("${_dep}" QUIET)
endif()
if(NOT ${_dep}_FOUND)
pkg_check_modules(${_dep} IMPORTED_TARGET)
endif()
if(NOT ${_dep}_FOUND)
find_package("${_dep}" REQUIRED)
endif()
```
This will work because of the following in FooTargetExport.cmake
```
set_target_properties(Foo::FooPROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${_IMPORT_PREFIX}/include"
INTERFACE_LINK_LIBRARIES "PkgConfig::GST;PkgConfig::LIBAV"
)
```

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.