为了将我们的库文件更方便地提供给他人使用,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
)

【CMake系列】07-export与find的更多相关文章

  1. Java 集合系列 07 List总结(LinkedList, ArrayList等使用场景和性能分析)

    java 集合系列目录: Java 集合系列 01 总体框架 Java 集合系列 02 Collection架构 Java 集合系列 03 ArrayList详细介绍(源码解析)和使用示例 Java ...

  2. JavaScript进阶系列07,鼠标事件

    鼠标事件有Keydown, Keyup, Keypress,但Keypress与Keydown和Keyup不同,如果按ctrl, shift, caps lock......等修饰键,不会触发Keyp ...

  3. 委托、Lambda表达式、事件系列07,使用EventHandler委托

    谈到事件注册,EventHandler是最常用的. EventHandler是一个委托,接收2个形参.sender是指事件的发起者,e代表事件参数. □ 使用EventHandler实现猜拳游戏 使用 ...

  4. 线程系列07,使用lock语句块或Interlocked类型方法保证自增变量的数据同步

    假设多个线程共享一个静态变量,如果让每个线程都执行相同的方法每次让静态变量自增1,这样的做法线程安全吗?能保证自增变量数据同步吗?本篇体验使用lock语句块和Interlocked类型方法保证自增变量 ...

  5. C#程序集系列07,篡改程序集

    以下几个方面用来区分不同的程序集:○ 程序集名称:Name○ 程序集版本:Version○ 程序集公匙: Public Token○ 程序集文化:Culture 如果没有很严格地按照上面的几个方面来创 ...

  6. CMake命令之export

    CMake中与export()相关的命令 (注:红色字体是标题,粉色是需要特别需要注意的地方) 总的来说,export()命令想要做的事情可以用一句话概括:Export targets from th ...

  7. Hibernate 系列 07 - Hibernate中Java对象的三种状态

    引导目录: Hibernate 系列教程 目录 1. Java对象的三种状态 当应用通过调用Hibernate API与框架发生交互时,需要从持久化的角度关注应用对象的生命周期. 持久化声明周期是Hi ...

  8. Java 集合系列07之 Stack详细介绍(源码解析)和使用示例

    概要 学完Vector了之后,接下来我们开始学习Stack.Stack很简单,它继承于Vector.学习方式还是和之前一样,先对Stack有个整体认识,然后再学习它的源码:最后再通过实例来学会使用它. ...

  9. Android Studio 单刷《第一行代码》系列 07 —— Broadcast 广播

    前情提要(Previously) 本系列将使用 Android Studio 将<第一行代码>(书中讲解案例使用Eclipse)刷一遍,旨在为想入坑 Android 开发,并选择 Andr ...

  10. 1. CMake 系列 - 从零构建动态库和静态库

    目录 1. 文件目录结构 2. 库文件源代码 3. 编译生成库文件 1. 文件目录结构 首先创建如下目录结构: └── lib ├── build # ├── CMakeLists.txt └── s ...

随机推荐

  1. 《刚刚问世》系列初窥篇-Java+Playwright自动化测试-1-环境准备与搭建

    1.简介 Python+Playwright系列的文章还没有结束,就有好的小伙伴或者童鞋们私信公众号留言,问宏哥什么时候出Java语言的Playwright的自动化测试文章.本来想趁热打铁将Pytho ...

  2. 可重入锁思想,设计MQ迁移方案

    如果你的MQ消息要从Kafka切换到RocketMQ且不停机,怎么做?在让这个MQ消息调用第三方发奖接口,但无幂等字段又怎么处理?今天小傅哥就给大家分享一个关于MQ消息在这样的场景中的处理手段. 这是 ...

  3. Salt安装部署

    Salt安装部署 一:salt简介 ​ 早期运维人员会根据自己的生产环境来写特定脚本完成大量重复性工作,这些脚本复杂且难以维护.系统管理员面临的问题主要是1.系统配置管理,2.远程执行命令,因此诞生了 ...

  4. Top cluster 树分块

    写点基础的东西.随便写的,勿喷. top cluster 一个 cluster 是一个联通子图,且至多有两个点与其他部分连接 这两个点被称为 boundary node 其余点被称为 internal ...

  5. podman+openresty+openssl,https双向认证demo测试

    前言 暂不讨论https原理,单论配置的话: 1. https单项认证 server: server.crt + server.key client: server_ca.crt 2. https双向 ...

  6. Python2 SyntaxError: Non-ASCII character '\xc3' in file...

    使用pip安装完需要的python库,运行脚本时报错:Syntax Error: Non-ASCII character '\xc3' in file /usr/local/lib/python2.7 ...

  7. UE5 射线检测排除隐藏的Actor

    0x00 Unreal Engine 5(UE5)以其卓越的性能和直观的开发工具在游戏开发领域占据了重要地位.本系列将深入探讨UE5中射线检测的关键概念,着重介绍处理隐藏Actor的技巧. 0x01. ...

  8. [oeasy]python0072_修改字体前景颜色_foreground_color_font

    修改颜色 回忆上次内容 m 可以改变字体样式 0-9 之间设置的都是字体效果 0 重置为默认 1 变亮 2 变暗 3 斜体 4 下划线 5 慢闪 6 快闪 7 前景背景互换 8 隐藏 9 中划线 叠加 ...

  9. [oeasy]python0021_python虚拟机的位置_可执行文件_转化为字节形态

    ​ 程序本质 回忆上次内容 ​\n​​ 就是换行 他对应着 ​​ascii​​ 字符的代码是(​​10​​)​​10进制​​ 他的英文是 LF,意思是​​Line Feed​​ 我们可以在<安徒 ...

  10. Android低功耗子系统的投票机制以及触发进入系统休眠的过程

    从kernel角度看,系统是否进入休眠应该由内核来控制,因此Linux引入了 wakeup source以及autosleep机制 关于wakeup source的介绍,请参考: Wakeup Sou ...