# Using Dependencies Guide

## Introduction

For developers wishing to use CMake to consume a third party binary package, there are multiple possibilities regarding how to optimally do so, depending on how CMake-aware the third-party library is.

CMake files provided with a software package contain instructions for finding each build dependency. Some build dependencies are optional in that the build may succeed with a different feature set if the dependency is missing, and some dependencies are required. CMake searches well-known locations for each dependency, and the provided software may supply additional hints or locations to CMake to find each dependency.

If a required dependency is not found by `cmake(1)`, the cache is populated with an entry which contains a `NOTFOUND` value. This value can be replaced by specifying it on the command line, or in the `ccmake(1)` or `cmake-gui(1)` tool. See the `User Interaction Guide` for more about setting cache entries.

## Libraries providing Config-file packages

The most convenient way for a third-party to provide library binaries for use with CMake is to provide Config-file Packages. These packages are text files shipped with the library which instruct CMake how to use the library binaries and associated headers, helper tools and CMake macros provided by the library.

The config files can usually be found in a directory whose name matches the pattern `lib/cmake/<PackageName>`, though they may be in other locations instead. The `<PackageName>` corresponds to use in CMake code with the `find_package()` command such as `find_package(PackageName REQUIRED)`.

The `lib/cmake/<PackageName>` directory will contain a file which is either named `<PackageName>Config.cmake` or `<PackageName>-config.cmake`. This is the entry point to the package for CMake. A separate optional file named `<PackageName>ConfigVersion.cmake` may also exist in the directory. This file is used by CMake to determine whether the version of the third party package satisfies uses of the `find_package()` command which specify version constraints. It is optional to specify a version when using `find_package()`, even if a `ConfigVersion` file is present.

If the `Config.cmake` file is found and the optionally-specified version is satisfied, then the CMake `find_package()` command considers the package to be found and the entire library package is assumed to be complete as designed.

There may be additional files providing CMake macros or Imported Targets for you to use. CMake does not enforce any naming convention for these files. They are related to the primary `Config` file by use of the CMake `include()` command.

`Invoking CMake` with the intent of using a package of third party binaries requires that cmake `find_package()` commands succeed in finding the package. If the location of the package is in a directory known to CMake, the `find_package()` call should succeed. The directories known to cmake are platform-specific. For example, packages installed on Linux with a standard system package manager will be found in the `/usr` prefix automatically. Packages installed in `Program Files` on Windows will similarly be found automatically.

Packages which are not found automatically are in locations not predictable to CMake such as `/opt/mylib` or `$HOME/dev/prefix`. This is a normal situation and CMake provides several ways for users to specify where to find such libraries.

The `CMAKE_PREFIX_PATH` variable may be set when invoking CMake. It is treated as a list of paths to search for Config-file Packages. A package installed in `/opt/somepackage` will typically install config files such as `/opt/somepackage/lib/cmake/somePackage/SomePackageConfig.cmake`. In that case, `/opt/somepackage` should be added to `CMAKE_PREFIX_PATH`.

The environment variable `CMAKE_PREFIX_PATH` may also be populated with prefixes to search for packages. Like the `PATH` environment variable, this is a list and needs to use the platform-specific environment variable list item separator (`:` on Unix and `;` on Windows).

The `CMAKE_PREFIX_PATH` variable provides convenience in cases where multiple prefixes need to be specified, or when multiple different package binaries are available in the same prefix. Paths to packages may also be specified by setting variables matching `<PackageName>_DIR`, such as `SomePackage_DIR`. Note that this is not a prefix but should be a full path to a directory containing a config-style package file, such as `/opt/somepackage/lib/cmake/SomePackage/` in the above example.

## Imported Targets from Packages

A third-party package which provides config-file packages may also provide Imported Targets. These will be specified in files containing configuration-specific file paths relevant to the package, such as debug and release versions of libraries.

Often the third-party package documentation will point out the names of imported targets available after a successful `find_package` for a library. Those imported target names can be used with the `target_link_libraries()` command.

A complete example which makes a simple use of a third party library might look like:

    cmake_minimum_required(VERSION 3.10)
    project(MyExeProject VERSION 1.0.0)

    find_package(SomePackage REQUIRED)
    add_executable(MyExe main.cpp)
    target_link_libraries(MyExe PRIVATE SomePrefix::LibName)

See `cmake-buildsystem(7)` for further information about developing a CMake buildsystem.

### Libraries not Providing Config-file Packages

Third-party libraries which do not provide config-file packages can still be found with the `find_package()` command, if a `FindSomePackage.cmake` file is available.

These module-file packages are different to config-file packages in that:

1. They should not be provided by the third party, except perhaps in the form of documentation

2. The availability of a `Find<PackageName>.cmake` file does not indicate the availability of the binaries themselves.

3. CMake does not search the `CMAKE_PREFIX_PATH` for `Find<PackageName>.cmake` files. Instead CMake searches for such files in the `CMAKE_MODULE_PATH` variable. It is common for users to set the `CMAKE_MODULE_PATH` when running CMake, and it is common for CMake projects to append to `CMAKE_MODULE_PATH` to allow use of local module-file packages.

4. CMake ships `Find<PackageName>.cmake` files for some `third party packages` for convenience in cases where the third party does not provide config-file packages directly. These files are a maintenance burden for CMake, so new Find modules are generally not added to CMake anymore. Third-parties should provide config file packages instead of relying on a Find module to be provided by CMake.

Module-file packages may also provide Imported Targets. A complete example which finds such a package might look like:

    cmake_minimum_required(VERSION 3.10)
    project(MyExeProject VERSION 1.0.0)

    find_package(PNG REQUIRED)

    # Add path to a FindSomePackage.cmake file
    list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
    find_package(SomePackage REQUIRED)

    add_executable(MyExe main.cpp)
    target_link_libraries(MyExe PRIVATE
        PNG::PNG
        SomePrefix::LibName
    )

The `<PackageName>_ROOT` variable is also searched as a prefix for `find_package()` calls using module-file packages such as `FindSomePackage`.