【CMake】学习笔记1

news2024/11/15 11:04:07

文章目录

  • 1. CMake概述
  • 2. 编写一个简单的CMakeLists.txt
    • 2.1注释
      • 2.1.1 注释行
      • 2.1.2 块注释
    • 2.1 只有源文件
  • 3. CMake中set使用
    • set 基本使用
    • set指定使用C++标准
    • set指定输出路径
  • 4. 搜索文件

1. CMake概述

  1. CMake 是一个项目构建工具,并且是跨平台的。关于项目构建我们所熟知的还有 Makefile(通过 make 命令进行项目的构建),大多是 IDE软件都集成了 make,比如:VS的 nmake、linux下的 GNU make、Qt 的 qmake 等,如果自己动手写 makefile,会发现,makefile 通常依赖于当前的编译平台,而且编写 makefile 的工作量比较大,解决依赖关系时也容易出错。
  2. 而 CMake 恰好能解决上述问题, 其允许开发者指定整个工程的编译流程,在根据编译平台, 自动生成本地化的Makefile和工程文件,最后用户只需 make 编译即可,所以可以把 CMake 看成一款自动生成 Makefile 的工具,其编译流程如下图:
    在这里插入图片描述

2. 编写一个简单的CMakeLists.txt

系统环境:

ubuntu20.04

查看Cmake是否安装:

cmake --version

CMake优点:

  1. 跨平台
  2. 能够管理大型项目
  3. 简化编译构建和编译过程
  4. 可扩展:可以为cmake编写特定功能的模块,扩充cmake功能

2.1注释

2.1.1 注释行

CMake使用#进行行注释,可以放在任何位置

# 这是一个CMakeLists.txt文件
cmake_minimum_required(VERSION 3.0.0)

2.1.2 块注释

CMake使用#[[]]进行块注释

#[[这是一个CMakeLists.txt文件
这是一个CMakeLists.txt文件
这是一个CMakeLists.txt文件
]]
cmake_minimum_required(VERSION 3.0.0)

2.1 只有源文件

add.cpp:

#include <stdio.h>
#include "head.h"

const char* libVersion = "Library Version 1.0";

int add(int a, int b){
    return a+b;
}

div.cpp:

#include <stdio.h>
#include "head.h"

double divide(int a, int b){
    return a/b;
}

mult.cpp:

#include <stdio.h>
#include "head.h"

int multiply(int a, int b){
    return a*b;
}

sub.cpp:

#include <stdio.h>
#include "head.h"

int substract(int a, int b){
    return a-b;
}

head.h

#include <stdio.h>
#include "head.h"

int substract(int a, int b){
    return a-b;
}

main.cpp

#include <stdio.h>
#include "head.h"

int main(){
    int a = 20;
    int b = 12;
    printf("a = %d, b= %d \n",a,b);
    printf("a+b = %d \n", add(a,b));
    printf("a-b = %d \n", substract(a,b));
    printf("a*b = %d \n", multiply(a,b));
    printf("a/b = %f \n", divide(a,b));
}

添加CMakeLists.txt文件:

cmake_minimum_required(VERSION 3.0.0)
project(CALC)
add_executable(app add.cpp div.cpp main.cpp mult.cpp sub.cpp)
  1. cmake_minimum_required: 指定cmake的最低版本,可选,非必须,如果不加可能会有警告
  2. project:定义工程名称,并可指定工程的版本、工程描述、web 主页地址、支持的语言(默认情况支持所有语言),如果不需要这些都是可以忽略的,只需要指定出工程名字即可。
#PROJECT 指令的语法是:
project(<PROJECT-NAME>[<language-name>...])
project(<PROJECT-NAME>
		[VERSION <major>[.<minor>[.<patch>[.<tweak>]]]]
		[DESCRIPTI0N <project-description-string>]
		[HOMEPAGE URL <url-string>]
		[LANGUAGES <language-name>...])  # 指定语言,即cmake支持的语言
  1. add_executable : 定义工程会生成一个可执行程序
add_executable(可执行程序名 源文件名称)

这里的可执行程序名和project中的项目名称没有任何关系
源文件名可以是一个也可以是多个,如果有多个可以用空格或者;间隔

# 样式1
add_executable(app add.c div.c main.c mult.c sub.c)
# 样式2
add_executable(app add.c;div.c;main.c;mult.c;sub.c)

4. 执行CMake命令
将CMakeLists.txt文件编译好之后,就可以执行cmake命令了

# cmake 命令原型
cmake CMakeLists.txt文件所在路径 

执行CMakeLists.txt会生成一些文件,可以在CMakeLists.txt目录下新建build文件,进入build文件,然后执行命令cmake ..这时候生成的文件就会在build目录下了,之后使用make对生成的Makefile文件进行编译,得到可执行文件app

3. CMake中set使用

set 基本使用

在上面的例子中一共提供了5个源文件,假设这五个源文件需要反复被使用,每次都直接将它们的名字写出来确实是很麻烦,此时我们就需要定义一个变量,将文件名对应的字符串存储起来,在cmake 里定义变量需要使用 set

# SET 指令的语法是:
#[]中的参数为可选项,如不需要可以不写
SET(VAR [VALUE][CACHE TYPE DOCSTRING [FORCE]])

其中:
VAR:变量名称
VALUE:变量值

# 方式1:各个源文件之间使用空格间隔
# set(SRC_LIST add.c div.cmain.c mult.csub.c)
# 方式2:各个源文件之间使用分号;间隔
set(SRC_LIST add.c;div.c;main.c;mult.c;sub.c)
add_executable(app${SRC_LIST})

set中变量的值都是字符串类型

set指定使用C++标准

在编写 C++程序的时候,可能会用到C++11、C++14、C++17、C++20 等新特性,那么就需要在编译的时候在编译命令中指定出要使用哪个标准:
如果不指定则默认使用C++98标准

g++ *.cpp -std=c+=11 -o app

上面的例子中通过参数 -std=c++11 指定出要使用 C++11 标准编译程序,C++标准对应有一宏叫做DCMAKE_CXX_STANDARD。在CMake 中想要指定C++标准有种方式:

1. 在CMakeLists.txt中通过set命令指定

# 增加 -std=c++11
set(CMAKE_CXX_STANDARD 11)

# 增加 -std=c++14
set(CMAKE_CXX_STANDARD 14)

# 增加 -std=c++17
set(CMAKE_CXX_STANDARD 17)

2.在执行cmake命令的时候指定出这个宏的值

# 增加-std=c++11
cmake CMakeLists.txt文件路径 -DCMAKE_CXX_STANDARD=11
# 增加-std=c++14
cmake CMakeLists.txt文件路径 -DCMAKE_CXX_STANDARD=14
# 增加-std=c++17
cmake CMakeLists.txt文件路径 -DCMAKE_CXX_STANDARD=17

set指定输出路径

在 CMake 中指定可执行程序输出的路径,也对应一个宏,叫做EXECUTABLE_OUTPUT_PATH,它的值还是通过 set

set(HOME /home/robin/Linux/Sort)
set(EXECUTABLE_OUTPUT_PATH ${HOME}/bin)
  1. 第一行:定义一个变量用于存储一个绝对路径
  2. 第二行:将拼接好的路径值设置给EXECUTABLE_OUTPUT_PATH 宏,如果这个路径中的子目录不存在会自动生成,无需自己手动创建,路径建议用绝对路径

修改之前的CMakeLists.txt文件:

cmake_minimum_required(VERSION 3.0.0)
project(test)

# 指定使用C++标准
set(CMAKE_CXX_STANDARD 11)
set(SRC add.cpp div.cpp main.cpp mult.cpp sub.cpp)

# 指定可执行文件生成路径
set(EXECUTABLE_OUTPUT_PATH /home/dabing/aa/bb/cc)
add_executable(app ${SRC})

4. 搜索文件

如果一个项目里边的源文件很多,在编写 CMakeLists.txt 文件的时候不可能将项目目录的各个文件一一罗列出来,这样太麻烦也不现实。所以,在CMake 中为我们提供了搜索文件的命令,可以使用aux_source_directory命令或者 file命令。

方式1:aux_source_directory

aux_source_directory(<dir> <variable>)
  1. dir: 要搜索的目录
  2. variable:将dir目录下搜索到的源文件列表存储到该变量中
cmake_minimum_required(VERSION 3.0.0)
project(test)

# 指定使用C++标准
set(CMAKE_CXX_STANDARD 11)

# aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR} SRC_LIST)
aux_source_directory(${PROJECT_SOURCE_DIR} SRC_LIST)
add_executable(app ${SRC_LIST})

方式2:file

fiLe(GLOB/GLOB_RECURSE 变量名 要搜索的文件路径和文件类型)

GLOB:将指定目录下搜索到的满足条件的所有文件名生成一个列表,并将其存储到变量中。
GLOB_RECURSE:递归搜索指定目录,将搜索到的满足条件的文件名生成一个列表,并将其存储到变量中。

搜索当前目录的src目录下所有源文件,并存储到变量中:

file(GLOB MAIN_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp)
file(GLOB MAIN_HEAD ${CMAKE_CURRENT_SOURCE _DIR}/include/*.h)

CMAKE_CURRENT_SOURCE_DIR:表示当前访问的CMakeLists.txt文件所在的路径
关于要搜索的文件路径和类型可以加双引号雨可以不加:
PROJECT_SOURCE_DIR: 是在执行cmake命令时后面跟着的路径

file(GLOB MAIN_HEAD "${CMAKE_CURRENT_SOURCE _DIR}/include/*.h")

使用示例:

cmake_minimum_required(VERSION 3.0.0)
project(test)

# 指定使用C++标准
set(CMAKE_CXX_STANDARD 11)
file(GLOB SRC_LIST ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp)
add_executable(app ${SRC_LIST})

注意:在实际使用中aux_source_directory使用更方便,因为file不仅要指定路径,还要指定文件后缀

本文参考:https://www.bilibili.com/video/BV14s4y1g7Zj/?spm_id_from=333.999.0.0

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

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

相关文章

【安全与管理并重】揭秘公司老板如何平衡信任与效率,利用非授权监控软件优化管理!

企业面临着前所未有的竞争压力&#xff0c;同时还需要确保内部管理的有效性和数据的安全性。如何在信任与效率之间找到平衡点&#xff0c;成为了许多公司老板关注的重点。安企神软件作为一款集数据防泄密、行为监控与流程化管理于一体的综合性解决方案&#xff0c;为企业提供了…

SpringCloud集成XXL-JOB定时任务

项目场景&#xff1a; XXL-JOB是一个分布式任务调度平台&#xff0c;它能够帮助开发者轻松地实现任务的定时执行、任务调度和任务管理 接入步骤 下载XXL-JOB压缩包 链接: xxl-job XXL-JOB做为子模块 将压缩包解压&#xff0c;项目二级新建目录xxl-job&#xff0c;放入目录…

后端Spring/SpringBoot框架基础介绍

1.Spring基础介绍 spring官网&#xff1a;https://spring.io/ 官方对spring的描述&#xff1a;使java更快、更容易、更安全&#xff0c;聚焦于速度、简洁和生产力。并且是全世界最流行的Java框架。 Spring如今已经形成开发生态圈&#xff0c;它提供若干个子项目&#xff0c;每…

超声波清洗机哪个牌子效果最好?四个可靠的超声波眼镜清洗机品牌推荐

作为一个常年佩戴眼镜的用户&#xff0c;还是养宠家庭&#xff0c;对于眼镜的清洗&#xff0c;一直是倍感困扰的&#xff0c;养宠的家庭&#xff0c;每天镜片上极易沾染灰尘&#xff0c;用眼镜布擦拭真的很容易把镜片刮花。尽管有时候路过眼镜店会进去清洗&#xff0c;但是终归…

【数学建模】LINGO编程

LINGO是一种专门用于求解数学规划问题的软件包。由于LINGO执行速度快&#xff0c;易于方便地输入、求解和分析数学规划问题&#xff0c;因此在教学、科研和工业界得到了广泛应用。LINGO主要用于求解线性规划、非线性规划、一次规划和整数规划等问题&#xff0c;也可用于求解一些…

Next-Key Lock 详解及其在 REPEATABLE READ 隔离级别中的作用

Next-Key Lock 是 MySQL InnoDB 引擎中使用的一种锁定机制&#xff0c;专门用于在 REPEATABLE READ 隔离级别下防止幻读&#xff08;Phantom Reads&#xff09;。它结合了行锁&#xff08;Record Lock&#xff09;和间隙锁&#xff08;Gap Lock&#xff09;&#xff0c;能够在高…

抽卡机小程序,开启全新拆卡乐趣

近段时间&#xff0c;盲盒卡牌市场异常火爆&#xff0c;最近爆火的“小马宝莉”系列卡牌就深受消费者的喜爱&#xff0c;受到了广泛关注&#xff0c;同时也推动了卡牌市场的快速发展&#xff01;盲盒卡牌拥有隐藏款卡牌和限量款卡牌&#xff0c;具有非常大的收藏价值&#xff0…

图纸防泄密高招:5款经典的图纸加密软件

图纸加密软件是专为保护设计图纸等敏感文件而设计的加密工具&#xff0c;通过先进的加密技术确保文件在传输、存储和使用过程中的安全性。小编试用后发现了5款经典的图纸加密软件。 1. 安企神软件 7天试用https://work.weixin.qq.com/ca/cawcde06a33907e60a 重点介绍&#xf…

2-68 基于matlab的小波分解子模式和盒维数的车型识别程序

基于matlab的小波分解子模式和盒维数的车型识别程序&#xff0c;可以选择不同车型&#xff0c;包括小车、中车、大车。GUI可视化界面操作&#xff0c;已包括多种图片。程序已调通&#xff0c;可直接运行。 2-68 小波分解子模式和盒维数 - 小红书 (xiaohongshu.com)

软件工程的核心原则:KISS, DRY, SOLID, YAGNI

软件工程的核心原则&#xff1a;KISS, DRY, SOLID, YAGNI — 深入解析与实践指南 引言 在软件开发的广阔领域中&#xff0c;原则和实践是构建高质量、可维护系统的基石。本文将深入探讨四个核心原则&#xff1a;KISS&#xff08;保持简单&#xff0c;愚蠢&#xff09;、DRY&a…

Element-05.组件-Form表单

一.Form表单组件 Form表单组件可以定义在Dialog对话框组件中 与Dialog对话框组件中的属性dialogTableVisible相似&#xff0c;dialogFormVisible的默认值也为false&#xff0c;这也说明了Dialog对话框中的Form表单默认是不显示的&#xff0c;只有当绑定的click事件发生后才会将…

解决麒麟 V10 SP1 升级 Python 后 yum dnf不可用问题

目录 一、前提概要 二、解决办法 1、卸载原有的 python 2、安装 Python 3.7.9 rpm 3、安装一系列 yum 相关 rpm 4、rpm 包下载 一、前提概要 在部署 gaussDB 的时候&#xff0c;安装代理时要求 python 版本满足 3.7.9&#xff0c;但已安装的麒麟 V10 内集成的 python 版…

探索工业互联网智能赋能智能制造算法综述

概述 文档地址&#xff1a;https://arxiv.org/pdf/2312.16174 源码地址&#xff1a;https://github.com/microsoft/Cream.git 由于激烈的竞争环境和日益增长的个性化定制需求&#xff0c;制造业面临着数字化转型和升级的压力。为我们指明了前进的方向。然而&#xff0c;现有研…

stable diffusion inapinting(img2img+inpaint/inapint-model)

https://zhuanlan.zhihu.com/p/681250295https://zhuanlan.zhihu.com/p/681250295AIGC专栏4——Stable Diffusion原理解析-inpaint修复图片为例_diffusion inpaint-CSDN博客文章浏览阅读1.7w次,点赞42次,收藏79次。Inpaint是Stable Diffusion中的常用方法,一起简单学习一下。…

python之pandas (5 画图)

画图 Series画图 import pandas as pd import numpy as np import matplotlib.pyplot as pltdatapd.Series(np.random.randn(1000),indexnp.arange(1000)) #randn生成服从标准正态分布&#xff08;均值为0&#xff0c;标准差为1&#xff09;的随机样本&#xff0c;1000表示10…

复现YOLOv8语义分割训练自己的数据集

一、YOLOv8源码下载&#xff1a;https://github.com/ultralytics/ultralytics/tree/v8.2.76 我下载的是最新版本8.2.76 接着下载权重 下载源码后解压 二、配置虚拟环境 创建虚拟环境 conda create -n yolov8 python3.9 激活环境 conda activate yolov8 下载pytorch,官网地…

数据结构——关于栈

1.栈 1.1栈的概念及结构 栈&#xff1a;一种特殊的线性表&#xff0c;其只允许在固定的一端进行插入和删除元素操作 进行数据插入和删除操作的一端称为栈顶&#xff0c;另一端称为栈底。栈中的数据元素遵守后进先出的原则 比如&#xff1a;羽毛球桶&#xff0c;弹夹等等 压…

【C++面经】

1 2 因为ptr还记录了对象的个数&#xff0c;通过中括号标识&#xff0c;就知道药一一调用数组的每个对象的析构函数 3 4 5 6

【C语言】二叉树链式结构的实现,详解

0.前言 二叉树的基本操作的实现基本离不开一个思想——分治算法。 分治算法的基本思想是将一个规模为n的问题分解为k个规模较小的子问题&#xff0c;这些子问题相互独立且与原问题相同。递归地解这些子问题&#xff0c;然后将各子问题的解合并得到原问题的解。这样&#xff0…

mysql主从复制同步、mysql5.7版本安装配置、python操作mysql数据库、mycat读写分离实现

一、mysql主从复制及同步 1、mysql主从自动开机同步 2、配置mysql5.7版本 mysql-5.7.44-linux-glibc2.12-x86_64.tar 启动服务、登录 对数据库进行基本操作 3、使用python操纵mysql数据库 4、编辑python脚本自动化操纵mysql数据库 二、mycat读写分离实现 1.上传jdk和mycat安装包…