You have a CMake-enabled library project. You need to use it in another library or executable. How to use CMake to find and link to the library? You may have the following preferences:
- write the least possible amount of boiler-plate code
- decouple the internal details of the linked library from the consuming target
Ideally, the usage of the library should look like this:
add_executable(myexe ...)
target_link_libraries(myexe mylib::mylib)
Let me demonstrate a possible solution on a concrete example:
The
myapp
projectWe have an executable target
myapp
. We're linking it withmylib
, which is built in its own build tree. In theCMakeLists.txt
ofmyapp
we find and specifymylib
as a dependency ofmyexe
:Let's see how to set up
mylib
and the build ofmyexe
to make this work.The
mylib
projectThe directory layout of
mylib
:In the
CMakeLists.txt
ofmylib
we need to create the target and specify its source files:The public header
mylib.h
will be included as#include "mylib.h"
both bymylib
and the clients ofmylib
:mylib
itself and other targets built inmylib
's CMake project (for example tests) need to findinclude/mylib.h
from themylib
source treemylib
built in their own projects (likemyexe
) need to findinclude/mylib.h
at its installed locationCMake allows us to specify both include paths for
mylib
:We're using the
PUBLIC
option here since this header is needed on the public interface ofmylib
. UsePRIVATE
for include paths internal tomylib
.The
INSTALL_INTERFACE
specifies a path relative to the install root, that is,CMAKE_INSTALL_PREFIX
. To actually install the public header:We also need to install the library itself and the so-called config-module and related files. The config-module is the file which will be used by consuming projects, like
myapp
to findmylib
and get all the parameters needed to link with it. It is similar to the pkg-config's.pc
files.We need two, related
install
commands. The first one:The list of destinations needed to cover all the standard install locations of static libraries,
dll
's andso
's. If you're sure your library will be built exclusively as a static lib, a singleDESTINATION lib
would make it.The interesting part is the
EXPORT
option. It assigns the list of targets (currently, it's onlymylib
) to the identifiermylib-targets
. This identifier will be used in the next command to generate and install some special files which makefind_package(mylib)
work in the consuming projects:This command generates multiple files:
mylib-config.cmake
The files will be installed into
${CMAKE_INSTALL_PREFIX}/lib/cmake/mylib
which is one of the many standard locations thefind_package(mylib)
command will search formylib-config.cmake
.Building
mylib
We need to specify an install location in the variable
CMAKE_INSTALL_PREFIX
:and build and install the library:
Building
myexe
myexe
needs to know where to look formylib
. The variableCMAKE_PREFIX_PATH
can be a list of paths. We need to specify the previous install location:A note on building multiple configurations
Usually we need to build multiple configurations (
Debug
,Release
). A critical issue is to specify configuration-dependent filenames or install locations. For example, you can set the default value of theDEBUG_POSTFIX
property for the library project:The debug version of the
mylib
library file will be namedlibmylibd.lib
(ormylibd.lib
on Windows). The generatedEXPORT
files will contain the modified filenames.If you're using makefile-style CMake generators you can control the build configuration by setting the
CMAKE_BUILD_TYPE
variable:You may need seperate build directories for each configuration or you can re-use the same build dir. In that case, to play it safe it's best to explicitly clean before build:
If you're using a multiconfig IDE generator, like
Xcode
orVisual Studio
, you need to specify the configuration in build time:References
You can clone and build this repository which contains the
mylib
andmyexe
projects (tested on Windows and Linux).Check out the CMake documentation. The most important related commands are:
and two detailed articles: