如何使用 CMake 查找并链接到使用 install-export 和 find_package 的库? [英] How to use CMake to find and link to a library using install-export and find_package?
问题描述
您有一个支持 CMake 的库项目.您需要在另一个库或可执行文件中使用它.如何使用 CMake 查找并链接到库?您可能有以下偏好:
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:
- 编写尽可能少的样板代码
- 将链接库的内部细节与消费目标分离
理想情况下,库的用法应该是这样的:
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:
我们有一个可执行目标 myapp
.我们将它与 mylib
链接,后者构建在自己的构建树中.在myapp
的CMakeLists.txt
中,我们找到并指定mylib
作为myexe
的依赖:
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::mylib)
让我们看看如何设置 mylib
和构建 myexe
来完成这项工作.
Let's see how to set up mylib
and the build of myexe
to make this work.
mylib
的目录布局:
mylib
- CMakeLists.txt
- mylib.c
+ include
- mylib.h # single public header
在mylib
的CMakeLists.txt
中,我们需要创建目标并指定其源文件:
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)
公共头文件 mylib.h
将被 mylib
和 的客户端包含为
:#include "mylib.h"
>mylib
The public header mylib.h
will be included as #include "mylib.h"
both by mylib
and the clients of mylib
:
mylib
本身和mylib
的 CMake 项目中内置的其他目标(例如测试)需要从中找到include/mylib.h
mylib
源代码树mylib
的客户端(如myexe
)内置在自己的项目中,需要在其安装位置找到include/mylib.h
莉>
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 允许我们为 mylib
指定两个包含路径:
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>)
我们在此处使用 PUBLIC
选项,因为 mylib
的公共接口需要此标头.将 PRIVATE
用于 mylib
内部的包含路径.
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
.
INSTALL_INTERFACE
指定相对于安装根目录的路径,即CMAKE_INSTALL_PREFIX
.实际安装公共标头:
The INSTALL_INTERFACE
specifies a path relative to the install root, that is, CMAKE_INSTALL_PREFIX
. To actually install the public header:
set_target_properties(mylib PROPERTIES PUBLIC_HEADER include/mylib.h")
我们还需要安装库本身以及所谓的配置模块和相关文件.config-module 是消费项目将使用的文件,例如 myapp
以查找 mylib
并获取与其链接所需的所有参数.它类似于 pkg-config 的 .pc
文件.
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.
我们需要两个相关的 install
命令.第一个:
We need two, related install
commands. The first one:
install(TARGETS mylib
EXPORT mylib-targets
PUBLIC_HEADER DESTINATION include
ARCHIVE DESTINATION lib
LIBRARY DESTINATION lib
RUNTIME DESTINATION bin)
需要覆盖静态库、dll
和 so
的所有标准安装位置所需的目标列表.如果您确定您的库将专门构建为静态库,则可以使用单个 DESTINATION lib
.
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.
有趣的部分是 EXPORT
选项.它将目标列表(目前只有 mylib
)分配给标识符 mylib-targets
.此标识符将在下一个命令中用于生成和安装一些特殊文件,这些文件使 find_package(mylib)
在消费项目中工作:
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
NAMESPACE mylib::
FILE mylib-config.cmake
DESTINATION lib/cmake/mylib)
此命令生成多个文件:
- 每个构建配置(调试、发布等)一个文件,描述库文件和配置相关参数
- 一个描述与配置无关的参数的文件,还包括所有与配置相关的文件.由于此文件也可以单独用作配置模块,因此我们只需将其重命名为
mylib-config.cmake
文件将安装到 ${CMAKE_INSTALL_PREFIX}/lib/cmake/mylib
中,这是 find_package(mylib)
命令将搜索的众多标准位置之一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
.
我们需要在变量CMAKE_INSTALL_PREFIX
中指定一个安装位置:
We need to specify an install location in the variable CMAKE_INSTALL_PREFIX
:
mkdir build
cd build
cmake -DCMAKE_INSTALL_PREFIX=$PWD/../out ../mylib
并构建和安装库:
cmake --build . --target install
构建myexe
myexe
需要知道去哪里寻找 mylib
.变量 CMAKE_PREFIX_PATH
可以是路径列表.我们需要指定之前的安装位置:
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 ../myexe
cmake --build .
关于构建多个配置的说明
通常我们需要构建多个配置(Debug
、Release
).一个关键问题是指定依赖于配置的文件名或安装位置.例如,您可以为库项目设置 DEBUG_POSTFIX
属性的默认值:
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)
mylib
库文件的调试版本将命名为 libmylibd.lib
(或 Windows 上的 mylibd.lib
).生成的 EXPORT
文件将包含修改后的文件名.
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.
如果您使用的是 makefile 样式的 CMake 生成器,您可以通过设置 CMAKE_BUILD_TYPE
变量来控制构建配置:
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
如果您使用的是多配置 IDE 生成器,例如 Xcode
或 Visual Studio
,则需要在构建时指定配置:
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
参考文献
您可以克隆和构建这个存储库,其中包含mylib
和 myexe
项目(在 Windows 和 Linux 上测试).
References
You can clone and build this repository which contains the mylib
and myexe
projects (tested on Windows and Linux).
查看 CMake 文档.最重要的相关命令是:
Check out the CMake documentation. The most important related commands are:
和两篇详细的文章:
这篇关于如何使用 CMake 查找并链接到使用 install-export 和 find_package 的库?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!