CMake 基础学习-认识 CMake 基本语法与应用

CMake 基础学习-认识 CMake

什么是 CMake

CMake 是一个跨平台、可扩展的开源脚本系统,它以独立于编译器的方式在操作系统中管理编译、工程文件的生成过程。

在 Linux 中 CMake 生成 Makefile(若是其他平台,则生成对应的编译管理文件) 文件,然后由 Makefile 文件管理 C、C++ 文件的编译组织。

与普通编程语言一样,CMake 也有承载用户定义的文件裁体:CmakeList.txt 文件。通常每个目录需要一个 CMakeLists.txt。

如何安装

# For Ubuntu$ sudo apt-get install cmake# For Redhat$ yum install cmake# For Mac OS X with Macports$ sudo port install cmake

基础语法常识

指令(类似其他编程语言的函数)

CMake 命令类似于 C++/Java 方法或函数,它们将参数作为列表并相应地执行某些任务。

CMake 命令不区分大小写。有内置命令,可以从 cmake 文档中找到:https://cmake.org/cmake/help/latest/manual/cmake-commands.7.html

一些常用的命令

  • message:打印给定的消息(类似print\printf)
  • cmake_minimum_required:设置要使用的最低 CMAKE 版本
  • add_executable:添加具有给定名称的可执行目标
  • add_library:添加要从列出的源文件构建的库目标
  • add_subdirectory:添加要参与构建的子目录

还有一些命令使开发人员能够写出条件语句、循环、迭代列表、赋值:

  • if, endif
  • elif, endif
  • while, endwhile
  • foreach, endforeach
  • list
  • return
  • set_property

CMake 中缩进不是强制性的,但在编写 CMake 脚本时建议使用。不同于 C/C++ 语言,CMake 不使用分号 ;来标识语句的结尾。

所有条件语句都应以其相应的结束命令(endifendwhileendforeach*)结尾。

一些开源软件框架有自己的 CMake 风格,如 KDE:

  • https://community.kde.org/Policies/CMake_Coding_Style

CMake 参数与变量

参数和变量是区分大小写的。

如:

set(files a.txt b.txt c.txt)

set 是赋值指令、files 是变量、a.txt 是参数。上面的语句类似 C 语句中的:

files = a.txt, b.txt, c.txt;

一些特别长的参数,如特别长的文件名,以双引号将处理不方便的文件名包含起来,如:

set(files “a1111.txt")

在变量的定义中,您只能使用字母、数字、字符、下划线破折号

可以在以下 URL 中找到有关 CMake 变量的更多详细信息

  • https://cmake.org/cmake/help/v3.0/manual/cmake-language.7.html#variables
  • https://cmake.org/cmake/help/v3.0/manual/cmake 变量.7.html#手册:cmake-variables(7)

一些变量是系统根据根文件目录预定义的:

  • CMAKE_BINARY_DIR:构建库和二进制输出文件目录的完整路径,默认情况下定义为构建树的顶层。
  • CMAKE_HOME_DIRECTORY:源树顶部的路径
  • CMAKE_SOURCE_DIR:源代码的完整路径。
  • CMAKE_INCLUDE_PATH:用于查找文件的路径

可以使用 ${<variable_name>} 访问变量值。如下是赋值、打印语句的简单示例:

set(CMAKE_CXX_STANDARD 14)
message("CXX Standard: ${CMAKE_CXX_STANDARD}")

注意:在 if 语句中可以直接使用变量名,不使用 ${<variable_name>}:

if(files)message("defined files!!!!!!!!!!")
else()message("NOT defined files!!!!!!!!!")
endif()if(open STREQUAL "ON")message("open = ON")
else()message("open = OFF")
endif()

CMake 环境变量

CMake 预定义了一些变量,它们是预定于的字符,有特殊含义。

环境变量用于为常规生成过程配置编译器标志链接器标志测试配置

可以从以下 URL 中看到环境变量的详细列表:

  • https://cmake.org/cmake/help/latest/manual/cmake-env-variables.7.html

下面是一个示例,当您想在编译过程中启用所有警告时,可以通过上述 set 指令,对环境变量-Wall命令。

CMake 列表与注释

注释通过 #符号来标识。

CMake 中的所有值都存储为字符串,但在某些上下文中可以将多个字符串视为列表,每个字符串之间可以通过空格分隔。

表示为字符串的元素列表,最终会通过“;”符合来连接。

# sets files to "a.txt;b.txt;c.txt"
set(files a.txt b.txt c.txt)

使用 list(APPEND…) 命令追加列表:

list(APPEND requires "app_update" "esp_partition")

为了访问列表的值,您可以使用CMake 的 for 命令,如下所示,可以依次取出 files 中的每个元素存入 file:

foreach(file ${files})message("Filename: ${file}")
endforeach()

在 CMake 中使用宏定义

宏可定义可以帮助工程师有条件地构建代码,以根据正在运行的系统配置丢弃或包含某些方法。

您可以使用add_definitions命令在CMake中定义宏,在宏名称前使用-D标志。

让我们定义名为CMAKEMACROSAMPLE的宏,并将其打印在代码中。

# Darwin is Apple's system name
if(${CMAKE_SYSTEM_NAME} MATCHES Darwin)add_definitions(-DCMAKEMACROSAMPLE="Apple MacOS")
elseif(${CMAKE_SYSTEM_NAME} MATCHES Windows)add_definitions(-DCMAKEMACROSAMPLE="Windows PC")
elseif(${CMAKE_SYSTEM_NAME} MATCHES ubuntu)add_definitions(-DCMAKEMACROSAMPLE="linux ubuntu")
endif()

下面是带有打印宏的.cpp 源文件:

#include <iostream>
#ifndef CMAKEMACROSAMPLE#define CMAKEMACROSAMPLE "NO SYSTEM NAME"
#endif
auto sum(int a, int b){return a + b;
}
int main() {std::cout<<"Hello CMake!"<<std::endl;std::cout<<CMAKEMACROSAMPLE<<std::endl;std::cout<<"Sum of 3 + 4 :"<<sum(3, 4)<<std::endl;return 0;
}

一些学习建议:

1)实践第一。如果工作中不是经常用到 cmake 就没有必要详细的学下去了,遇到问题查询一下就可以了。

2)大型项目下,如果你不是负责系统级别的工作,你可以考虑学习些 cmake 的基本语法,入门即可。小型项目其实不太会用 cmake,直接使用 Makefile 多一些。

3)在C/C++ 领域的大型项目中,如果你负责大型项目的维护工作,可以考虑研究下 cmake 的更多用法。学习 QT 开放的同学你可能向使用 qmake 更多一些。

使用 CMake 进行构建的流行的开源项目:

  • OpenCV: https://github.com/opencv/opencv
  • Caffe2:: https://github.com/caffe2/caffe2
  • Caffe2::https://github.com/mysql/mysql-server

可阅维基百科以获取更多的开源项目 https://en.wikipedia.org/wiki/CMake#Applications_that_use_CMake

示例与解析

获取示例代码:samples1

简单 cmake 示例的解析:

# Specify the minimum version for CMake
cmake_minimum_required(VERSION 2.8)# Project's name
project(HELLO)# Set the output folder where your program will be created
set(CMAKE_BINARY_DIR ${CMAKE_SOURCE_DIR}/bin)
set(EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR})
set(LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR})# The following folder will be included
include_directories("${PROJECT_SOURCE_DIR}")

其中有一些 CMake 的全局变量

  • CMAKE_BINARY_DIR:如果您在源代码中构建,则与 CMAKE_SOURCE_DIR 相同,否则这是构建树的顶级目录。

  • CMAKE_SOURCE_DIR: 这是启动 cmake 的目录,即顶级源目录。

  • EXECUTABLE_OUTPUT_PATH: 设置此变量以指定 CMake 应放置所有可执行文件的公共位置(而不是CMAKE_CURRENT_BINARY_DIR

  • LIBRARY_OUTPUT_PATH: 设置此变量以指定 CMake 应放置所有库的公共位置(而不是CMAKE_CURRENT_BINARY_DIR

  • PROJECT_NAME: 命令设置的项目名称PROJECT()。更完整的项目名称如下,后面的几个选项都可以缺省:

    project(myAppVERSION 1.0DESCRIPTION "A brief CMake experiment"LANGUAGES CXX)
    
  • PROJECT_SOURCE_DIR: 包含项目源目录根目录的完整路径,即 CMakeLists.txt 包含 PROJECT() 命令的最近目录.

现在要编译示例的 test.cpp,你需要在 cmake 中添加:

# hello 是要生成的可执行文件(目标),后面可以跟多个源文件、头文件。
add_executable(hello ${PROJECT_SOURCE_DIR}/test.cpp)

然后在 c1 目录查看并编译源文件:

$ ls
test.cpp   CMakeLists.txt
$ cmake -H. -Bbuild  // 在 build 目录创建 cmake 构建文件的临时文件,该命令会自动生成一个 bin 目录(H indicates source directory,B indicates build directory
$ ls
bin  build  CMakeLists.txt test.cpp
$ cmake --build build -- -j3 // 生成可执行文件./bin/hello,编译时的代码优化级别为 j3
$ ./bin/hello // 运行可执行文件./bin/hello
Hello World
$ cd build // 切换到 build 目录
$ make clean // 清理工程

注意:工程名HELLO,和可执行程序的名字 hello,他们是不同的。

注意:本示例演示的是 cmake 的外部构建流程,其实内部构建生成的临时文件很多,导致大部分情况下使用起来有些麻烦,因此这里仅介绍外部构建,内部构建的方式不过多叙述。

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

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

相关文章

ElasticSearch之分布式模型介绍,选主,脑裂

写在前面 本文看下es分布式模型相关内容。 1&#xff1a;分布式模型 1.1&#xff1a;分布式特征 支持水平扩展&#xff0c;可以存储PB级别数据&#xff0c;每个就能都有自己唯一的名称,默认名称时elasticsearch&#xff0c;可以通过配置文件&#xff0c;如cluster.name: my…

canvas签名页面跟着滑动bug

记录一个花了两天时间才解决的bug&#xff0c;过程非常难受&#xff0c;需求是一个阅读合同的小程序界面&#xff0c;在阅读完成后弹出遮罩层进行签名 问题&#xff1a;在弹出层签名的时候遮罩层下面的合同也在跟着滑动&#xff0c;安卓端没有这个问题&#xff0c;真机调试的io…

PowerBI怎么修改数据库密码

第一步&#xff1a;点击转换数据 第二步&#xff1a;点击数据源设置 第三步&#xff1a;点击编辑权限 第四步&#xff1a;点击编辑 第五步&#xff1a;输入正要修改的密码就可以了

STM32启动过程及反汇编

STM32从Flash启动的过程&#xff0c;主要是从上电复位到main函数的过程&#xff0c;主要有以下步骤&#xff1a; 1.初始化堆栈指针 SP_initial_sp&#xff0c;初始化 PC 指针Reset_Handler 2.初始化中断向量表 3.配置系统时钟 4.调用 C 库函数_main 初始化用户堆栈&#xf…

SAP HANA中PAL算法使用入门

1 应用场合 SAP HANA作为一款内存数据库产品, 使得数据常驻内存, 物理磁盘的存储作为数据备份与日志记录, 以防断电内存中数据丢失. 这种构架大大的缩短了数据存取的时间, 使得SAP HANA很”高速”. 在传统数据模型中,数据库只是作为存取数据一个工具,对于类似下图所示的应用, 客…

星瑞格数据库管理系统

一. 产品介绍 随着信息化的到来&#xff0c;数据安全成为保障信息化建设的一个关键问题&#xff1b;数据库作为信息化系统的基础软件其自身安全以及对数据的保障是至关重要。现阶段国内重要部门的信息系统存放着大量敏感数据&#xff0c;为了保障其数据的安全性&#xff0c;使用…

11、电源管理入门之Regulator驱动

目录 1. Regulator驱动是什么? 2. Regulator框架介绍 2.1 regulator consumer 2.2 regulator core 2.3 regulator driver 3. DTS配置文件及初始化 4. 运行时调用 5. Consumer API 5.1 Consumer Regulator Access (static & dynamic drivers) 5.2 Regulator Outp…

基于springboot+vue的美食烹饪互动平台

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

Tomcat+Nginx的动静分离

1.反向代理多机 实验&#xff1a;Nginx要开启upstream(负载均衡)、location(url链接)、proxy_pass(反向代理) 配置&#xff1a;7-3做代理服务器&#xff1b;7-1 和 7-2做Tomcat服务器 关闭防火墙和selinux 1.准备配置 7-3安装nginx&#xff1b;7-1 和 7-2安装Tomcat&#xff…

章鱼网络 Community Call #18|Omnity 将首先支持 Runes 协议资产跨链

香港时间2024年2月8日12点&#xff0c;章鱼网络举行第18期 Community Call。 2024年&#xff0c;我们打开一个良好的局面&#xff1a;$NEAR Restaking 已经完成第三方审计&#xff0c;并且经过几次迭代&#xff0c;进入了正式稳定运行的阶段。更重要的是&#xff0c;我们宣布了…

对话框

1.焦点变更监听器 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas.android.com/apk/res/android"xmlns:app"http://schemas.android.com/apk/res-auto"xmlns:tools"http://schem…

appium解锁android真机系统的屏幕

在使用appium进行app自动化操作的过程中&#xff0c;经常遇到的第一个难题就是如何解锁系统屏幕&#xff0c;也就是亮屏解锁。 实际上解决办法如下&#xff1a;在desired_capabilities中增加两个参数unlockType和unlockKey&#xff0c;类似的示例代码如下&#xff1a; desire…

【操作系统学习笔记】文件管理1.4

【操作系统学习笔记】文件管理1.4 参考书籍: 王道考研 视频地址: Bilibili I/O 软件层次结构 I/O 请求: 用户 -> 用户层软件 -> 设备独立性软件 -> 设备驱动程序 -> 中断处理程序 -> 硬件 I/O 应答: 硬件 -> 中断处理程序 -> 设备驱动程序 -> 设备独…

一文弄懂回溯算法(例题详解)

目录 什么是回溯算法&#xff1a; 子集问题&#xff1a; 子集问题II(元素可重复但不可复选): 组合问题&#xff1a; 组合问题II(组合总和): 组合问题III(组合总和II): 排列问题&#xff1a; 排列问题II(元素可重复但不可复选): 排列问题III(元素无重复但可复选): 最后…

程序猿怎么选赛道|规划

程序员职业赛道是一个关乎个人兴趣、技能、市场需求以及长期发展规划的重要决策过程。 自我认知与兴趣挖掘 首先&#xff0c;选择职业赛道的核心是明确自身的兴趣所在和擅长之处。前端开发人员往往需要对用户体验有深刻理解&#xff0c;享受将设计变为现实&#xff0c;使用户与…

electron+vue3全家桶+vite项目搭建【29】封装窗口工具类【3】控制窗口定向移动

文章目录 引入实现效果思路声明通用的定位对象主进程模块渲染进程测试效果 引入 demo项目地址 窗口工具类系列文章&#xff1a; 封装窗口工具类【1】雏形 封装窗口工具类【2】窗口组&#xff0c;维护窗口关系 封装窗口工具类【3】控制窗口定向移动 很多时候&#xff0c;我们想…

Qt 运行一个实例进程

QLocalSocket QLocalServer 逻辑&#xff1a;首先一个新的实例启动时&#xff0c;将尝试连接到同一个本地服务器&#xff0c;如果连接失败&#xff0c;则表示第一个实例进程&#xff0c;创建一个本地服务器&#xff1b;否则&#xff0c;拉起已打开的实例进程。 main.cpp #i…

【学习心得】网站运行时间轴(爬虫逆向)

一、网站运行时间轴 掌握网站运行时间轴&#xff0c;有助于我们对“请求参数加密”和“响应数据加密”这两种反爬手段的深入理解。 二、从网站运行的时间轴角度来理解两种反爬手段 1、加载HTML&#xff1a; 这是浏览器访问网站时的第一步&#xff0c;服务器会返回基础…

C#双向链表:只用泛型节点类ListNode<T>设计的最短的双向链表包含初始化链表数据和遍历链表各节点

目录 一、涉及到的知识点&#xff1a; 1.ListNode 类使用自动属性设计 2. 泛型节点类设计的误区 二、仅仅定义泛型节点类&#xff0c;实现最短的双向链表 一、涉及到的知识点&#xff1a; 1.ListNode 类使用自动属性设计 public class ListNode {public object Object { …

javascrip几种基本的设计模式

单例模式 ES5 function Duck1(name:string){this.namenamethis.instancenull }Duck1.prototype.getNamefunction(){console.log(this.name) }Duck1.getInstancefunction(name:string){if(!this.instance){this.instance new Duck1(name)} } const aDuck1.getInstance(a) const…