Finding Packages

Overview

Teaching: 10 min
Exercises: 0 min
Questions
  • How do I search for packages?

Objectives
  • Understand FindPackage.cmake

  • Understand PackageConfig.cmake

You can search for packages in CMake in two ways; both of them, however, use the same interface. Here’s what it would look like:

find_package(MyPackage 1.2)

This will look for a file in the CMAKE_MODULE_PATH that is named FindMyPackage.cmake. If it does not find one, it will look for a file named MyPackageConfig.cmake in several places, including MyPackage_DIR if that variable exists. You can only perform one of these searches with MODULE or CONFIG, respectively.

You can add COMPONENTS in some cases, if the package supports it, and you can also add QUIET to hide extra text, or REQUIRED to cause a missing package to fail the configure step.

Aside: Environment Hints

Hinting the installation of software package that is installed outside of a system paths works can also be done with environment variables. In CMake 3.12+, individual packages locations can be hinted by setting their installation root path in <PackageName>_ROOT.

export HDF5_ROOT=$HOME/software/hdf5-1.12.0

Similarly, the variable CMAKE_PREFIX_PATH can be used to hint a list of installation root paths at once:

export CMAKE_PREFIX_PATH=$HOME/software/hdf5-1.12.0:$HOME/software/boost-1.74.0:$CMAKE_PREFIX_PATH

FindPackage

The older method for finding packages is the FindPackage.cmake method (MODULE). This is a CMake or user supplied search script that knows how to look for a package. While there are some conventions here, and some tools to help, there are not many hard-and-fast requirements. A package should at least set the variable Package_FOUND. There are 100 or so find packages included in CMake, refer to the documentation for each.

PackageConfig

The “better” way to do things is to have an installed package provide its own details to CMake; these are “CONFIG” files and come with many packages. These files can be simpler and smarter, since they don’t have to search for the package and query the options, but rather can be generated with the correct paths and options for a particular install. ROOT is an example of a package that is now providing a CONFIG file; another one that is just beginning to is Boost; while CMake includes a FindBoost, it has to be updated with each new Boost release, whereas BoostConfig.cmake can be included with each Boost release (first version in 1.70). One issue with some packages (TBB, for example) is that they may provide optional CONFIG files, and your packager may not have activated them.

To be clear: If you are a package author, never supply a Find<package>.cmake, but instead always supply a <package>Config.cmake with all your builds. If you are depending on another package, try to look for a Config first, and if that is not available, or often not available, then write a find package for it for your use.

Key Points

  • A FindPackage.cmake file can factor out package discovery for a package you don’t own.

  • A PackageConfig.cmake helps others find your package.