CMake笔记之PROJECT_SOURCE_DIR、CMAKE_SOURCE_DIR、CMAKE_CURRENT_BINARY_DIR对比

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.mfbz.cn/a/470455.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

深度解析 JavaScript 的 structuredClone() 方法

您是否知道,现在 JavaScript 中有一种原生的方式可以深拷贝对象? 没错,这个内置于 JavaScript 运行时的structuredClone函数就是这样: const calendarEvent {title: "Builder.io大会",date: new Date(123),attendees…

(一)Linux+Windows下安装ffmpeg

一丶前言 FFmpeg是一个开源的音视频处理工具集,由多个命令行工具组成。它可以在跨平台的环境中处理、转换、编辑和流媒体处理音视频文件。 FFmpeg支持多种常见的音视频格式和编解码器,可以对音视频文件进行编码、解码、转码、剪辑、合并等操作。它具有广…

python3入门机器学习,知识点全面总结与代码实操示例

目录 写在前面的话 一、机器学习的基本任务与方法分类 机器学习的概念和定义 基本任务 二分类任务(Binary Classification): 多分类任务(Multi-class Classification): 多标签分类任务(Mu…

SpringAOP(控制反转)【看这一片文章就够了】

目录 一、SpringAOP 1.概述 1 什么是AOP 2 AOP的作用 3 AOP的底层 4 AOP相关概念 5 AOP开发前要明确的事情 2. AOP入门 小结: 3. AOP详解-通知类型 1 通知类型 2 通知方法里获取目标方法信息(备用) 3 小结 4. AOP详解-切入点表达式 1 execution 2 an…

opencv 傅里叶变换(低通滤波 + 高通滤波)

文章目录 1、傅里叶变换2、通过numpy实现3、高通滤波器5、通过opencv实现傅里叶变换6、低通滤波器 1、傅里叶变换 时域分析:以时间作为参照物,世间万物都是随着时间变化而变化,并且不会停止 频域分析:认为世间万物都是静止的&…

将html网页展示的图表,下载到PPT文档内,以图片的形式展示在PPT内

使用到的工具有: 开发工具:IDEA 报表开发工具:帆软10.0.19 1、针对帆软报表[普通报表]的设置 1.1首先选中在帆软里制作好的报表,选择模板web属性 1.2.选择数据分析模式,添加一个事件设置,该事件应该设置“…

使用甘特图实现高效时间规划

甘特图虽然看似简单,却蕴含着规划时间的奥秘。它将复杂的工序分解成逻辑严密的任务链条,每个短小的条形图块都清晰地道出一个任务的起始、持续和终止。就像指挥家挥舞手中的棒,每个动作都精确拍着节奏,确保各个乐手分工合作、行云流水。择一个好用的甘特图制作工具,会让你事半功…

HCIP作业

实验要求: 1、R6为ISP,接口IP地址均为公有地址,该设备只能配置IP地址,之后不能再对其进行任何配置; 2、R1-R5为局域网,私有IP地址192.168.1.0/24,请合理分配; 3、R1、R2、R4&#x…

空间解析几何之直线与平面:推导直线与直线、直线与平面交点

空间解析几何——直线与平面 三维空间中的直线和平面与二维空间中的性质有一定的类似之处,但是其相交关系的求解方式有所差异。本文回顾了三维空间中直线和平面的解析表达,然后推导线-线、线-面交点。 平面 空间平面的表达式为: A x B y…

React状态管理库快速上手-Redux(一)

基本使用 安装 pnpm install reduxjs/toolkit react-redux创建一个仓库 定义state createSlice相当于创建了一个模块仓库,initialState存放状态,reducers存放改变状态的方法。 import { createSlice } from reduxjs/toolkitexport const counterSli…

MATLAB环境下基于改进最大相关峭度解卷积的滚动轴承故障诊断

相关峭度解卷积MCKD是一种新的解卷积方法,其设计了一个新的目标函数—相关峭度,并以此为优化目标设计一系列的FIR滤波器,为实现最好的效果,需要从中找到最优滤波器并最终实现对信号中噪声的抑制和对信号中冲击成分的突出的目的。M…

产品推荐 | 基于XC7K325T的FMC接口万兆光纤网络验证平台

01、产品概述 TES307是一款基于XC7K325T FPGA的万兆光纤网络验证平台,板卡具有1个FMC(HPC)接口,4路SFP万兆光纤接口、4路SATA接口、1路USB3.0接口。 板载高性能的FPGA处理器可以实现光纤协议、SATA总线控制器、以及USB3.0高速串…

长安链Docker Java智能合约引擎的架构、应用与规划

#功能发布 长安链3.0正式版发布了多个重点功能,包括共识算法切换、支持java智能合约引擎、支持后量子密码、web3生态兼容等。我们接下来为大家详细介绍新功能的设计、应用与规划。 在《2022年度长安链开源社区开发者调研报告》中,对Java合约语言支持是开…

华为配置HTTPS服务器实验

配置HTTPS服务器示例 组网图形 图1 配置HTTPS服务器组网图 组网需求配置思路配置注意事项操作步骤配置文件 组网需求 如图1所示,用户通过Web方式访问网关设备AP。 为了防止传输的数据不被窃听和篡改,实现对设备的安全管理,网络管理员要…

Makefile编译make complie时报错的心路历程

本次报错是在Makefile文件里面找错 Makefile文件找错的方法很复杂,必须要有一双慧眼,一层一层剥离分析 第一个错误(还有一个错在全志 76节 23:35的时候连接wiringPi库) 第二个错误: undefined reference…

Java:类和对象

目录 1.面对对象的初步认识1.1 什么是面向对象?(Java当中一切皆为对象)1.2 面对对象与面对过程 2.类的定义和使用2.1简单认识类2.2 类的定义格式 3.类的实例化3.1 什么是实例化3.2类和对象的说明 4.this引用4.1为什么要使用this引用4.2 什么是…

docker小白第十四天之Portainer与CIG

Portainer简介 Portainer是一款轻量级的应用,它提供了图形化界面,用于方便地管理Docker环境,包括单机环境和集群环境。 Portainer命令安装 # 一个容器可以同时起多个-p端口,restartalways表示随时在线,重启机器后也…

O2OA红头文件流转与O2OA版式公文编辑器基本使用

O2OA开发平台在流程管理中,提供了符合国家党政机关公文格式标准(GB/T 9704—2012)的公文编辑组件,可以让用户在包含公文管理的项目实施过程中,轻松地实现标准化公文格式的在线编辑、痕迹保留、手写签批等功能。并且可以…

[uni-app] uni.createAnimation动画在APP端无效问题记录

文章目录 uni.createAnimation动画描述动画代码templatejs部分 问题原因改进方案template js部分改动git 改进截图 uni.createAnimation 动画描述 实现一个以左上角为锚点,以Z轴做平面抬起及落下的动画效果 动画代码 template <image v-if"showHot(item.cname)&quo…

锂电极片生产中机器视觉系统的多元检测能力

随着新能源行业的快速发展&#xff0c;锂电池作为核心组件&#xff0c;其生产质量受到了前所未有的关注。在锂电极片的生产过程中&#xff0c;机器视觉系统以其高精度、高效率的特点&#xff0c;成为了保障产品质量的关键工具。本文将探讨机器视觉系统在锂电极片生产中可以检测…
最新文章