多层次目录结构的CMake工程管理

news2024/9/21 10:40:59

多层次目录结构的CMake工程管理

  • 一、多层次目录结构的文件结构
  • 二、如何利用CMake组织多层次目录结构
  • 三、构建工程

一、多层次目录结构的文件结构

我们编写程序,不可能把所有源文件都一股脑地放在顶层目录下,必然会有一个目录结构,每个目录中只放置自己相关的一些文件,甚至多层嵌套也是很常见的。

比如以下名为gtestdemo的工程目录结构, 便可以说明问题。

[hubing@192 gtestdemo]$ tree
.
├── CMakeLists.txt
├── doc
│   └── README.md
└── src
    ├── CMakeLists.txt
    ├── main.cpp
    └── utils
        ├── CMakeLists.txt
        ├── MathUtils.cpp
        ├── MathUtils.hpp
        └── ut
            └── testMathUtils.cpp

顶级工程目录下,有一个顶级的CMakeLists.txt, 外加两个子目录doc和src,doc子目录放置文档相关的文件,src子目录放置源代码。
src子目录下还有下一级目录utils,里面有若干源代码文件。

20230102211228

二、如何利用CMake组织多层次目录结构

utils 相关代码:

MathUtils.hpp

namespace utils::math
{

// Returns n! (the factorial of n).  For negative n, n! is defined to be 1.
int Factorial(int n);

// Returns true if n is a prime number.
bool IsPrime(int n);

}

MathUtils.cpp

#include "MathUtils.hpp"

namespace utils::math
{

// Returns n! (the factorial of n).  For negative n, n! is defined to be 1.
int Factorial(int n) {
    int result = 1;
    for (int i = 1; i <= n; i++) {
        result *= i;
    }
 
    return result;
}

bool IsPrime(int n) {
    // Trivial case 1: small numbers
    if (n <= 1) return false;
 
    // Trivial case 2: even numbers
    if (n % 2 == 0) return n == 2;
 
    // Now, we have that n is odd and n >= 3.
    // Try to divide n by every odd number i, starting from 3
    for (int i = 3; ; i += 2) {
        // We only have to try i up to the squre root of n
        if (i > n / i) break;
 
        // Now, we have i <= n/i < n.
        // If n is divisible by i, n is not prime.
        if (n % i == 0) return false;
    }
    // n has no integer factor in the range (1, n), and thus is prime.
    return true;
}

}

我们来看src/utils/CMakeLists.txt如何编写:

add_library(utils MathUtils.cpp)

只有一行,利用 add_library 创建一个名为utils的target库,使用的源文件是MathUtils.cpp。

为了使用这个utils库,我们需要在上一层的CMakeLists.txt(也就是src/CMakeLists.txt)中加上一行

add_subdirectory(utils)

这样一来utils库就可以被编译。

下一步为了能够链接到utils库,我们还需要使用target_link_libraries指令

add_executable(gtestdemo main.cpp)
target_link_libraries(gtestdemo PUBLIC utils)

最后,为了在main.cpp中能够使用utils库,我们在main.cpp中会写上

#include "MathUtils.hpp"

那么如何才能找到这个头文件呢?此时需要使用 target_include_directories 指令:

target_include_directories(gtestdemo PUBLIC "${PROJECT_BINARY_DIR}" "${PROJECT_SOURCE_DIR}/src/utils")

完整的 src/CMakeLists.txt 内容如下:

add_subdirectory(utils)

add_executable(gtestdemo main.cpp)

target_link_libraries(gtestdemo PUBLIC utils)

message(STATUS "this is BINARY dir " ${PROJECT_BINARY_DIR})
message(STATUS "this is SOURCE dir " ${PROJECT_SOURCE_DIR})
target_include_directories(gtestdemo PUBLIC "${PROJECT_BINARY_DIR}" "${PROJECT_SOURCE_DIR}/src/utils")

main.cpp 内容如下:

#include <iostream>
#include "MathUtils.hpp"

int main(int, char**) {
    std::cout << "Hello, world!"<< std::endl;
    std::cout << "4! = " << utils::math::Factorial(4) << std::endl;
    std::cout << "check whether 10 is a prime number: " << utils::math::IsPrime(10) << std::endl;
    std::cout << "check whether 11 is a prime number: " << utils::math::IsPrime(11) << std::endl;
}

最后到了最顶层的CMakeLists.txt,内容如下:

cmake_minimum_required(VERSION 3.0.0)
project(gtestdemo VERSION 0.1.0)

set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)

add_subdirectory(src bin)

现在对其进行说明:

  • cmake_minimum_required(VERSION 3.0.0)
    任何工程的最顶级CMakeLists.txt,必须起始于这个cmake_minimum_required指令,用于明确CMake的最低版本号

  • project(gtestdemo VERSION 0.1.0)
    project指令设定了当前工程的名字叫 gtestdemo,版本号是 0.1.0

  • set(CMAKE_CXX_STANDARD 11)

  • set(CMAKE_CXX_STANDARD_REQUIRED True)
    这两个指令用于指示C++标准号,例如当前指定的是C++ 11标准

  • add_subdirectory(src bin)
    将子目录src添加进工程并编译,同时指定二进制目标文件的输出路径为bin目录。如果不指定bin目录,那么编译结果都将存放在build/src目录下(这个src和源码中的src目录对应)。

最后,本例中有个src/utils/ut/testMathUtils.cpp, 这个文件是用作ut demo的,此处暂未涉及。

三、构建工程

照例在工程的顶级目录中先建立一个build子目录,然后进行构建。

mkdir build
cd build
cmake ..
make

执行效果如下:
20230102214822

有了这个示例之后,对于更多层次的目录结构,便可以依葫芦画瓢,使用CMake进行管理了。

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

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

相关文章

【django】项目开发准备之数据库配置

文章目录一、docker中启动mariadb服务二、django配置文件中进行配置1.安装mysqlclient2.找到settings.py文件3.启动django程序一、docker中启动mariadb服务 --restartalways:自动启动容器 --name mydb&#xff1a;容器名称 -d&#xff1a;后台运行容器 -v /home/ubuntu/ck14/ma…

php宝塔搭建部署实战服务类家政钟点工保姆网站源码

大家好啊&#xff0c;我是测评君&#xff0c;欢迎来到web测评。 本期给大家带来一套php开发的服务类家政钟点工保姆网站源码&#xff0c;感兴趣的朋友可以自行下载学习。 技术架构 PHP7.2 nginx mysql5.7 JS CSS HTMLcnetos7以上 宝塔面板 文字搭建教程 下载源码&…

单机模拟搭建 Zookeeper 集群

1. 准备 官网下载&#xff1a;https://www.apache.org/dyn/closer.lua/zookeeper/zookeeper-3.6.3/apache-zookeeper-3.6.3-bin.tar.gz 注意&#xff1a; zookeeper 从 3.5 版本以后&#xff0c;命名就发生了改变apache-zookeeper-X.X.X.tar.gz 这样命名的&#xff0c;都是未…

并发编程之JMMvolatile详解

目录 什么是JMM模型 定义 JMM不同于JVM内存区域模型 主内存 工作内存 Java内存模型与硬件内存架构的关系 JMM存在的必要性 数据同步八大原子操作 同步规则分析 并发编程的可见性&#xff0c;原子性与有序性问题 原子性 可见性 有序性 JMM如何解决原子性&…

【单片机】AT24C02存储器(I²C总线)/DS18B20温度传感器(单总线)

目录 一、AT24C02存储器 1、AT24C02存储器介绍 2、存储器简化模型 3、AT24C02存储器原理图 二、IC总线 1、IC总线的介绍 2、IC电路 3、IC时序图 3.1IC开始和结束时序图 3.2IC主机发送和接收时序图 3.3IC主机发送应答/接收应答 4、IC数据帧发送/接收方式 4.1主机向…

数据可视化系列-02各类图表的综合使用介绍及实践-上篇

文章目录3.各类图表的综合使用介绍及实践3.1了解数据功能图1、可视化中的数据2、基于数据的研究3、数据的可视化组件4、可视化图表的作用、制作流程和类型3.2北极星指标展示1、指标类知识回顾&#xff1a;指标类简介、指标类主要场景2、指标类图表&#xff1a;指标看板、指标趋…

C++关联容器(复习题篇)

本篇博客将介绍标准库关联容器&#xff0c;包括&#xff1a; 关联容器的概念和简单的使用关联容器涉及的类型和操作&#xff0c;特别是与顺序容器的差异无序关联容器&#xff0c;特别是与有序关联容器的差异 练习1.1 描述map和vector的不同 vector是顺序容器其中的元素是“顺序…

分布式事务的介绍

本地事务 单服务进程&#xff0c;单数据库资源,同一个连接conn多个事务操作 在JDBC编程中&#xff0c;我们通过java.sql.Connection对象来开启、关闭或者提交事务。代码如下所示&#xff1a; Connection conn ... //获取数据库连接 conn.setAutoCommit(false); //开启事务 t…

educoder数据结构与算法 栈 第2关:实现一个链接存储的栈

本文已收录于专栏 &#x1f332;《educoder数据结构与算法_大耳朵宋宋的博客-CSDN博客》&#x1f332; 目录 任务描述 相关知识 编程要求 测试说明 AC_Code 任务描述 本关任务是实现 step2/LnkStack.cpp 中的LS_IsEmpty、LS_Length、LS_Push、LS_Pop和LS_Top五个操作函数…

π122E30兼容Si8622BC-B-IS 双通道数字隔离器

π122E30兼容Si8622BC-B-IS 双通道数字隔离器 &#xff0c;具有出色的性能特征和可靠性&#xff0c;整体性能优于光耦和基于其他原理的数字隔离器产品。 产品传输通道间彼此独立&#xff0c;可实现多种传输方向的配置&#xff0c;可实现 3.0kVrms 隔离耐压等级和 DC 到 200Mbp…

Day 17-Vue3 技术_其它

1.全局API的转移 Vue 2.x 有许多全局 API 和配置。例如&#xff1a;注册全局组件、注册全局指令等。 //注册全局组件 Vue.component(MyButton, {data: () > ({count: 0}),template: <button click"count">Clicked {{ count }} times.</button> })//注…

acwing-1015 摘花生

项目场景&#xff1a; 线性dp 题源 数字三角形 问题描述 Hello Kitty想摘点花生送给她喜欢的米老鼠。 她来到一片有网格状道路的矩形花生地(如下图)&#xff0c;从西北角进去&#xff0c;东南角出来。 地里每个道路的交叉点上都有种着一株花生苗&#xff0c;上面有若干颗花…

用Typora,PicGo和OSS实现自动上传图片

前言&#xff1a; 以前写博客要发布到好些个平台&#xff0c;我是将图片一张张上传到每个平台&#xff0c;后来发现是真的麻烦&#xff0c;上传图片花的时间太多&#xff0c;极大的降低了我写文章的积极性。 后来改进为使用oss&#xff0c;把博客的图片都上传到oss上面。然后…

JAVA : ArrayList和数组的转换

一、ArrayList转换为数组 ArrayList提供public T[] toArray(T[] a)方法返回一个按照正确的顺序包含此列表中所有元素的数组&#xff0c;返回数组的运行时类型就是指定数组的运行时类型。 import java.util.ArrayList; import java.util.List; public class Test { public st…

戴尔笔记本电脑重装系统后进不了系统怎么办

​戴尔电脑是一款很棒的电脑品牌&#xff0c;不少小伙伴都在使用这个牌子的电脑。但有不少小伙伴在重装完系统之后却进不去&#xff0c;那么碰到这种情况应该怎么办呢&#xff1f;下面就和小编一起来看看戴尔笔记本电脑重装系统后进不了系统怎么办的吧。 工具/原料&#xff1a…

【设计模式】-创造篇-工厂方法

制造业是一个国家工业经济发展的重要支柱&#xff0c;而工厂则是其根基所在。程序设计中的工厂类往往是对对象构造、实例化、初始化过程的封装&#xff0c;而工厂方法(Factory Method)则可以升华为一种设计模式&#xff0c;它对工厂制造方法进行接口规范化&#xff0c;以允许子…

Vector - VT System - 板卡_VT7001

接上篇我们介绍完了背板VT8006和VT8012&#xff0c;今天我们来介绍下电源模块板卡VT7001&#xff0c;这个板卡是我们在不需要程控电源的时候依然能够实现精细化的电压、电流控制及检查的板卡&#xff0c;并且在脚本开发中无需考虑时延的一个模块。我们使用的大部分设备无论是继…

14---实现文件上传和下载(头像上传功能)

1、建Files表 接下来开始完成文件管理的内容&#xff0c;首先是数据库建Files表 DROP TABLE IF EXISTS file;CREATE TABLE file (id int(11) NOT NULL AUTO_INCREMENT COMMENT id,name varchar(255) DEFAULT NULL COMMENT 文件名称,type varchar(255) DEFAULT NULL COMMENT 文…

Detection of Individual Tree Crowns in Airborne Lidar Data

Abstract 激光扫描提供了一种收集林分信息的好方法。本文介绍了一种在落叶林和混合温带森林中的小足迹光检测和测距&#xff08;激光雷达&#xff09;数据中自动描绘单棵树的方法。在光栅化激光数据中&#xff0c;可能的树顶用局部最大值滤波器检测。之后&#xff0c;结合浇注…

【Bootstrap】基础知识和环境配置

目录 一、Bootstrap基础 1. 概念 2. 特点 3. 组成 3.1 基本结构 3.2 丰富的CSS样式库 3.3 布局组件 3.4 插件 二、bootstrap的环境配置 1. 在页面中引入本地文件 2. 使用CDN加速器 一、Bootstrap基础 1. 概念 Bootstrap是一个基于HTML、CSS和JavaScript语言编写的…