为了将我们的库文件更方便地提供给他人使用,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时间类型和格式化到微秒问题

    常规的问题此处略,因为网络上到处都是,这里主要讨论三个问题: 1.数据库的时间戳类型(含微秒)对应java的什么类型 java的常见时间类型比较多: java.util.Date java.sql.D ...

  2. 为什么Python的多线程是假的呢?

    https://www.zhihu.com/question/23474039/answer/269526476

  3. WAV音频文件按秒切片段

    wav音频文件按秒切片段 import wave def split_wav_by_seconds(input_file, output_file, start_second, end_second) ...

  4. USB OTG有关协议

    想了解USB OTG的工作原理,需要知道三个协议: ADP:Attach Detection Protocol HNP:Host Negotiation Protocol SRP:Session Re ...

  5. 什么是Selenium Grid?如何搭建Selenium Grid?

    标签(空格分隔): 测试架构 什么是测试基础架构? 测试基础架构指的是,执行测试的过程中用到的所有基础硬件设施以及相关的软件设施.因此,我们也把测试基础架构称之为广义的测试执行环境.通常来讲,测试基础 ...

  6. Node.js中的模块

    CommonJS模块 CommonJS是一种规范,它定义了JavaScript 在服务端运行所必备的基础能力,比如:模块化.IO.进程管理等.其中,模块化方案影响深远,其对模块的定义如下: 1,模块引 ...

  7. 使用docker搭建ELK分式日志同步方案

    ELK作为业界最常用日志同步方案,我们今天尝试一下使用docker快速搭建一套ELK方案.ELK使用国内加速源拉取的镜像比较旧,有条件的朋友可以拉取官网的源.elasticsearch作为日志储存库( ...

  8. 2024 年 Visual Studio 实用插件集合

    前言 在软件开发领域,选择正确的工具可以极大地提升开发效率和质量. Visual Studio作为微软推出的强大集成开发环境(IDE),通过安装合适的插件,可以进一步增强其功能,满足开发者多样化的需求 ...

  9. 4. 系统I/O

    系统 I/O 示例代码: #include <iostream> // 标准库头文件 // #include "myheader.h" // 自己写的头文件 void ...

  10. UE 实现鼠标点选模型

    楔子 在孪生的场景中,点击三维对象是常用的操作.比如点击模型显示相关属性和图片,点击摄像头模型播放视频,点击楼宇展开楼层等等. 因此点选模型是属于数字孪生最必要的基础能力. 准备知识 UE蓝图介绍 本 ...