【问题标题】:How to use CMake to find and link to a library using install-export and find_package?如何使用 CMake 使用 install-export 和 find_package 查找并链接到库?
【发布时间】:2015-07-21 11:19:28
【问题描述】:

您有一个启用 CMake 的库项目。您需要在另一个库或可执行文件中使用它。如何使用 CMake 查找并链接到库?您可能有以下偏好:

  • 尽可能少地编写样板代码
  • 将链接库的内部细节与消费目标解耦

理想情况下,该库的用法应如下所示:

add_executable(myexe ...)
target_link_libraries(myexe mylib::mylib)

【问题讨论】:

标签: cmake


【解决方案1】:

让我通过一个具体的例子来演示一个可能的解决方案:

myapp 项目

我们有一个可执行目标myapp。我们将它与mylib 链接起来,它是在它自己的构建树中构建的。在myappCMakeLists.txt 中,我们找到并指定mylib 作为myexe 的依赖项:

find_package(mylib REQUIRED)
...
add_executable(myexe ...)
target_link_libraries(myexe mylib::mylib)

让我们看看如何设置 mylib 和构建 myexe 来完成这项工作。

mylib 项目

mylib的目录布局:

mylib
- CMakeLists.txt
- mylib.c
+ include
  - mylib.h # single public header

mylibCMakeLists.txt 中,我们需要创建目标并指定其源文件:

add_library(mylib mylib.c include/mylib.h)

mylibmylib 的客户都将公共标头mylib.h 包含为#include "mylib.h"

  • mylib本身和mylib的CMake项目中构建的其他目标(例如测试)需要从mylib源树中找到include/mylib.h
  • mylib 的客户在自己的项目中构建(如myexe)需要在其安装位置找到include/mylib.h

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。实际安装公共标头:

    set_target_properties(mylib PROPERTIES PUBLIC_HEADER  include/mylib.h")

我们还需要安装库本身以及所谓的 config-module 和相关文件。 config-module 是消费项目将使用的文件,例如 myapp 以查找 mylib 并获取与其链接所需的所有参数。它类似于 pkg-config.pc 文件。

我们需要两个相关的install 命令。第一个:

install(TARGETS mylib
    EXPORT mylib-targets
    PUBLIC_HEADER DESTINATION include
    ARCHIVE DESTINATION lib
    LIBRARY DESTINATION lib
    RUNTIME DESTINATION bin)

包含静态库的所有标准安装位置所需的目标列表,dllso。如果您确定您的库将专门构建为静态库,则可以使用单个 DESTINATION lib

有趣的部分是EXPORT 选项。它将目标列表(目前只有mylib)分配给标识符mylib-targets。此标识符将在下一个命令中用于生成和安装一些特殊文件,这些文件使 find_package(mylib) 在消费项目中工作:

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 的众多标准位置之一。

大楼mylib

我们需要在变量CMAKE_INSTALL_PREFIX中指定安装位置:

mkdir build
cd build
cmake -DCMAKE_INSTALL_PREFIX=$PWD/../out ../mylib

并构建和安装库:

cmake --build . --target install

大楼myexe

myexe 需要知道在哪里寻找mylib。变量CMAKE_PREFIX_PATH 可以是路径列表。我们需要指定之前的安装位置:

mkdir build
cd build
cmake -DCMAKE_PREFIX_PATH=$PWD/../out ../myexe
cmake --build .

关于构建多个配置的说明

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

您可能需要为每个配置使用单独的构建目录,或者您可以重复使用相同的构建目录。在这种情况下,为了安全起见,最好在构建之前明确清理:

cmake --build . --target install --clean-first

如果您使用的是多配置 IDE 生成器,例如 XcodeVisual Studio,则需要在构建时指定配置:

cmake -DCMAKE_INSTALL_PREFIX=$PWD/../out ../mylib
cmake --build . --target install --config Release

参考文献

您可以克隆和构建包含mylibmyexe 项目的this repository(在Windows 和Linux 上测试)。

查看CMake documentation。最重要的相关命令是:

还有两篇详细的文章:

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-05-25
    • 1970-01-01
    • 2021-05-23
    • 2019-12-22
    • 1970-01-01
    • 1970-01-01
    • 2023-03-31
    相关资源
    最近更新 更多