1

Note: Re-asking a poorly-written earlier question.

How should a package/library developer, using CMake, allow for their package to be effectively installed on a system, as well as easily integrated/used in another CMake-based project?

According to the oft-linked-to talk by Daniel Pfeiffer (slides here), this is an example of how it's done:

In CMakeLists.txt:

find_package(Bar 2.0 REQUIRED)
add_library(Foo ...)
target_link_libraries(Foo PRIVATE Bar::Bar)

install(TARGETS Foo EXPORT FooTargets
    LIBRARY DESTINATION lib
    ARCHIVE DESTINATION lib
    RUNTIME DESTINATION bin
    INCLUDES DESTINATION include
)

install(EXPORT FooTargets
    FILE FooTargets.cmake
    NAMESPACE Foo::
    DESTINATION lib/cmake/Foo
)

in a second file (which?):

include(CMakePackageConfigHelpers)
write_basic_package_version_file("FooConfigVersion.cmake"
    VERSION ${Foo_VERSION}
    COMPATIBILITY SameMajorVersion
)
install(FILES "FooConfig.cmake" "FooConfigVersion.cmake"
    DESTINATION lib/cmake/Foo
)

in a third file (which?):

include(CMakeFindDependencyMacro)
find_dependency(Bar 2.0)
include("${CMAKE_CURRENT_LIST_DIR}/FooTargets.cmake")

So, we have:

  • At least four different CMake files (CMakeLists.txt, FooTargets.cmake, FooConfig.cmake, FooConfigVersion.cmake)
  • ... more than one of which is generated, but more than one is written by hand
  • ... and which also include each other
  • ... and whose names do not make it clearer which does what
  • ... with some, but not all of them, getting installed.

I keep getting confused and mixed-up about this. Pfeifer says "I wish this were easier; but at least it's straightforward" - it's not really that straightforward.

Questions:

  • Can this be simplified somehow?
  • If not, why are each of these files important to have?
  • Can't some more of the files be auto-generated with less commands/scripts/files generated dynamically?
einpoklum
  • 118,144
  • 57
  • 340
  • 684
  • I tried to do it myself and I ended up with exactly the same configuration : export targets, include targets in a config.cmake file. And it also took me a lot of instructions. – Arne J Aug 12 '19 at 09:39
  • @ArneJ: 1. But did you need four (or more) files as well? 2. What about automating this whole thing, at least? – einpoklum Aug 12 '19 at 09:47
  • Well in source at least 2 files : one CMakeLists.txt and one config.cmake.in . Then I have CMake generate myptoject-config.cmake (with a function similar to write_basic_package_version_file(), but for config files). The installed files I have are the exported targets, config and version files, correct ! So your setup seems quite ok to me, and I did mine more than a year ago. Maybe just find out if you can also reuse one config.cmake.in – Arne J Aug 12 '19 at 10:51
  • @ArneJ: Perhaps you should make that comment into an answer. – einpoklum Aug 12 '19 at 11:10

1 Answers1

0

In conclusion : when I tried to do this about a year ago, I had a very similar setup.

In source at least 2 files : one CMakeLists.txt and one config.cmake.in . Then I have CMake generate myproject-config.cmake with configure_package_config_file().

In installed files I also had the exported targets, config and version files.

As a suggestion, find out if you can also reuse one config.cmake.in using configure_package_config_file().

Arne J
  • 415
  • 2
  • 9
  • 1. If this is a FOSS project - can you link to it? 2. Did you also need to repeat yourself, e.g. by listing dependencies like in my example? 3. Why do we need both a config file and a version file? Can't they both be in the same file? – einpoklum Aug 12 '19 at 14:15