CMake笔记之PROJECT_SOURCE_DIR、CMAKE_SOURCE_DIR、CMAKE_CURRENT_BINARY_DIR对比

news2025/1/15 14:40:14

CMake笔记之PROJECT_SOURCE_DIR、CMAKE_SOURCE_DIR、CMAKE_CURRENT_BINARY_DIR对比

—— 杭州 2024-03-19 夜

在这里插入图片描述

code review!

文章目录

  • CMake笔记之PROJECT_SOURCE_DIR、CMAKE_SOURCE_DIR、CMAKE_CURRENT_BINARY_DIR对比
    • 1.三者区别
    • 2.具体示例说明
    • 3.CMAKE_SOURCE_DIR 和 PROJECT_SOURCE_DIR的区别

1.三者区别

下面是一个表格,简要总结了 CMAKE_CURRENT_BINARY_DIRCMAKE_SOURCE_DIRPROJECT_SOURCE_DIR 的区别:

变量描述
CMAKE_CURRENT_BINARY_DIR指向当前处理的 CMakeLists.txt 文件对应的构建目录。对于多级目录结构的项目,每个目录的这个变量指向的都是它自己的构建目录。
CMAKE_SOURCE_DIR指向最顶层 CMakeLists.txt 文件的源码目录,即整个项目的根源码目录。在所有的 CMakeLists.txt 文件中保持不变,无论它们在源码树的何处。
PROJECT_SOURCE_DIR指向最近通过 project() 命令定义的项目的根源码目录。如果是单个项目,则与 CMAKE_SOURCE_DIR 相同。在使用 add_subdirectory 命令嵌套项目时,对于每个子项目来说,它指向的是各自的根源码目录。

这些变量在不同的 CMakeLists.txt 文件中的行为会有所不同,特别是在含有多个子项目的情况下。例如,在一个包含子项目的构建系统中:

root_project/           # 根项目目录
|- CMakeLists.txt       # 根项目 CMakeLists.txt, 包含 project(RootProject)
|- sub_project/         # 子项目目录
   |- CMakeLists.txt    # 子项目 CMakeLists.txt, 包含 project(SubProject)

假设我们在 root_project/build 目录中执行构建命令,每个 CMakeLists.txt 文件中变量的值将如下:

文件CMAKE_CURRENT_BINARY_DIRCMAKE_SOURCE_DIRPROJECT_SOURCE_DIR
root_project/CMakeLists.txtroot_project/buildroot_projectroot_project
sub_project/CMakeLists.txtroot_project/build/sub_projectroot_projectsub_project

在这个例子中,CMAKE_SOURCE_DIR 在所有的 CMakeLists.txt 文件中都是相同的,因为它指向最顶层 CMakeLists.txt 文件的目录。而 PROJECT_SOURCE_DIR 在子项目的 CMakeLists.txt 中指向的是子项目的源码目录,因为 project() 命令在那里被调用。而 CMAKE_CURRENT_BINARY_DIR 则对应于每个 CMakeLists.txt 文件的当前构建目录。

2.具体示例说明

让我们假设你有一个项目的文件组织结构如下所示:

/my_project
|-- CMakeLists.txt
|-- src
|   |-- CMakeLists.txt
|   |-- main.cpp
|-- lib
    |-- utils
        |-- CMakeLists.txt
        |-- util.cpp

在这个结构中:

  • /my_project 是项目的根目录。
  • /my_project/src 包含项目的主要源文件。
  • /my_project/lib/utils 包含项目的一些实用工具函数。

现在,我们将看看如何在不同的 CMakeLists.txt 文件中使用这些变量:

  1. /my_project/CMakeLists.txt (顶层 CMakeLists.txt):
cmake_minimum_required(VERSION 3.0)
project(MyProject)

add_subdirectory(src)
add_subdirectory(lib/utils)

# CMAKE_SOURCE_DIR 在这里指向 /my_project
# PROJECT_SOURCE_DIR 在这里指向 /my_project
# CMAKE_CURRENT_BINARY_DIR 在这里指向 /my_project/build (假设在 /my_project/build 目录中运行 cmake ..)
  1. /my_project/src/CMakeLists.txt:
# 这个文件是 src 目录的 CMakeLists.txt

# CMAKE_SOURCE_DIR 这里仍然指向 /my_project
# PROJECT_SOURCE_DIR 这里仍然指向 /my_project
# CMAKE_CURRENT_BINARY_DIR 在这里指向 /my_project/build/src
# (假设在 /my_project/build 目录中运行 cmake ..)
  1. /my_project/lib/utils/CMakeLists.txt:
# 这个文件是 lib/utils 目录的 CMakeLists.txt

# CMAKE_SOURCE_DIR 这里仍然指向 /my_project
# PROJECT_SOURCE_DIR 这里仍然指向 /my_project
# CMAKE_CURRENT_BINARY_DIR 在这里指向 /my_project/build/lib/utils
# (假设在 /my_project/build 目录中运行 cmake ..)

如果你在 /my_project/build 目录中运行 cmake .. 命令来构建你的项目,CMake 会创建相应的构建文件在该 build 目录中。在这种情况下:

  • CMAKE_CURRENT_BINARY_DIR 对于每个 CMakeLists.txt 文件,都指向其对应的在构建目录树中的位置,而不是源码目录树。
  • CMAKE_SOURCE_DIRPROJECT_SOURCE_DIR 在所有的 CMakeLists.txt 文件中始终指向项目的顶层源码目录 /my_project

这样,无论你在项目的哪个子目录中工作,你都可以使用这些变量来引用项目中的其他文件或目录,而不必担心相对路径的问题。

3.CMAKE_SOURCE_DIR 和 PROJECT_SOURCE_DIR的区别

在 CMake 中,CMAKE_SOURCE_DIRPROJECT_SOURCE_DIR 确实有细微的区别,尤其是在涉及多项目(例如,使用add_subdirectory,或者在超级构建中)的情况下。这里是它们的具体区别:

  • CMAKE_SOURCE_DIR 指向最顶层 CMakeLists.txt 文件的目录,这个目录是整个构建树的根源码目录。不管你在哪个子目录中调用 CMAKE_SOURCE_DIR,它始终指向顶层 CMakeLists.txt 所在的目录。在单项目构建中,CMAKE_SOURCE_DIRPROJECT_SOURCE_DIR 是相同的。

  • PROJECT_SOURCE_DIR 指向最近一次调用 project() 命令的目录。如果你在一个子目录中有另一个 project() 命令(表示该子目录是一个独立的项目),那么在该子目录及其下级目录中,PROJECT_SOURCE_DIR 会指向这个子项目的根源码目录,而不是整个构建树的根源码目录。

这里是一个例子来说明这一点:

假设你有以下目录结构:

/my_super_project
|-- CMakeLists.txt         # contains 'project(SuperProject)'
|-- subproject_a
|   |-- CMakeLists.txt     # contains 'project(ProjectA)'
|-- subproject_b
    |-- CMakeLists.txt     # does not contain 'project()' command

这里是每个目录中这些变量的值:

  • /my_super_project/CMakeLists.txt 中:

    • CMAKE_SOURCE_DIR = /my_super_project
    • PROJECT_SOURCE_DIR = /my_super_project
  • /my_super_project/subproject_a/CMakeLists.txt 中:

    • CMAKE_SOURCE_DIR = /my_super_project
    • PROJECT_SOURCE_DIR = /my_super_project/subproject_a
  • /my_super_project/subproject_b/CMakeLists.txt 中(没有 project() 命令):

    • CMAKE_SOURCE_DIR = /my_super_project
    • PROJECT_SOURCE_DIR = /my_super_project (因为 subproject_b 没有自己的 project() 命令,所以它继承了顶层项目的 PROJECT_SOURCE_DIR)

正因为这样的行为,PROJECT_SOURCE_DIR 在处理复杂项目结构时非常有用,尤其是当你需要引用当前项目的根源码目录时。这样,即使在多个子项目的设置中,每个子项目也可以有自己的根源码目录。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1530780.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

[C语言]一维数组二维数组的大小

对于一维数组我们知道取地址是取首元素的地址,二维数组呢,地址是取第一行的地址,sizeof(数组名)这里计算的就是整个数组的大小,&数组名 表示整个数组,取出的是整个数组的地址,显示的是数组的首元素 记…

sqlite3安装

下载地址:SQLite Download Page windows下载下面两个选项 解压缩后将两个解压缩文件的内容放在一个文件夹下: 将该文件夹的路径添加到系统路径 在cmd下输入sqlite3显示以下内容说明安装成功 安装可视化工具:SQLiteStudio 安装完成后打开如…

软件推动开放自动化落地

当你唯一拥有的是一把锤子时,你周围的一切都是钉子。 软件是硬件设备的护城河,国际自动化厂商不遗余力地开发各种新型工业软件,其战略站在应用的制高点。以前我们追求硬件兼容,现在我们要致力于应用引领。如果我们拥有强大的SCADA…

C语言经典算法-7

文章目录 其他经典例题跳转链接36.排序法 - 改良的选择排序37.快速排序法(一)38.快速排序法(二)39.快速排序法(三)40.合并排序法 其他经典例题跳转链接 C语言经典算法-1 1.汉若塔 2. 费式数列 3. 巴斯卡三…

32串口学习

基于之前的GPIO等工程,后面的上手难度就简单多了,主要是相关寄存器的设置。 void USART1_Config(void) {GPIO_InitTypeDef GPIO_InitStructure;USART_InitTypeDef USART_InitStructure;/* config USART1 clock */RCC_APB2PeriphClockCmd(RCC_APB2Periph…

好物分享:FPGA实现SDI视频编解码的方案设计汇总

目录 1、前言2、专用芯片方案2.1、GS2971FPGA的图像采集 设计方案2.2、GS2971FPGA的图像采集图像缩放 设计方案2.3、GS2971FPGA的图像采集纯verilog图像缩放纯verilog视频拼接 设计方案2.4、GS2971FPGA的图像采集HLS图像缩放Video Mixer视频拼接 设计方案2.5、GS2971FPGA的图像…

python爬虫之xpath入门

文章目录 一、前言参考文档: 二、xpath语法-基础语法常用路径表达式举例说明 三、xpath语法-谓语表达式举例注意 四、xpath语法-通配符语法实例 五、选取多个路径实例 六、Xpath Helper安装使用说明例子: 七、python中 xpath 的使用安装xpath 的依赖包xm…

基于VMware虚拟机安装MacOS BigSur系统

这周用VMWare搞了个MacOS虚拟机,也算是完成初中高中时候的梦想了吧~~(那时候我的电脑配置还很拉跨,带不动虚拟机)~~ 写一篇博客记录一下,当然这也是yonagi04.github.io建站的第一篇新博客 准备工作(VMWare…

【Linux更新驱动、cuda和cuda toolkit】

目录 1. 更新显卡驱动1.1. 查看当前显卡驱动版本1.2. 删除原始显卡驱动1.3. 删除CUDA Toolkit1.4. 在NVIDIA官网找到2080Ti对应的最新驱动程序 2. 更新CUDA Toolkit2.1. 下载CUDA Toolkit2.2. 安装.run2.3. 添加环境变量2.4. 检查是否安装好了 最近需要更新服务器的显卡驱动和C…

yolov7 gui 轻松通过GUI来实现车辆行人计数

YOLOv7 GUI 是一款用户友好型图形界面应用程序,专为简化基于YOLOv7(You Only Look Once version 7)的目标检测流程而设计。该工具允许用户无需深入掌握命令行操作和复杂编程细节,即可方便快捷地运行YOLOv7模型来检测图像或视频中的…

精简版 Obsidian 图床配置 PicGo+ gitee

精简版 Obsidian 图床配置 PicGo gitee 图床的作用 图床(Image Hosting Service)是一种在线服务,用于存储和托管用户上传的图片文件。用户可以将图片上传到图床服务器,并获得一个可访问的图片链接,然后可以在网页、博…

NVIDIA最新 Blackwell架构简介

NVIDIA Blackwell架构简介 在AI和大型语言模型(LLMs)迅速发展的领域中,追求实时性能和可扩展性至关重要。从医疗保健到汽车行业,组织正深入探索生成性AI和加速计算解决方案的领域。对生成性AI解决方案的需求激增,促使企…

安防监控视频汇聚平台EasyCVR接入海康Ehome设备,设备在线但视频无法播放是什么原因?

安防视频监控/视频集中存储/云存储/磁盘阵列EasyCVR平台可拓展性强、视频能力灵活、部署轻快,可支持的主流标准协议有国标GB28181、RTSP/Onvif、RTMP等,以及支持厂家私有协议与SDK接入,包括海康Ehome、海大宇等设备的SDK等。平台既具备传统安…

视频监控平台问题-通过url免密直接浏览实时视频出错的问题解决

目 录 一、通过url免密浏览实时监控视频介绍 二、浏览出错现象描述 1、问题提出 2、问题描述 (1)现象 (2)前端调试 (3)后端日志 三、问题解决 1、问题分析 2,查找资源&#…

【MQTT】Vue中使用mqtt

MQTT(Message Queuing Telemetry Transport)作为一种轻量级、开放、灵活、简单、易于实现的通信协议。它基于发布/订阅(Publish/Subscribe)模式的消息传输协议,在上位机和硬件设备间通信时经常用到。虽然在嵌入式软件一…

1、Java虚拟机学习-类的生命周期-加载阶段-以及怎样查看方法区中的对象和堆中对象的关联以及静态变量存在什么地方

类的生命周期 其中连接又可以分为3个小阶段 一、加载阶段 1、加载阶段第一步是类加载器根据类的全限定名通过不同的渠道以二进制流的方式获取字节码信息。 渠道: 2、类加载器在加载完类之后,Java虚拟机会将字节码中的信息保存在内存的方法区中。 方法区是虚拟…

AI - 机器学习GBDT算法

目录 GBDT 提升树 梯度提升树 GBDT算法实战案例 XGBoost 😆😆😆感谢大家的观看😆😆 GBDT 梯度提升决策树(Gradient Boosting Decision Tree),是一种集成学习的算法&…

基于springboot+vue的餐饮管理系统

博主主页:猫头鹰源码 博主简介:Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战,欢迎高校老师\讲师\同行交流合作 ​主要内容:毕业设计(Javaweb项目|小程序|Pyt…

GAMES101 学习3

Lecture 13 ~ 16 Shadow mapping 一种图像空间算法生成阴影时不需要知道场景中的几何信息会产生走样现象 最重要的思想:如果有的点不在阴影里你又能看到这个点,那么说明摄像机可以看到这个点,光源也可以看到这个点 经典的Shadow mapping …

提升合规性!Zoho如何优化CRM产品合规性?

在企业数字化和信息化高速发展的今天,CRM管理系统成为越来越多企业的选择。然而,不是所有CRM供应商都有合规意识。合规性不应当只是一项法律规定,更是保证CRM供应商持续发展、赢得客户信赖以及应付监管压力的关键支撑。Zoho对企业合规性的重视…