如何使用 CMake 查找并链接到使用 install-export 和 find_package 的库? [英] How to use CMake to find and link to a library using install-export and find_package?

查看:44
本文介绍了如何使用 CMake 查找并链接到使用 install-export 和 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 链接,后者构建在自己的构建树中.在myappCMakeLists.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

mylibCMakeLists.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.hmylib 源代码树
  • mylib 的客户端(如myexe)内置在自己的项目中,需要在其安装位置找到include/mylib.h莉>
  • mylib itself and other targets built in mylib's CMake project (for example tests) need to find include/mylib.h from the mylib source tree
  • clients of mylib built in their own projects (like myexe) need to find include/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)

需要覆盖静态库、dllso 的所有标准安装位置所需的目标列表.如果您确定您的库将专门构建为静态库,则可以使用单个 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 .

关于构建多个配置的说明

通常我们需要构建多个配置(DebugRelease).一个关键问题是指定依赖于配置的文件名或安装位置.例如,您可以为库项目设置 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 生成器,例如 XcodeVisual 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

参考文献

您可以克隆和构建这个存储库,其中包含mylibmyexe 项目(在 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆