如何使用CMake查找和链接到库使用install-export和find_package? [英] How to use CMake to find and link to a library using install-export and find_package?
问题描述
您有一个启用了CMake的库项目。您需要在另一个库或可执行文件中使用它。如何使用CMake找到并链接到图书馆?您可能有以下偏好设置:
- 写尽可能少的样板代码
- 将链接库的内部细节从使用目标中解耦
理想情况下,库的使用应如下所示:
add_executable(myexe ...)
让我来演示一个具体例子的可能的解决方案:
target_link_libraries(myexe mylib)
h1>myapp
项目
我们有一个可执行目标
myapp
。我们将它与mylib
链接,它是在自己的构建树中构建的。在CMakeLists.txt
的myapp
中,我们找到并指定mylib
作为myexe的依赖项
:find_package(mylib REQUIRED)
...
add_executable(myexe ...)
target_link_libraries(myexe mylib)
让我们来看看如何设置
mylib
和myexe
p>
mylib
项目
mylib
:mylib
- CMakeLists.txt
- mylib.c
+ include
- mylib.h#single public header
在
CMakeLists.txt
mylib
中,我们需要创建目标并指定其源文件:add_library(mylib mylib.c include / mylib.h)
公共头
mylib.h
将作为#includemylib.h
两个都由mylib
和mylib
的客户:
-
mylib
本身和其他目标内置于mylib
的CMake项目例如测试)需要从mylib
源代码树 中找到 - 在其自己的项目(如
myexe
)中创建mylib
的客户需要查找include / mylib.h
在其安装位置
include / mylib.h
b CMake允许我们指定 mylib
:
target_include_directories(mylib PUBLIC
$< BUILD_INTERFACE :$ {CMAKE_CURRENT_SOURCE_DIR} / include>
$< INSTALL_INTERFACE:include>)
我们使用 PUBLIC
选项,因为在 mylib
的公共接口上需要此标头。使用 PRIVATE
以包含 mylib
内部的包含路径。
INSTALL_INTERFACE
指定相对于安装根目录的路径,即 CMAKE_INSTALL_PREFIX
。实际安装公开标头:
install(FILES include / mylib.h DESTINATION include)
我们还需要安装库本身和所谓的配置模块和相关文件。 config-module是将被消费项目使用的文件,例如 myapp
找到 mylib
,并获取所有参数需要链接到它。它类似于 pkg-config 的 .pc
文件。
需要两个,相关的 install
命令。第一个:
安装(TARGETS mylib
导出mylib目标
ARCHIVE DESTINATION lib
LIBRARY DESTINATION lib
RUNTIME DESTINATION bin)
覆盖所有标准安装静态库的位置, dll
和所以
的。如果您确定您的库将仅作为静态库构建,则单个 DESTINATION lib
将会创建它。
有趣的部分是 EXPORT
选项。它将目标列表(目前只有 mylib
)分配给标识符 mylib-targets
。这个标识符将在下一个命令中用于生成和安装一些特殊的文件,使 find_package(mylib)
在消费项目中工作:
install(EXPORT mylib-targets
FILE mylib-config.cmake
DESTINATION lib / cmake / mylib)
此命令生成多个文件:
- 文件,用于描述库文件和配置相关参数的每个构建配置(Debug,Release等)
- 一个描述配置不可知参数的文件,还包括所有配置依赖文件。因为这个文件也可以作为一个配置模块自己使用,我们只需要重命名为
mylib-config.cmake
这些文件将安装到 $ {CMAKE_INSTALL_PREFIX} / lib / cmake / mylib
code> find_package(mylib)命令将搜索 mylib-config.cmake
。
建立 mylib
我们需要在变量 CMAKE_INSTALL_PREFIX
:
mkdir build
cd build
cmake -DCMAKE_INSTALL_PREFIX = $ PWD /../ out ../mylib
并构建并安装库:
cmake --build。 --target install
构建 myexe
h1>
myexe
需要知道在哪里查找 mylib
。变量 CMAKE_PREFIX_PATH
可以是路径列表。我们需要指定先前的安装位置:
mkdir build
cd build
cmake -DCMAKE_PREFIX_PATH = $ PWD /../ out ../mylib
cmake --build。
有关构建多个配置的注意事项
通常我们需要构建多个配置( Debug
, Release
)。一个关键问题是指定依赖于配置的文件名或安装位置。例如,您可以为库项目设置 DEBUG_POSTFIX
属性的默认值:
set(CMAKE_DEBUG_POSTFIX d)
mylib
库文件将命名为 libmylibd.lib
(或在Windows上命名为 mylibd.lib
。 EXPORT
文件将包含修改的文件名。
如果您使用makefile风格的CMake生成器,通过设置 CMAKE_BUILD_TYPE
变量来控制构建配置:
cmake -DCMAKE_BUILD_TYPE = Release -DCMAKE_INSTALL_PREFIX = $ PWD /../ out ../mylib
cmake --build。 --target install
您可能需要为每个配置分别构建目录,或者可以重复使用构建目录。在这种情况下,为了安全起见,最好在build之前显式清除:
cmake --build。 --target install --clean-first
如果您使用多配置IDE生成器, code> Xcode 或 Visual Studio
,您需要在构建时指定配置:
cmake -DCMAKE_INSTALL_PREFIX = $ PWD /../ out ../mylib
cmake --build。 --target install --config发布
参考
您可以克隆并构建此存储库,其中包含 mylib
c> a href =http://www.cmake.org/cmake/help/v3.3> CMake文档。最重要的相关命令是:
- add_library
- target_link_libraries
- find_package
- 安装 a>
- target_include_directories li>
- target_compile_definitions
和两个详细文章:
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)
Let me demonstrate a possible solution on a concrete example:
The myapp
project
We have an executable target myapp
. We're linking it with mylib
, which is built in its own build tree. In the CMakeLists.txt
of myapp
we find and specify mylib
as a dependency of myexe
:
find_package(mylib REQUIRED)
...
add_executable(myexe ...)
target_link_libraries(myexe mylib)
Let's see how to set up mylib
and the build of myexe
to make this work.
The mylib
project
The directory layout of mylib
:
mylib
- CMakeLists.txt
- mylib.c
+ include
- mylib.h # single public header
In the CMakeLists.txt
of mylib
we need to create the target and specify its source files:
add_library(mylib mylib.c include/mylib.h)
The public header mylib.h
will be included as #include "mylib.h"
both by mylib
and the clients of mylib
:
mylib
itself and other targets built inmylib
's CMake project (for example tests) need to findinclude/mylib.h
from themylib
source tree- clients of
mylib
built in their own projects (likemyexe
) need to findinclude/mylib.h
at its installed location
CMake allows us to specify both include paths for mylib
:
target_include_directories(mylib PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>)
We're using the PUBLIC
option here since this header is needed on the public interface of mylib
. Use PRIVATE
for include paths internal to mylib
.
The INSTALL_INTERFACE
specifies a path relative to the install root, that is, CMAKE_INSTALL_PREFIX
. To actually install the public header:
install(FILES include/mylib.h DESTINATION include)
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 find mylib
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:
install(TARGETS mylib
EXPORT mylib-targets
ARCHIVE DESTINATION lib
LIBRARY DESTINATION lib
RUNTIME DESTINATION bin)
The list of destinations needed to cover all the standard install locations of static libraries, dll
's and so
's. If you're sure your library will be built exclusively as a static lib, a single DESTINATION lib
would make it.
The interesting part is the EXPORT
option. It assigns the list of targets (currently, it's only mylib
) to the identifier mylib-targets
. This identifier will be used in the next command to generate and install some special files which make find_package(mylib)
work in the consuming projects:
install(EXPORT mylib-targets
FILE mylib-config.cmake
DESTINATION lib/cmake/mylib)
This command generates multiple files:
- one file for each build configuration (Debug, Release, etc..) which describes the library file and configuration-dependent parameters
- a file which describes the configuration-agnostic parameters and also includes all the config-dependent files. Since this file can also be used as a config-module on its own we simply rename it as
mylib-config.cmake
The files will be installed into ${CMAKE_INSTALL_PREFIX}/lib/cmake/mylib
which is one of the many standard locations the find_package(mylib)
command will search for mylib-config.cmake
.
Building mylib
We need to specify an install location in the variable CMAKE_INSTALL_PREFIX
:
mkdir build
cd build
cmake -DCMAKE_INSTALL_PREFIX=$PWD/../out ../mylib
and build and install the library:
cmake --build . --target install
Building myexe
myexe
needs to know where to look for mylib
. The variable CMAKE_PREFIX_PATH
can be a list of paths. We need to specify the previous install location:
mkdir build
cd build
cmake -DCMAKE_PREFIX_PATH=$PWD/../out ../mylib
cmake --build .
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 the DEBUG_POSTFIX
property for the library project:
set(CMAKE_DEBUG_POSTFIX d)
The debug version of the mylib
library file will be named libmylibd.lib
(or mylibd.lib
on Windows). The generated EXPORT
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:
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=$PWD/../out ../mylib
cmake --build . --target install
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:
cmake --build . --target install --clean-first
If you're using a multiconfig IDE generator, like Xcode
or Visual Studio
, you need to specify the configuration in build time:
cmake -DCMAKE_INSTALL_PREFIX=$PWD/../out ../mylib
cmake --build . --target install --config Release
References
You can clone and build this repository which contains the mylib
and myexe
projects (tested on Windows and Linux).
Check out the CMake documentation. The most important related commands are:
- add_library
- target_link_libraries
- find_package
- install
- target_include_directories
- target_compile_definitions
and two detailed articles:
这篇关于如何使用CMake查找和链接到库使用install-export和find_package?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!