现代 CMake 模块化项目管理指南

news2024/11/19 17:27:18

文章目录

  • 一、基于CMake,对文件/目录组织规范
    • 1.推荐的目录组织方式
    • 2.划分子项目
    • 3.根项目的 CMakeLists.txt 配置
    • 4.子项目的 CMakeLists.txt 配置
    • 5.子项目的头文件
    • 6.子项目的源文件
    • 补充:GLOB 和 GLOB_RECRUSE 的区别
    • 7.头文件和源文件的一一对应关系
    • 8.只有头文件,没有源文件的情况
    • 9.每新增一个功能模块,需要创建两个文件
    • 10.一个模块依赖其他模块,则应导入他的头文件
    • 11.以项目名为名字空间(namsepace),避免符号冲突
    • 12.依赖另一个子项目,则需要链接他
    • 13.CMake 的 include 功能
    • 补充:macro 和 function 的区别

一、基于CMake,对文件/目录组织规范

1.推荐的目录组织方式

目录组织格式:

  • 项目名/include/项目名/模块名.h
  • 项目名/src/模块名.cpp

CMakeLists.txt 中写:

  • target_include_directories(项目名 PUBLIC include)

源码文件中写:

#include <项目名/模块名.h>
项目名::函数名();

头文件(项目名/include/项目名/模块名.h)中写:

#pragma once
namespace 项目名 {
void 函数名();
}

实现文件(项目名/src/模块名.cpp)中写:

#include <项目名/模块名.h>
namespace 项目名 {
void 函数名() { 函数实现 }
}

2.划分子项目

eg:

在这里插入图片描述

大型的项目,往往会划分为几个子项目。
即使你只有一个子项目,也建议你先创建一个子目录,方便以后追加新的子项目。
上图的案例中,我们在根目录下,创建了两个子项目 biology 和 pybmain,他们分别在各自的目录下有自己的 CMakeLists.txt。

3.根项目的 CMakeLists.txt 配置

在这里插入图片描述

cmake_minimum_required(VERSION 3.18)

if (NOT CMAKE_BUILD_TYPE)
    set(CMAKE_BUILD_TYPE Release)
endif()
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake;${CMAKE_MODULE_PATH}")

project(CppCMakeDemo LANGUAGES CXX)

include(MyUsefulFuncs)

add_subdirectory(pybmain)
add_subdirectory(biology)
  • 在根项目的 CMakeLists.txt 中,设置了默认的构建模式,设置了统一的 C++ 版本等各种选项。
  • 然后通过 project 命令初始化了根项目。
  • 随后通过 add_subdirectory 把两个子项目 pybmain 和 biology 添加进来(顺序无关紧要),这会调用 pybmain/CMakeLists.txt 和 biology/CMakeLists.txt。

4.子项目的 CMakeLists.txt 配置

在这里插入图片描述

file(GLOB_RECURSE srcs CONFIGURE_DEPENDS src/*.cpp include/*.h)
add_library(biology STATIC ${srcs})
target_include_directories(biology PUBLIC include)

  • 子项目的 CMakeLists.txt 就干净许多,只是创建了 biology 这个静态库对象,并通过 GLOB_RECRUSE 为他批量添加了所有位于 src 和 include 下源码和头文件。

  • 根项目的 CMakeLists.txt 负责处理全局有效的设定。而子项目的 CMakeLists.txt 则仅考虑该子项目自身的设定,比如他的头文件目录,要链接的库等等。

5.子项目的头文件

在这里插入图片描述
在这里插入图片描述

  • 这里我们给 biology 设置了头文件搜索路径 include。
  • 因为子项目的 CMakeLists.txt 里指定的路径都是相对路径,所以这里指定 include 实际上是:根/biology/include。
  • 注意我们用了 PUBLIC 修饰符,这是为了让链接 biology 的 pybmain 也能够共享 根/biology/include 这个头文件搜索路径。

6.子项目的源文件

在这里插入图片描述
在这里插入图片描述

  • 这里我们给 biology 批量添加了 src/*.cpp 下的全部源码文件。
  • 明明只有 .cpp 需要编译,为什么还添加了 include/.h?为了头文件也能被纳入 VS 的项目资源浏览器,方便编辑。(Linux则不需要添加)
  • 因为子项目的 CMakeLists.txt 里指定的路径都是相对路径,所以这里指定 src 实际上是:根/biology/src。

补充:GLOB 和 GLOB_RECRUSE 的区别

file (GLOB myvar CONFIGURE_DEPENDS src/*.cpp)
file (GLOB_RECURSE myvar CONFIGURE_DEPENDS src/*.cpp)
  • 疑问1:都是按照通配符批量匹配文件,有什么区别?
    GLOB: src/main.cpp(√) src/test/main.cpp(×)
    GLOB_RECURSE: src/main.cpp(√) src/test/main.cpp(√)
    区别在于 GLOB_RECURSE 允许 * 匹配嵌套的目录。

  • 疑问2:加了 CONFIGURE_DEPENDS 这个选项有什么区别?
    如果不加,在你创建新文件时,myvar 不会自动更新,还是旧的那几个文件,可能出现 undefined symbol,需要重新运行 cmake -B build 才能更新。
    加了,则每次 cmake --build 时自动检测目录是否更新,如果目录有新文件了,CMake 会自动帮你重新运行 cmake -B build 更新 myvar 变量。
    注:如果脚本每次都执行cmake -B build && cmake --build build则不需要关心

7.头文件和源文件的一一对应关系

在这里插入图片描述

  • 通常每个头文件都有一个对应的源文件,两个文件名字应当相同(方便我们理解,也方便 IDE 跳转),只有后缀名不一样。

  • 如果是一个类,则文件名应和类名相同,方便查找(Animal.cpp)。

  • 头文件中包含函数和类的声明,源文件则包含他们的实现。
    在这里插入图片描述

8.只有头文件,没有源文件的情况

在这里插入图片描述

  • 有时我们会直接把实现直接写在头文件里,这时可以没有与之对应的源文件,只有一个头文件。
  • 注意:在头文件里直接实现函数时,要加 static 或 inline 关键字

在这里插入图片描述

9.每新增一个功能模块,需要创建两个文件

在这里插入图片描述

  • 添加一个新功能模块 Carer 时,同时添加同名的源文件和头文件。
  • 头文件中的声明和源文件中的实现一一对应。

在这里插入图片描述

10.一个模块依赖其他模块,则应导入他的头文件

在这里插入图片描述

如果模块 Carer 的头文件 Carer.h 虽然引用了其他模块中的 Animal 类,但是他里面并没有解引用 Animal,只有源文件 Carer.cpp 解引用了 Animal。

那么这个头文件是不需要导入 Animal.h 的,只需要一个前置声明 struct Animal,只有实际调用了 Animal 成员函数的源文件需要导入 Animal.h。

  • 好处:加快编译速度,防止循环引用。

在这里插入图片描述

11.以项目名为名字空间(namsepace),避免符号冲突

在这里插入图片描述

在声明和定义外面都套一层名字空间,例如此处我的子项目名是 biology,那我就 biology::Animal。避免暴露全局的 Animal。

  • 这是因为万一有个“不拘一格”的第三方库也暴露个全局的 Animal,两个符号就会发生冲突,由于类符号都具有 weak 属性,链接器会随机选择一个覆盖掉,非常危险!

在这里插入图片描述

12.依赖另一个子项目,则需要链接他

在这里插入图片描述

  • 让 pybmain 链接上 biology:target_link_libraries(pybmain PUBLIC biology)
  • 由于 PUBLIC 属性具有传染性,根/biology/include 现在也加入 pybmain 的头文件搜索路径了,因此 pybmain 里可以 #include 到 biology 的头文件。
  • 同理如果又有一个 target_link_libraries(zxxpig PUBLIC pybmain) 那么 zxxpig 也有 pybmain 和 biology 的所有头文件搜索路径了。
    在这里插入图片描述

13.CMake 的 include 功能

在这里插入图片描述
和 C/C++ 的 #include 一样,CMake 也有一个 include 命令。
你写 include(XXX),则他会在 CMAKE_MODULE_PATH 这个列表中的所有路径下查找 XXX.cmake 这个文件。

  • 这样你可以在 XXX.cmake 里写一些你常用的函数,宏,变量等。

在这里插入图片描述

补充:macro 和 function 的区别

macro 相当于直接把代码粘贴过去,直接访问调用者的作用域。这里写的相对路径 include 和 src,是基于调用者所在路径。
function 则是会创建一个闭包,优先访问定义者的作用域。这里写的相对路径 include 和 src,则是基于定义者所在路径。

  • cmake-function
  • cmake-macro

include 相当于直接把代码粘贴过去,直接访问调用者的作用域。这里创建的变量和外面共享,直接 set(key val) 则调用者也有 ${key} 这个变量了。
function 中则是基于定义者所在路径,优先访问定义者的作用域。这里需要 set(key val PARENT_SCOPE) 才能修改到外面的变量。

参考:

  • parallel101/course

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

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

相关文章

揭秘神秘的JS混淆加密技术

在编程的世界里&#xff0c;沉香舞动着一种强大的力量&#xff0c;就像母亲为了救子不惜一切的决心。而在JavaScript的领域中&#xff0c;我们也有一种神秘的技术&#xff0c;它能够将代码变得晦涩难懂&#xff0c;宛如沉香救母一般&#xff0c;守护着程序的安全。今天&#xf…

Anaconda 安装并使用 PyTorch(PyCharm)

文章目录 Anaconda 安装并使用 PyTorch&#xff08;PyCharm&#xff09;1. Anaconda 安装1.1 下载安装包1.2 安装1.3 测试1.4 更改镜像源 2. PyTorch 安装2.1 创建虚拟环境2.3 激活/关闭环境2.4 CUDA2.5 conda 安装 PyTorch 3. PyCharm 使用3.1 安装 PyCharm3.2 登录3.3 使用虚…

Lookup-包含查找

lookup函数有个特性&#xff1a; LOOKUP(lookup_value, lookup_vector, [result_vector]) 如果 LOOKUP 函数找不到 lookup_value&#xff0c;则该函数会与 lookup_vector 中小于或等于 lookup_value 的最大值进行匹配。 这个特性&#xff0c;我这里简称&#xff1a;包含查找…

高丰度铈磁体

随着烧结钕铁硼应用领域的不断拓展和产量的快速增长&#xff0c;相应的稀土资源也被大量开采。稀土矿中各种稀土元素是共生的&#xff0c;但在钕铁硼的制备过程中&#xff0c;利用的主要是在轻稀土中质量分数为25%的镨Pr和钕Nd元素&#xff0c;这样对轻稀土中占比为质量分数49%…

档案馆档案管理的八防指的是哪些?

档案库房档案安全保护的“八防”&#xff1a;即防高温、防潮湿、防盗、防火、防霉菌、防光、防尘、防虫等要求。 “八防”实现了档案库房安全保护由被动人工管理向现代化、智能化、科学化、人性化管理的历史性跨越。该系统采用模块化设计&#xff0c;系统功能强大&#xff0c;…

夏天已至,放手一搏—V6.0.6版本发布

夏日莺啼&#xff0c;新品绽放。轻盈而来&#xff0c;清凉沁心。 香气四溢&#xff0c;舒缓暑气。一份清爽&#xff0c;满足您的期待。 预订新品&#xff0c;共享仲夏芬芳。 本次更新&#xff1a;经过一个月的细节打磨&#xff0c; V6.0.6版本发布&#xff0c;APP构建能力强…

Knowledge-Based Systems latex论文模板

Knowledge-Based Systems 杂志官网https://www.sciencedirect.com/journal/knowledge-based-systems Knowledge-Based Systems 期刊投稿网址 Editorial Manager LetPub 投稿经验和评论&#xff1a; KNOWLEDGE-BASED SYSTEMS 影响因子8.139分&#xff0c;是几区&#xff0c;20…

掌握RDD算子2

文章目录 扁平映射算子案例任务1、统计不规则二维列表元素个数方法一、利用Scala来实现方法二、利用Spark RDD来实现 按键归约算子案例任务1、在Spark Shell里计算学生总分任务2、在IDEA里计算学生总分第一种方式&#xff1a;读取二元组成绩列表第二种方式&#xff1a;读取四元…

控制系统典型应用车型 —— 潜入顶升式AMR

车型介绍: “潜入顶升AMR”是由驱动装置车身装置升降装置等结构组成的高性能移动机器人。通过复杂的智能技术来合理的路径规划&#xff0c;以适应环境并在其中导航&#xff0c;结合近距离激光雷达、碰撞传感器等技术&#xff0c;可以在高速运转的同时&#xff0c;潜伏至货物固…

【Python】布尔类型 ( 布尔类型变量 | 比较运算符 )

文章目录 一、布尔类型变量二、比较运算符三、代码示例 一、布尔类型变量 Python 中的 布尔类型 ( bool ) 用于 逻辑判断 , 布尔类型 是 数字类型 ( Number ) 的一种 , 其有两种 字面量 取值 : 真 : True , 其本质是数字 1 ;假 : False , 其本质是数字 0 ; 代码示例 : # 布尔…

电脑清灰记录(惠普暗影精灵5)

如果选择自己清灰&#xff0c;请确保自己处于精神平静&#xff0c;耐心可控&#xff0c;无粗暴动作倾向&#xff0c;无孩童打扰的状态。 新手全程大概需要2个半小时&#xff0c;老手比较顺利的话半个小时搞定。以下电脑&#xff0c;首次尝试。参考链接暗影精灵四笔记本电脑拆机…

AI绘画新秀-免费使用-Leonardo(Midjourney对手)注册教程

本教程收集于:AIGC从入门到精通教程 AI绘画新秀-免费使用-Leonardo(Midjourney对手) 保姆级注册教程 目录 一、写在前面的话。 二、纯文字教程 2.1 Leonardo注册教程:

一个Python的轻量级搜索工具--Whose

本文将简单介绍 Python 中的一个轻量级搜索工具Whoosh&#xff0c;并给出相应的使用示例代码。 # Whoosh 简介 Whoosh 由 Matt Chaput 创建&#xff0c;它一开始是一个为 Houdini 3D 动画软件包的在线文档提供简单、快速的搜索服务工具&#xff0c;之后便慢慢成为一个成熟的搜…

数字人的新革命,BAT的“冲高”战场

配图来自Canva可画 ChatGPT横空出世&#xff0c;让人们看到了数字人的另一种可能&#xff0c;将ChatGPT与虚拟数字人融合&#xff0c;研发出更加智能化、拟人化的虚拟数字人成为数字人厂商的新命题、新方向。 2月份&#xff0c;岭南股份、风语筑、开普云等10多家公司&#xf…

java设备台账管理系统myeclipse定制开发mysql数据库网页模式java编程jdbc

一、源码特点 java设备台账管理系统 是一套完善的web设计系统&#xff0c;对理解JSP java编程开发语言有帮助 mysql数据库&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。 java设备台账管理系统myeclipse定制开发mysql 二、功能介绍 此次系统…

3D控件Aspose.3D入门教程(11):通过简单的步骤生成条形码

Aspose.3D 是一个功能丰富的游戏软件和计算机辅助设计&#xff08;CAD&#xff09;的API&#xff0c;可以在不依赖任何3D建模和渲染软件的情况下操作文档。API支持Discreet3DS, WavefrontOBJ, FBX (ASCII, Binary), STL (ASCII, Binary), Universal3D, Collada, glTF, GLB, PLY…

JetsonNano学习(七)Nginx 搭建 HLS 直播服务器

文章目录 一、使用 Nginx-rtmp-module 编译 Nginx下载 Nginx-rtmp-module安装 Nginx 依赖下载 Nginx编译 Nginx 二、Nginx 配置文件三、启动 Nginx 服务方式一安装nginx初始化脚本、获取nginx初始化脚本 方式二直接调用 四、使用 RTMP 将视频推送到 Nginx安装FFmpeg捕获网络摄像…

行业分析——半导体行业

半导体行业是现代高科技产业和新兴战略产业&#xff0c;是现代信息技术、电子技术、通信技术、信息化等产业的基础之一。我国政府先后制定了《中国集成电路产业发展规划》和《中国人工智能发展规划》&#xff0c;明确提出要支持半导体和人工智能等产业的发展&#xff0c;为半导…

xs _webmsxyw 纯算法还原盗用代码请注明出处搬来搬去真的很下头!

本文以教学为基准、本文提供的可操作性不得用于任何商业用途和违法违规场景。 本人对任何原因在使用本人中提供的代码和策略时可能对用户自己或他人造成的任何形式的损失和伤害不承担责任。 最新版 x-s 没露任何版权请审核员认真对待谢谢。 【2023.05.22】 更新全站接口通用 …

【ARM位段地址分配】STM32 struct 位段内存分配位置问题

因为需要将 7位地址位 和 1位读写标志位 进行组合&#xff0c;想到了用 struct 和 union 的方法。 说明&#xff1a;作为自己测试用&#xff0c;使用硬件STM32F407ZET6 本篇文章仅对位段操作再ARM芯片上存储空间位置分配的探究&#xff0c;供给作为需要确定位段操作分配内存…