Including external libraries in a cmake project is usually performed using find_package()
.
But in a large multi-application / multi-library project, it is typical for some 3rd-party and/or system libraries to be used by multiple applications and libraries.
Where should find_package()
for these common libraries be called?
CMakeLists.txt
file for each executable/library that needs them?CMakeLists.txt
file?The first options seems to be a more modular approach, but the associated find_package()
scripts are executed for each library/executable that uses them. This can slow down the configuration step.
The second option is more efficient, but looks a bit too much like a global variable to me.
CMake ships with its own set of built-in find_package scripts, and their location is in the default CMAKE_MODULE_PATH.
CMake searches for a file called Find<package>. cmake in the CMAKE_MODULE_PATH followed by the CMake installation. If the file is found, it is read and processed by CMake. It is responsible for finding the package, checking the version, and producing any needed messages.
CMakeLists. txt is placed at the root of the source tree of any application, library it will work for. If there are multiple modules, and each module can be compiled and built separately, CMakeLists. txt can be inserted into the sub folder.
For a candidate package configuration file <config-file>. cmake the corresponding version file is located next to it and named either <config-file>-version. cmake or <config-file>Version. cmake .
I would distinguish between subprojects/-directories that might be standalone packages on their own (or already are) and those that exclusively reflect the source code structure.
In the first case, find_package
should clearly be in the subdirectory CMakeLists.txt
to allow for extracting the subdirectory for a standalone build or distribution. Inefficiency of the configuration step should not be a concern here, as the configuration of a build is not performed that often.
In the second case, I would prefer find_package
calls in the toplevel CMakeLists.txt
. If you don't use the variables set by these calls to populate global variables but use target_link_libraries
instead (as suggested in the comments), this should be clean enough. Sometimes though, found packages do not export proper targets to link against, but rather define some include path variables and the like. Then, it should be easy to define your own INTERFACE
library that encapsulate these flags/paths as usage requirements and propagate them transitively when linked via target_link_libraries
again.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With