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.
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.
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.
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.
As the library provides a pkg-config file, I could rely fully on the pkg-config and use FindPkgConfig 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.
I copy the behaviour of many CMake-provided FindModules and use pkg-config as a hint to finding the library using find_library 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
There are multiple options to upstream direct CMake support, including not adding any direct support at all, solely relying on the above FindModule.
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.
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.
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.
- 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?