【CMake系列】07-export与find

为了将我们的库文件更方便地提供给他人使用,cmake 提供了一种方式,通过查找 .cmake 文件,将库导入项目中。
本节学习的内容,就是将我们的库导出一个 xxx.cmake 文件,以及 在项目中导入

本专栏的实践代码全部放在 github 上,欢迎 star !!!

如有问题,欢迎留言、或加群【392784757】交流

xxxConfig.cmake 文件是一个 CMake 配置文件用于在项目中查找和使用某个库。目的是方便在其 CMake 构建系统中找到并正确配置该库。

cmake_minimum_required(VERSION 3.20)

project(export_my_package)

file(WRITE include/slib.h "void slib();")
file(WRITE slib.cpp [=[

#include <iostream>
#include "slib.h"
void slib()
{
  std::cout<<"in slib func\n" <<std::endl;
}
]=])

add_library(slib STATIC slib.cpp)
# 导出头文件; file glob 加入所有 头文件
set_target_properties(slib PROPERTIES PUBLIC_HEADER include/slib.h)

设置 头文件include路径,这里的设置有两个层面
如果仅这样设置

target_include_directories(slib PUBLIC include) # PUBLIC 第三方调用时 也可以导入头文件

会在构建时报错

#[[
Target "slib" INTERFACE_INCLUDE_DIRECTORIES property contains path:

    "E:/my-github-repos/learn-cmake-together/ref_course/506export_my_package/include"

  which is prefixed in the source directory.

]]

提示 INTERFACE_INCLUDE_DIRECTORIES 包含了一个源目录路径。这个路径是绝对路径,而不是相对于安装目录的相对路径。当你尝试导出或安装这个目标时,绝对路径可能会导致错误,因为在安装后的环境中,这个路径可能不存在。
因此我们需要对这个include 路径进行 分别设置,一个是 构建时,一个是导出时【也就是他人使用时 用到的路径】

通过 生成表达式 我们可以根据 是在哪个行为 进而设置路径

# 路径被两次引用 1 编译slib 库时 2 export 写入config时
target_include_directories(slib PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> # 仅在编译时有效
$<INSTALL_INTERFACE:include> # 只在install 时有值 绝对路径/include
) 

安装导出

在安装过程中,通过添加EXPORT 这一指令,将我们的库配置文件导出

install(TARGETS slib
EXPORT slib # 导出
RUNTIME DESTINATION bin
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
PUBLIC_HEADER DESTINATION include
)

install(EXPORT slib FILE slibConfig.cmake DESTINATION config)

导出文件的默认名称
# Config.cmake
# slibConfig.cmake

构建指令

cmake -B build -S .
cmake --build build
cmake --install build --prefix=out # --config=Debug # windows下需要添加--congig

执行后,结构如下
在这里插入图片描述
在config 目录下,有库对应的 xxx.cmake 文件,也就是我们后续导入库 需要找到的文件

导入

cmake_minimum_required(VERSION 3.20)
project(find_my_package)

file(WRITE main.cpp [=[

#include "slib.h"
#include <iostream>

using namespace std;
int main()
{
  cout<<"in main"<<endl;
  slib();
  return 0;
}
]=])
find_package(slib)

message("slib_found = ${slib_FOUND}")
if(slib_FOUND)
message("find slib success!")
endif()

add_executable(main main.cpp)

target_link_libraries(main slib)

get_target_property(inc slib INTERFACE_INCLUDE_DIRECTORIES)
message("INTERFACE_INCLUDE_DIRECTORIES = ${inc}")

执行后提示 找不到

CMake Warning at CMakeLists.txt:21 (find_package):
  By not providing "Findslib.cmake" in CMAKE_MODULE_PATH this project has
  asked CMake to find a package configuration file provided by "slib", but
  CMake did not find one.

  Could not find a package configuration file provided by "slib" with any of
  the following names:

    slibConfig.cmake
    slib-config.cmake

  Add the installation prefix of "slib" to CMAKE_PREFIX_PATH or set
  "slib_DIR" to a directory containing one of the above files.  If "slib"
  provides a separate development package or SDK, be sure it has been
  installed.

通过提示,我们看到添加slib路径的方法

  1. 添加 slib 安装路径 到 CMAKE_PREFIX_PATH
  2. 设置 slib_DIR 变量 包含 xxx.cmake 路径
set(slib_DIR "替换包含 slibConfig.cmake 所在的路径")

然后重新构建,执行

导入成功
在这里插入图片描述

版本问题

相关的库可以设置版本,设定相应的限制,只导入指定要求的版本,这样也需要在导出配置时,进行一定的设置
version 的变量值 可以预先设定 + -Dversion 传入的方式实现

install(EXPORT slib FILE slibConfig.cmake DESTINATION config/slib-${version})
# <packagename>Config.cmake
# slibConfig.cmake

# 写入版本信息 slibConfigVersion.cmake
include(CMakePackageConfigHelpers)
write_basic_package_version_file(
  ${CMAKE_INSTALL_PREFIX}/config/slib-${version}/slibConfigVersion.cmake
  VERSION ${version}
  COMPATIBILITY SameMajorVersion #版本兼容问题 cmake.org.cn
)
posted @ 2024-06-12 13:34  蔡不菜和他的uU们  阅读(39)  评论(0编辑  收藏  举报