# Adding CMake support to existing library

**URL:** https://discourse.cmake.org/t/adding-cmake-support-to-existing-library/9306
**Category:** Usage
**Created:** [October 30, 2023, 12:34pm UTC](https://discourse.cmake.org/t/adding-cmake-support-to-existing-library/9306 "2023-10-30T12:34:00Z")
**Posts on this page:** 3
**Page:** 1

<div class="post-metadata">

### Author: ![fsimonis](https://discourse.cmake.org/user_avatar/discourse.cmake.org/fsimonis/32/1712_2.png) [@fsimonis](https://discourse.cmake.org/u/fsimonis)
#### Post date: [October 30, 2023, 12:34pm UTC](https://discourse.cmake.org/t/adding-cmake-support-to-existing-library/9306/1 "2023-10-30T12:34:00Z")

</div>

Hi,  
I try to keep this question and its context as generic as possible, to help others who may be facing a similar challenge. Also, @craig.scott s excellent Professional CMake barely touches this part and I hope this question could spark some ideas for additional content.

## Goal

My goal is to provide direct CMake support for an existing library which is both forward and backward-compatible.

This means that I would like to contribute CMake support directly upstream into the library starting at some version X, and provide a FindModule to allow forward-compatibility for versions before X.  
Both the CMake config and the FindModule should provide the same variables and the same target to link against.

## Further context

The library is complex and has a custom build configuration, which generates a pkg-config file using a python script.  
pkg-config support is available for all relevant versions of the library.

It also allows downloading, building and installing dependencies during the configuration step. This can make the pkg-config file rather complex. Flags are not straight forward.

Finally, the primary library maintainers are not daily users of CMake, which makes code simplicity even more significant.

## Support for versions prior to X

To provide forward-compatibility, I could write a FindModule which can then be copied into other projects to detect older versions of the library. This poses the question on how to design it.

### Rely on pkg-config

As the library provides a pkg-config file, I could rely fully on the pkg-config and use [FindPkgConfig](https://cmake.org/cmake/help/latest/module/FindPkgConfig.html#command:pkg_search_module) to locate the library.  
In the FindModule, I would locate the library, set up variables as well as an imported target with an alias.

**Pro:** everything complex is handled by the FindPkgConfig CMake FindModule. The Module is clean, simple, and understandable for non CMake experts.  
**Contra:** pkg-config is required on the system and the pc files have to be detectable.

### Use pkg-config as a hint

I copy the behaviour of many CMake-provided FindModules and use pkg-config as a hint to finding the library using [find\_library](https://cmake.org/cmake/help/latest/command/find_library.html) etc.  
In the Find module, I would locate the library using pkg-config if it is available on the system, locate the library using the pkg-config info as hints, attempt handle additional flags, set up variables as well as an imported target.

**Pro:** does not require a pkg-config installation  
**Contra:** correctly handling all flags the find module is very complex and poses a severe maintenance burden

## Support starting at version X

There are multiple options to upstream direct CMake support, including not adding any direct support at all, solely relying on the above FindModule.

### Generate CMake config files

I could reuse the existing code used to generate the pkg-config files to additionally generate CMake config and version files.

**Pro:** direct CMake support without additional dependencies  
**Contra:** Adds maintainability overhead, as multiple places need to be changed to keep these config files consistent.

### CMake Config as a pkg-config wrapper

I could reuse the existing code to generate a CMake version file and a CMake Config file which internally used pkg-config to request the exact version.

**Pro:** less code to maintain as the complicated parts are handled when creating the pkg-config file  
**Contra:** may detect incorrect versions via pkg-config (same version different build) and requires pkg-config to be installed on the system.

### FindModule only

I don’t provide CMake config and version files, but solely rely on the provided FindModule.

**Pro:** Even less code to maintain. No need to keep functionality aligned between the CMake config and the FindModule.  
**Contra:** Limits functionality to the information provided by the FindModule. If it requires pkg-config to work, then CMake support as a whole requires a pkg-config installation.

These are the options I have considered until now.

## Questions to the CMake community and developers:

- Can you think of further options, pros, or cons?
- Has experience shown that some methods are to be avoided/preferred?
- Which method would you accept as a contribution to your code base?

---

<div class="post-metadata">

### Author: ![ben.boeckel](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/b/ea5d25/32.png) [@ben.boeckel](https://discourse.cmake.org/u/ben.boeckel)
#### Post date: [October 30, 2023, 2:00pm UTC](https://discourse.cmake.org/t/adding-cmake-support-to-existing-library/9306/2 "2023-10-30T14:00:12Z")

</div>

> [@fsimonis](#):
>
> This means that I would like to contribute CMake support directly upstream into the library starting at some version X, and provide a FindModule to allow forward-compatibility for versions before X.  
> Both the CMake config and the FindModule should provide the same variables and the same target to link against.

I highly recommend making the `-config.cmake` variant first and then making that interface through the `Find` module directly. Avoid variables where possible and instead only provide `IMPORTED` targets. You can then stick this at the top of the `Find` module:

```cmake
unset(Name_FOUND)
unset(Name_NOT_FOUND_MESSAGE)
find_package(Name CONFIG) # may want to forward QUIET and COMPONENTS
if (Name_FOUND)
  # Canonical interface, just return.
  return ()
elseif (DEFINED Name_NOT_FOUND_MESSAGE)
  # Found the package, but it said "no"; let it stand.
  return ()
endif ()

```

The `config.cmake` file can then fill out `Name_NOT_FOUND_MESSAGE` for any reason why a request wasn’t reasonable and avoid the `Find` module’s logic.

> [@fsimonis](#):
>
> Finally, the primary library maintainers are not daily users of CMake, which makes code simplicity even more significant.

If that’s the case, providing a proper `-config.cmake` file is not really in the “trivial” category IME (especially for a project as complicated as “downloads its own dependencies”). I suspect you might be best by generating a `-config.cmake` from the `.pc` file information at build time rather than trying to make CMake targets directly (unless the project plans on moving the CMake exclusively).

> [@fsimonis](#):
>
> Limits functionality to the information provided by the FindModule

The main power of `-config.cmake` files is that CMake provides a lot of the information in a reliable way. Nothing stops a `Find` module from providing the same quality except how much work it is.

---

<div class="post-metadata">

### Author: ![craig.scott](https://discourse.cmake.org/user_avatar/discourse.cmake.org/craig.scott/32/20_2.png) [@craig.scott](https://discourse.cmake.org/u/craig.scott)
#### Post date: [October 30, 2023, 8:57pm UTC](https://discourse.cmake.org/t/adding-cmake-support-to-existing-library/9306/3 "2023-10-30T20:57:16Z")

</div>

> [@ben.boeckel](#):
>
> The main power of `-config.cmake` files is that CMake provides a lot of the information in a reliable way. Nothing stops a `Find` module from providing the same quality except how much work it is.

To me, the biggest driver to using `-config.cmake` files instead of Find modules is not the format of the file, but the fact that `-config.cmake` files come with the package they are providing, whereas a Find module is typically provided by something outside that package. This means Find modules are almost always less reliable than `-config.cmake` files because a Find module has to deal with an unbounded range of package versions, but a `-config.cmake` file only has to deal with one package and it knows exactly what should be in that package.
