CMake基础教程

news2025/1/12 17:23:26

CMake最大优势是跨平台,可以根据不同的平台生成Makefile文件,看下CMake的基础使用。

cmake(单目录单文件)

第一个最简单的cmake构建。

demo1.cpp代码:

#include <iostream>

using namespace std;

int main(int argc, char *argv[]) {
    cout << "hello, cmake" << endl;
    return 0;
}

编写 CMakeLists.txt 文件

CMAKE_MINIMUM_REQUIRED(VERSION 3.10)

PROJECT(demo1)

# 生成可执行程序
ADD_EXECUTABLE(demo1 demo1.cpp)

在当前目录下,执行cmake:

lorien@ubuntu20:/work2/cmake/demo1$ cmake ./

会生成一些中间文件和Makefile文件。
在这里插入图片描述
执行make

lorien@ubuntu20:/work2/cmake/demo1$ make

第一个cmake构建就完成了。

cmake(单目录多文件)

目录结构:
在这里插入图片描述

main.cpp:

#include "hello_cmake.h"

int main(int argc, char *argv[]) {
    print_hello();
    return 0;
}

hello_cmake.cpp:

#include <iostream>

using namespace std;

int print_hello() {
    cout << "hello cmake" << endl;
    return 0;
}

hello_cmake.h:

int print_hello();

看下CMakeLists.txt的写法

CMAKE_MINIMUM_REQUIRED(VERSION 3.10)

PROJECT(demo2)

# 生成可执行程序
ADD_EXECUTABLE(demo2 main.cpp hello_cmake.cpp)

通过在ADD_EXECUTABLE后面追加源文件就可以实现但目录多文件cmake构建。

如果源文件太多,在后面一直追加很是麻烦,AUX_SOURCE_DIRECTORY可以解决这个问题。

AUX_SOURCE_DIRECTORY:发现一个目录下所有源代码文件并将列表存储在一个变量中

CMAKE_MINIMUM_REQUIRED(VERSION 3.10)

PROJECT(demo2)

AUX_SOURCE_DIRECTORY(./ DIR_HELLO_SRCS)

ADD_EXECUTABLE(demo2 ${DIR_HELLO_SRCS})

cmake(多目录多文件)

文件结构如下:

在这里插入图片描述
源文件和上面一样,不再贴了。看一下子目录和根目录下的CMakeLists.txt

mylib目录下的CMakeLists.txt

AUX_SOURCE_DIRECTORY(./ DIR_LIB_SRCS)

# 生成库文件
ADD_LIBRARY(mylib STATIC ${DIR_LIB_SRCS})

ADD_LIBRARY:表示生成库文件。STATIC表示静态库。这样mylib下的所有源代码会被编译成一个.a文件

根目录下的CMakeLists.txt

CMAKE_MINIMUM_REQUIRED(VERSION 3.10)

PROJECT(demo3)

# 向当前工程添加存放源文件的子目录
ADD_SUBDIRECTORY(./mylib)

AUX_SOURCE_DIRECTORY(./ DIR_HELLO_SRCS)

ADD_EXECUTABLE(demo3 ${DIR_HELLO_SRCS})

# 为target链接共享库
TARGET_LINK_LIBRARIES(demo3 mylib)

解释下两个命令:

  • ADD_SUBDIRECTORY:向当前工程添加存放源文件的子目录
  • TARGET_LINK_LIBRARIES: 为target链接共享库,target是demo3。库是mylib,这个库由上面mylib目录下的源代码编译生成。

在根目录下执行:cmake ./

我们看到在mylib目录下生成了库文件libmylib.a,在根目录下生成了可执行文件:demo3
在这里插入图片描述

cmake工程标准结构

上面的例子,源文件和cmake构建的中间产物混在一起,导致源文件被污染。合理的目录结构如下:
在这里插入图片描述

  • mylib/:存放三方库文件
  • src/:项目源文件
  • build/:cmake构建中间产物

mylib/CMakeLists.txt

AUX_SOURCE_DIRECTORY(./ DIR_LIB_SRCS)

# 指定库文件存储路径
SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib)

# 生成库文件
ADD_LIBRARY(mylib STATIC ${DIR_LIB_SRCS})

LIBRARY_OUTPUT_PATH 用于指定库文件的生成路径。

PROJECT_BINARY_DIR表示工程二进制根目录,这个目录是执行cmake命令时所处的目录,比如我们会在build下面执行cmake目录,PROJECT_BINARY_DIR就是build/

src/CMakeLists.txt

# 包含头文件搜索目录
INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/mylib)

# 指定可执行程序存储路径
SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)

AUX_SOURCE_DIRECTORY(./ DIR_SRCS)

# 生成可执行文件
ADD_EXECUTABLE(demo4 ${DIR_SRCS})

TARGET_LINK_LIBRARIES(demo4 mylib)

INCLUDE_DIRECTORIES:向工程添加头文件搜索路径。添加这个命令后,我们在源文件中include头文件就不用再添加目录下。src/main.cpp

// 通过INCLUDE_DIRECTORIES添加了头文件搜索路径,可以直接include文件
#include "hello_cmake.h"

int main(int argc, char *argv[]) {
    print_hello();
    return 0;
}

顶层目录下的CMakeLists.txt

CMAKE_MINIMUM_REQUIRED(VERSION 3.10)

PROJECT(demo4)

# 向当前工程添加存放源文件的子目录
ADD_SUBDIRECTORY(./mylib)

# 向当前工程添加存放源文件的子目录
ADD_SUBDIRECTORY(./src)

我们cd进入build目录,执行命令

cmake ..

看下文件结构:
在这里插入图片描述
可以看到中间文件都在build目录下面,同时生成了bin/ 和 lib/目录。避免了我们源文件被污染。接下来在build目录执行make

在这里插入图片描述
最终,可执行文件demo4在bin目录下,库文件libmylib.a在lib目录下。

cmake自定义编译选项

cmake实现自定义编译选项用来控制程序逻辑。先看下demo目录结构

在这里插入图片描述

顶层目录的CMakeLists.txt

CMAKE_MINIMUM_REQUIRED(VERSION 3.10)

PROJECT(demo5)

# 向当前工程添加存放源文件的子目录
ADD_SUBDIRECTORY(./src)

src/CMakeLists.txt

configure_file(
    "${PROJECT_SOURCE_DIR}/config/config.h.in"
    "${PROJECT_SOURCE_DIR}/config/config.h"
)

option(MY_LOG
    "use MY_LOG"
    ON)

SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)

AUX_SOURCE_DIRECTORY(./ DIR_SRCS)

ADD_EXECUTABLE(demo5 ${DIR_SRCS})

重点是configure_file和option

  • configure_file:生成配置头文件config.h,这个头文件通过config.h.in生成。
  • option:配置宏打开或者关闭

config/config.h.in

#cmakedefine MY_LOG

src/main.cpp

#include <iostream>
#include "../config/config.h"

using namespace std;

int main(int argc, char *argv[]) {
#ifdef MY_LOG
    cout << "define MY_LOG" << endl;
#else
    cout << "not define MY_LOG" << endl;
#endif
    return 0;
}

接着我们进入build目录,执行cmake

cmake ..

一切正常的话,我们会在config目录下,发现cmake自动生成了头文件config.h

#define MY_LOG

如果要关掉宏定义,在src/CMakeLists.txt里面设置option为OFF

option(MY_LOG
    "use MY_LOG"
    OFF)

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

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

相关文章

【基于机械臂触觉伺服的物体操控研究】UR5e动力学建模及代码实现

我的毕设题目定为《基于机械臂触觉伺服的物体操控研究》&#xff0c;这个系列主要用于记录做毕设的过程。 前言&#xff1a;UR系列是优傲公司的代表产品&#xff0c;也是目前比较通用的产品级机械臂。所以我打算用该机械臂进行毕设的仿真实现。关于其动力学建模&#xff0c;网…

台阶问题-

台阶问题 题目描述 有NNN级的台阶&#xff0c;你一开始在底部&#xff0c;每次可以向上迈最多KKK级台阶&#xff08;最少111级&#xff09;&#xff0c;问到达第NNN级台阶有多少种不同方式。 输入格式 两个正整数N&#xff0c;K。 输出格式 一个正整数&#xff0c;为不同…

JVM(一)——架构基础

JVM java虚拟机 java gc 主要回收的是 方法区 和 堆中的内容&#xff0c;以下架构图是重点&#xff1a; 方法区和堆是线程共享&#xff0c;java栈、本机方法栈、程序计数器是线程私有。 运行时数据区可以用Runtime.getRuntime()获取 字节码执行引擎&#xff0c;修改程序计数器…

不要怀疑了,个人也是可以做好跨境电商的!

近几年随着跨境电商卖家们赚得盆满钵满&#xff0c;许多人都想从中分一杯羹&#xff0c;进而入住了跨境电商市场&#xff0c;有人与一些公司企业合作&#xff0c;也有人选择了自己做跨境电商平台&#xff0c;个人做的优劣势又有哪些呢&#xff1f; 个人做跨境电商平台最明显突…

A V L树

概念 在之前介绍了搜索二叉树&#xff0c;但是当我们插入的数据若是有序或者接近于有序&#xff0c;那么此时查找的效率底下&#xff0c;于是俄罗斯的数学家G.M.Adelson-Velskii和E.M.Landis在1962年发明了一种解决上述问题的方法&#xff1a;当向二叉搜索树中插入新结点后&am…

javaEE学生教学实习计划申报系统Myeclipse开发mysql数据库web结构jsp编程计算机网页项目

一、源码特点 javaEE学生教学实习计划申报系统 是一套完善的web设计系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为TOMCAT7.0,Myeclipse8.5开发&#xff0c;数据库为Mysql&…

正点原子【第四期】手把手教你学 Linux之驱动开发篇-01

学习目的 了解驱动开发和应用开发的过程&#xff0c;具有一定的基础就行 第一讲&#xff1a;linux驱动开发与裸机开发区别 刚开始听不懂很正常&#xff0c;等之后学了一点你就会知道它说啥了 第二讲&#xff1a;字符设备驱动开发基础 字符设备驱动是最简单的&#xff0c;块设…

C++ 移动语义

从拷贝说起我们知道&#xff0c;C中有拷贝构造函数和拷贝赋值运算符。那既然是拷贝&#xff0c;听上去就是开销很大的操作。没错&#xff0c;所谓拷贝&#xff0c;就是申请一块新的内存空间&#xff0c;然后将数据复制到新的内存空间中。如果一个对象中都是一些基本类型的数据的…

【Unity3D】绘制物体外框线条盒子

1 需求描述 点选物体、框选物体、绘制外边框 中介绍了物体投影到屏幕上的二维外框绘制方法&#xff0c;本文将介绍物体外框线条盒子绘制方法。 内框&#xff1a;选中物体后&#xff0c;绘制物体的内框&#xff08;紧贴物体、并与物体姿态一致的内框盒子&#xff09;外框&#…

Python与C++语法比较--字符串篇

tags: C Python 写在前面 刷lc从Python转向C, 不只是语法层面, 还要改变很多的API, 这次记录一下C和Python在字符串方面的一些区别, 供参考. 基本区别 Python字符串是不可变类型, 而C的String为容器(本质上是一个类的别名, 说容器有点不合适, 因为容器内的元素类型已经被指…

Kotlin中的Lambda编程

文章目录1.集合的创建与遍历2.集合的函数式API3.Java函数式API的使用1.集合的创建与遍历 传统意义上的集合主要是List和Set&#xff0c;再广泛一点的话&#xff0c;像Map这样的键值对数据结构也可以包含进来。List&#xff0c;Set和Map再Java中都是接口&#xff0c;List主要的…

Java设计模式-命令模式Command

介绍 命令模式&#xff08;Command Pattern&#xff09;&#xff1a;在软件设计中&#xff0c;我们经常需要向某些对象发送请求&#xff0c;但是并不知道请求的接收 者是谁&#xff0c;也不知道被请求的操作是哪个&#xff0c; 我们只需在程序运行时指定具体的请求接收者即可&…

数影周报:TikTok因在线跟踪被罚500万欧,Windows 7退出历史舞台

本周看点&#xff1a;TikTok因在线跟踪被法国罚款500万欧元 &#xff1b;思科已裁员近700 人&#xff1b;Windows 7退出历史舞台&#xff1b;亚马逊向所有卖家开放Buy with Prime服务&#xff1b;“全路程”完成2亿元C轮融资......数据安全那些事TikTok因在线跟踪被法国罚款500…

Android13 wifi无线调试adb连接设置

在进行adb调试的时候&#xff0c;有时候需要使用wifi连接&#xff0c;或者wifi连接较为方便&#xff0c;早些的Android上&#xff0c;需要设置端口等操作&#xff0c;adb tcpip 6666参考android wifi adb 调试 - 简书 (jianshu.com)好几步操作&#xff0c;在Android13上&#x…

Deque 的理解 STL中stack与queue为什么选择使用deque为底层模板容器

目录 一、Deque的引入 二、Deque是什么&#xff1f; 三、deque的遍历方式&#xff1f;deque的缺陷&#xff1f; 四、它为什么能更贴合与stack与queue&#xff1f; 五、STL中vector与list的底层实现 一、Deque的引入 Stack、Queue在之前的博客中我也是分别使用了更容易处理…

【蓝桥杯】历届真题 杨辉三角形 (省赛)Java

【问题描述】 下面的图形是著名的杨辉三角形: 如果我们按从上到下、从左到右的顺序把所有数排成一列&#xff0c;可以得到如下数列: 1,1&#xff0c;1&#xff0c;1&#xff0c;2,1&#xff0c;1&#xff0c;3,3&#xff0c;1&#xff0c;1,4&#xff0c;6,4&#xff0c;1&…

数字IC设计、验证、FPGA笔试必会 - Verilog经典习题 (六)多功能数据处理器

数字IC设计、验证、FPGA笔试必会 - Verilog经典习题 &#xff08;六&#xff09;多功能数据处理器 &#x1f508;声明&#xff1a; &#x1f603;博主主页&#xff1a;王_嘻嘻的CSDN博客 &#x1f9e8;未经作者允许&#xff0c;禁止转载 &#x1f511;系列专栏&#xff1a;牛客…

react基础Day02-受控组件评论案例propscontext

React组件 目标 能够知道受控组件是什么能够写出受控组件了解非受控组件 表单处理 受控组件&#xff08;★★★&#xff09; HTML中的表单元素是可输入的&#xff0c;也就是有自己的可变状态而React中可变状态通常保存在state中&#xff0c;并且只能通过setState() 方法来…

[acwing周赛复盘] 第 86 场周赛20230114

[acwing周赛复盘] 第 86 场周赛20230114 一、本周周赛总结二、 4794. 健身1. 题目描述2. 思路分析3. 代码实现三、4795. 安全区域1. 题目描述2. 思路分析3. 代码实现四、4796. 删除序列1. 题目描述2. 思路分析3. 代码实现六、参考链接一、本周周赛总结 去吃羊蝎子了&#xff0…

基于汽车知识图谱的汽车问答多轮对话系统 详细教程

结果: 1 技术路线 该技术路线主要将KBQA分为三部分,实体识别与实体链接,关系识别,sparql查询,其中每个部分分为一到多种方法实现。具体的处理流程图如下: