Proper "scope" of Find Modules

I apologize at the outset for any lack of clarity in this question. I’m swimming in deep waters and not always staying above the surface. I have tried to figure this out, and have come to a fork in the road, and need to understand the best practice before I choose a path.


I’m trying to fix an application (GNSS-SDR) that is built upon a third-party package (GNU Radio). GNSS-SDR tries to maintain extensive backwards compatibility with older versions, compilers, and operating systems, which seems to complicate things a lot.

The leaf issue is that the newer GNU Radio releases replaced one third party package (log4cpp) with another (spdlog). They also made some significant improvements in their exported CMake files. When I build GNSS-SDR on my CentOS 7 environment, I get a compile error that traces through GNU Radio into spdlog.

I have determined that spdlog properly exposes interface compile and link properties in its spdlogConfigTargets.cmake, like this (from ArchLinux):

set_target_properties(spdlog::spdlog PROPERTIES
  INTERFACE_LINK_LIBRARIES "Threads::Threads;fmt::fmt"


GNSS-SDR implements a number of FindModules that wrap other packages. Because GNSS-SDR wraps the finding of all these third-party packages, it creates its own import targets for them. I think information is lost in doing this.

In particular, this code explicitly adds the SPDLOG_FMT_EXTERNAL define to the compile flags of any user of the package.

I tried simply removing the FindSPDLOG module from GNSS-SDR; then I realized that there is no reason to find it at all; GNU Radio should be (and is) exporting the dependency. When I do this, though, distributions that need the SPDLOG_FMT_EXTERNAL define no longer compile.

What I think should be happening is that the GNU Radio targets expose the spdlog dependency, including the compilation properties. Unfortunately, GNSS-SDR wraps the GNU Radio targets (gnuradio::gnuradio-XXX) with its own targets (Gnuradio::XXX). I think this is the root cause of my problem.

However, as I’ve tried to remove the FindGNURADIO module, I see that it is doing more than just “finding” the package. Here’s where my CMake-fu is too weak.

The Real Question

Should a FindModule simply “find” a package, bringing it into the environment such that it can be used by targets, or should it also “augment” the package, adding meta-data. For example, here, here, and here exposes a flag based on an implementation detail that changed in the past.

If I just remove the GNSS-SDR FindModule (and change find_package(GNURADIO) to find_package(Gnuradio), then things mostly work, but I’m left with the missing metadata. So is that the proper domain of a FindModule?

If I don’t remove the project-specific FindModule and rely on the provided one, where should I put the metadata? Right now, some metadata is in the FindModules and other is in the top-level CMakeLists.txt.

I’m not afraid to do major surgery, but it would be good to “see one” before I “do one”[1].


I’ve tried to search on my own. I’ve looked at

I can’t say I’ve understood it all, but I’m coming closer.

That’s the end goal. If there is metadata required, it is best provided at the source. So instead of figuring out “is this static?” after the find_package returns, the implementation should be enhanced to just provide this information up-front.

If you want a fairly complex example that does “just about everything”, VTK’s vtk-config.cmake has all kinds of patterns involved. This includes adding additional properties to its provided targets for various uses (the -module-properties.cmake files it includes).

I can embrace that philosophy, but in this case I’m in the middle. Even if I were to enhance GNU Radio’s exports, that wouldn’t address the need of GNSS-SDR to support older versions (without the enhancement).

So should the meta-data be localized to the FindGNURADIO.cmake of GNSS-SDR, or put in the top-level CMakeLists.txt or moved to some other module that perhaps wraps find_package(GNURADIO)?

I would try to get upstream to provide this information first and then provide that same information from installs that don’t have it as needed. That way there’s no “oh, upstream changed what we thought we needed and now there are more variables to consider” situation.