1

I am developing my own header-only library that I want to use as a framework in other software. I am using CMake for setting up demo targets, tests, and so on.

However, I am unsure how to deal with dependencies of my library. Currently, I am using the following approach:

FIND_PACKAGE( foo )

I have a configuration config/foo.hh.in file for foo that checks whether the package exists:

#ifndef FOO_HH__
#define FOO_HH__
  #cmakedefine HAVE_FOO
#endif

In the main CMakeLists.txt, I do:

CONFIGURE_FILE( ${CMAKE_SOURCE_DIR}/include/config/foo.hh.in ${CMAKE_SOURCE_DIR}/include/config/foo.hh )

In the code, I can thus do:

#include "config/foo.hh"
#ifdef HAVE_FOO
  // Code that is specific to having the `foo` library available
#endif

The problem with this approach is that it only works once, namely when the library is installed for the first time and all the dependencies are being checked. Since I am not shipping the optional dependencies with my library, I am wondering whether this is a good approach. What if the user decides to install an optional dependency after installing my library? In this case, I will not be able to detect the presence of the library.

How do you usually solve this issue? What am I doing wrong with this approach?

2
  • Forgive my ignorance, but if your header only library only defines a number of macros, then isn't a compile-only utility. Commented Feb 14, 2018 at 13:39
  • Of course the whole library contains more than just macros. Some parts are dependent on the availability of external dependencies, though, so I was wondering how other people are solving this. Commented Feb 14, 2018 at 13:48

1 Answer 1

2

Normally, when you build and install some software, you decide which features will be available when you build the software, not when you use it, therefore I'd say that the approach makes sense.

Anyway if you want to allow the software to be installed, and the features detected at a later time, I think that you can do something like this (note that this will work only if the users of your library will use CMake):

  1. Remove the FIND_PACKAGE(foo) check in your main CMakeLists.txt and the #cmakedefine in your config file.

  2. Export a target for your library using add_library(INTERFACE), export(TARGET) if you don't do that already (see add_library, export, and install commands documentation for details).

  3. Add a MyProjectConfig.cmake file if you don't have one (see here).

  4. Inside your MyProjectConfig.cmake, after including the target files, you can do something like this:

    find_package(foo QUIET)
    if(foo_FOUND)
        target_compile_definitions(MyTarget INTERFACE HAVE_FOO)
    endif()
    
  5. The users of the library will have to link the target, and the definition will be added only if the library is found on the system when the user library is configured. Your library can be used in this way:

    find_package(MyProject)
    add_library(bar [...])
    target_link_libraries(bar MyProject::MyTarget)
    
1
  • Thank you, this sounds like a viable plan. Also, your argument concerning the availability of features is convincing. Maybe it does not make sense to go through so much trouble. Commented Feb 20, 2018 at 7:09

Not the answer you're looking for? Browse other questions tagged or ask your own question.