cmake简单使用

news2024/11/24 14:14:40

简介

理论上,任意一个C++程序都可以用g++来编译

当程序规模越来越大时,一个工程可能有许多个文件夹和源文件,这时输入的编译命令将越来越长。通常,一个小型C++项目可能含有十几个类,各类间还存在着复杂的依赖关系。其中一部分要编译成可执行文件,另一部分编译成库文件。如果仅靠g++命令,则需要输入大量的编译指令,整个编译过程会变得异常烦琐。因此,对于C++项目,使用一些工程管理工具会更加高效。在历史上,工程师们曾使用makefile进行自动编译,但下面要谈的cmake比它更加方便。并且cmake在工程上广泛使用

cmake允许开发者编写一种与平台无关(跨平台)的CMakeLists.txt 文件来制定整个工程的编译流程,cmake 工具会解析CMakeLists.txt 文件语法规则,再根据当前的编译平台,生成本地化的Makefile 和工程文件

简而言之,makefile是一个定义源文件编译过程的文件,而CMakeLists.txt是一个可以生成makefile的文件,它们之间的关系如下图所示:

cmake的下载

sudo apt-get install cmake

 cmake的使用

单个文件编译

如下,我们写了一个简单的cpp文件

 #include<iostream>                                                            
 using namespace std;
  
 int main()
 {
     cout<<"hello slam!"<<endl;
     return 0;
 }

现在我们想编译该文件以生成一个可执行文件,如果使用g++进行编译是这样的:

g++ helloSLAM.cpp -o helloSLAM

如果我们使用cmake,则我们首先需要编写CMakeLists.txt文件,内容如下:

  #声明cmake的最低版本
  cmake_minimum_required(VERSION 2.8)
  #声明一个cmake工程
  project(hello)
  #添加一个可执行文件,类似于执行g++ helloSLAM.cpp -o helloSLAM                 
  add_executable(helloSLAM helloSLAM.cpp )

文件中内容的各行作用如注释所示

当前路径下各文件如下所示:

保存该文件后,执行如下命令

cmake ./

cmake 后面携带的路径指定了CMakeLists.txt 文件的所在路径,执行结果如下所示

可以看到,执行完cmake 之后,除了源文件main.c 和CMakeLists.txt 之外,生成了很多其它的文件或文件夹,包括:CMakeCache.txt、CmakeFiles、cmake_install.cmake、Makefile 

接下来,我们之间执行make编译命令即可生成可执行文件

执行可执行文件,执行结果如下 

为了便于管理,我们可以把cmake生成的文件单独存放在一个文件夹内, 这时我们只需创建一个build文件夹

之后进入build文件夹,执行

cmake ../

可以看到,此时cmake生成的文件就全部在build文件中了 

使用库文件

如果我们的源代码中使用了库文件,该如何编写CMakeLists.txt文件呢

库文件libHelloSLAM.h

  #ifndef LIBHELLOSLAM_H                                                        
  #define LIBHELLOSLAM_H
  
  void printHello();
  
  #endif

libHelloSLAM.cpp

  #include<iostream>
  using namespace std;
  void printHello()
  {
      cout<<"hello SLAM!"<<endl;
      return;
  }

helloSLAM.cpp 

  #include<iostream>
  using namespace std;
  #include"libHelloSLAM.h"
  int main()
  {
  //  cout<<"hello slam!"<<endl;
      printHello();                                                             
      return 0;
  }

则CMakeLists.txt文件内容如下:

  #声明cmake的最低版本                                                          
  cmake_minimum_required(VERSION 2.8)
  #声明一个cmake工程
  project(hello)
  
  #添加一个静态库文件
  add_library(helloLib libHelloSLAM.cpp)
  #添加一个可执行文件,类似于执行g++ helloSLAM.cpp -o helloSLAM
  add_executable(helloSLAM helloSLAM.cpp )
  #将库文件内容链接到可执行程序上
  target_link_libraries(helloSLAM helloLib)

此时文件结构如下:

之后再次进入build文件夹执行cmake ../命令,文件夹结构没有什么变化

但是执行完make编译命令后,再次查看build文件夹,会发现多了一个libhelloLib.a的文件,该文件就是我们的静态库文件

在Linux中,库文件分成静态库和共享库两种静态库以.a作为后缀名,共享库以.so结尾。所有库都是一些函数打包后的集合,差别在于静态库每次被调用都会生成一个副本,而共享库则只有一个副本,更省空间

如果想生成共享库而不是静态库,只需使用以下语句即可。 

add_library(helloSharedLib SHARED libHelloSLAM.cpp) 

此时CMakeLists.txt文件内容为:

  #声明cmake的最低版本
  cmake_minimum_required(VERSION 2.8)
  #声明一个cmake工程
  project(hello)
  
  #添加一个静态库文件
  #add_library(helloLib libHelloSLAM.cpp)
  #添加一个动态库文件
  add_library(helloSharedLib SHARED libHelloSLAM.cpp)
  #添加一个可执行文件,类似于执行g++ helloSLAM.cpp -o helloSLAM
  add_executable(helloSLAM helloSLAM.cpp )
  #将库文件内容链接到可执行程序上
  target_link_libraries(helloSLAM helloSharedLib) 

再次执行cmake ..命令和make编译命令后,build文件内容如下:

将源文件放在不同的目录

文件结构如下:
 

.
├── build
├── CMakeLists.txt
├── libHello
│   ├── CMakeLists.txt
│   ├── libHelloSLAM.cpp
│   └── libHelloSLAM.h
└── src
    ├── CMakeLists.txt
    └── helloSLAM.cpp

  • 顶层CMakeLists.txt
  #声明cmake的最低版本
  cmake_minimum_required(VERSION 2.8)
  #声明一个cmake工程
  project(hello)
  
  #添加子文件
  add_subdirectory(libHello)
  add_subdirectory(src) 

其中add_subdirectory 命令告诉cmake 去子目录中寻找新的CMakeLists.txt 文件并解析它 

  • libHello文件夹内的CMakeLists.txt文件 
  add_library(libSharedHello SHARED libHelloSLAM.cpp) 

libHello文件夹内存放的是库文件,因此该 CMakeLists.txt文件表示生成一个共享库文件

  • src文件夹内的 CMakeLists.txt文件 
  include_directories(../libHello)                                              
  add_executable(helloSLAM helloSLAM.cpp)
  target_link_libraries(helloSLAM libSharedHello)

该文件夹内存放的是主程序,其中include_directories 命令用来指明头文件所在的路径 

或者如下:

  include_directories(${PROJECT_SOURCE_DIR}/libHello)
  add_executable(helloSLAM helloSLAM.cpp)
  target_link_libraries(helloSLAM libSharedHello)

这种方式使用到了PROJECT_SOURCE_DIR 变量,该变量指向了一个路径,从命名上可知,该变量表示工程源码的目录。 

和前面一样,进入到build 目录下进行构建、编译,最终会得到可执行文件helloSLAM(build/src/helloSLAM)和库文件libSharedHello.so(build/libHello/libSharedHello.so)

将生成的可执行文件和库文件放在不同的目录

如果我想让可执行文件单独放置在bin目录下,而库文件单独放置在lib目录下,如下所示

├──build
	├──lib
	│	└──libSharedHello.so
	└──bin
		└──helloSLAM

可以通过两个变量来实现,将src 目录下的CMakeList.txt 文件进行修改,如下所示:

  include_directories(${PROJECT_SOURCE_DIR}/libHello)
  set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
  add_executable(helloSLAM helloSLAM.cpp)
  target_link_libraries(helloSLAM libSharedHello)

然后再对libhello 目录下的CMakeList.txt 文件进行修改,如下所示:

  set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib)                            
  add_library(libSharedHello SHARED libHelloSLAM.cpp)

EXECUTABLE_OUTPUT_PATH 变量控制可执行文件的输出路径,
LIBRARY_OUTPUT_PATH 变量控制库文件的输出路径。

参考:

【精选】CMake 入门与进阶_.cmake文件-CSDN博客 

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

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

相关文章

Unity优化(1)——合并Mesh

在某些移动端项目中&#xff0c;对于DrawCall的要求是很严格的&#xff0c;我们一般查看DrawCall可以通过Statistics里面的Batches进行查看&#xff0c;一般移动设备的Batches要控制在200左右比较合适&#xff0c;所以降低Batches是很重要的。 我们常常会遇到一个物体下挂载很多…

【观察】OpenHarmony:技术先进“创新局”,持续创新“谋新篇”

毫无疑问&#xff0c;开源作为今天整个软件产业的创新“原动力”&#xff0c;目前在软件产业发展中的重要性愈加凸显。根据Linux基金会的统计&#xff0c;现在全球软件产业中有70%以上的代码来源于开源软件。 从这个角度来看&#xff0c;开源技术已逐渐成为推动企业数字化转型和…

任正非说:10%的特殊场景就像牛在路上,谁也不知道它会在哪拉屎

你好&#xff01;这是华研荟【任正非说】系列的第40篇文章&#xff0c;让我们聆听任正非先生的真知灼见&#xff0c;学习华为的管理思想和管理理念。 一、我们要建立核心生产能力&#xff0c;否则我们对供应链理解不深&#xff0c;供应链不能打通。我们之所以管道系统做得好&am…

【LeetCode刷题笔记】二叉树(三)

701. 二叉搜索树中的插入操作 解题思路: 1. 模拟 ,如果 根节点为空 ,就用 插入值创建根节点 直接返回。否则, cur 从 根节点 开始,比较 当前节点的值和插入值的大小关系 : 1)如果 插入值 < cur ,就

路由器ipsec|vpn实验分析

AR1 和 AR2代表两个公司的出口&#xff0c;R2模拟互联&#xff0c;两个公司通信&#xff0c;通过ipsec vpn 加密隧道进行业务通信 切记&#xff1a;ipsec 路由器一定用AR系列&#xff0c;千万别用R&#xff0c;否则会给你惊喜 R2只有接口配ip&#xff0c;无任何配置&#xff…

手机数据恢复应用程序有哪些?手机数据恢复免费软件排名TOP 9

一些免费的手机数据恢复应用程序和软件有付费版本。 如果您想要高功能&#xff0c;请选择付费版本&#xff0c;如果您不想要那么多功能&#xff0c;或者如果您目前不需要它&#xff0c;请选择免费版本。 手机数据恢复免费软件排名TOP 9 ​1. 奇客数据恢复 ​奇客数据恢复是一款…

一文读懂GPTs的构建与玩法(GPTs保姆级教程)

Rocky Ding 公众号&#xff1a;WeThinkIn 写在前面 【WeThinkIn出品】栏目专注于分享Rocky的最新思考与经验总结&#xff0c;包含但不限于技术领域。欢迎大家一起交流学习&#x1f4aa; 大家好&#xff0c;我是Rocky。 本文将从“什么是GPTs”&#xff0c;“GPTs搭建流程”&am…

修改树莓派4b密码

修改树莓派4b密码&#xff0c;vnc viewer远程连接树莓派时忘记了密码&#xff0c;修改为新密码进行远程连接 sudo passwd pi 其中pi为所要修改密码的用户

LeetCode:1334. 阈值距离内邻居最少的城市(Floyd C++)

1334. 阈值距离内邻居最少的城市 链接&#xff1a; 1334. 阈值距离内邻居最少的城市 题目描述&#xff1a; 有 n 个城市&#xff0c;按从 0 到 n-1 编号。给你一个边数组 edges&#xff0c;其中 edges[i] [fromi, toi, weighti] 代表 fromi 和 toi 两个城市之间的双向加权边…

OpenCV的应用——快递二维码识别

OpenCV&#xff08;Open Source Computer Vision Library&#xff09;是一个开源的计算机视觉库&#xff0c;它提供了丰富的图像处理和计算机视觉算法&#xff0c;可用于实现图像识别、目标检测、图像分割等功能。在现代物流行业中&#xff0c;快递二维码识别是一项非常重要的任…

unity shaderGraph实例-可交互草地

效果展示 整体结构 各区域内容 区域1 计算交互用的cube和草各个顶点的距离 此处可以理解为&#xff0c;从cube的中心到草的顶点的距离&#xff0c;其距离是一个从0到整数的过程&#xff0c;如下图 区域2 将距离除以某个值&#xff0c;这个值是交互范围&#xff0c;相当于将白…

OpenAI暂停新的ChatGPT Plus注册 | OpenAI 的 GPT Builder 创建您的 GPTs

OpenAI DevDay 才过去仅仅一周时间&#xff0c;伴随着开发者大会上发布的一系列重磅升级和新特性&#xff0c;无疑这样的进化速度让广大网友炸锅了&#xff0c;其火热程度可见一斑。 就在四个小时前&#xff0c;OpenAI的CEO Sam Altma突然宣布&#xff0c;ChatGPT Plus账号暂停…

如何搭建属于自己的AI数字人直播SAAS系统?

随着人工智能技术的不断发展&#xff0c;AI数字人直播正成为互联网行业的新宠。面向未来的AI数字人直播系统无疑是直播领域的新风口。虽然拥有众多优势&#xff0c;但从0到1搭建这个系统可能存在着资源、技术和时间的挑战。那么&#xff0c;如何可以快速搭建属于自己的AI数字人…

周赛370(模拟、树形DP(正难则反)、树状数组优化DP)

文章目录 周赛370[2923. 找到冠军 I](https://leetcode.cn/problems/find-champion-i/)模拟 [2924. 找到冠军 II](https://leetcode.cn/problems/find-champion-ii/)统计入度 [2925. 在树上执行操作以后得到的最大分数](https://leetcode.cn/problems/maximum-score-after-appl…

用友NC及NC Cloud mxservlet反序列化漏洞复现

0x01 产品简介 用友NC是一款企业级ERP软件。作为一种信息化管理工具&#xff0c;用友NC提供了一系列业务管理模块&#xff0c;包括财务会计、采购管理、销售管理、物料管理、生产计划和人力资源管理等&#xff0c;帮助企业实现数字化转型和高效管理。 0x02 漏洞概述 用友NC及N…

小红书x-s、x-s-common算法研究与分析(仅供学习)

文章目录 1. 写在前面2. 参数分析2.1. x-s、x-t、x-s-common 1. 写在前面 最近花时间分析了一下xhs&#xff0c;研究的不深&#xff0c;也参考了网上许多开源出来的案例。简单记录一下&#xff0c;感兴趣的将就看一下吧&#xff01; 之前也研究过一段时间的某音&#xff0c;下…

VUE基础的一些总结

首先推荐观看VUE官方文档 目录 创建一个 Vue 应用 要创建一个 Vue 应用&#xff0c;你需要按照以下步骤操作&#xff1a; 步骤 1&#xff1a;安装 Node.js 和 npm 确保你的计算机上已经安装了 Node.js。你可以在 Node.js 官网 上下载并安装它。安装完成后&#xff0c;npm&…

io+day8

#ifndef __SEM2 #define __SEM3 4 //声明一个创>5 int init_sem(6 7 //声明一个p操8 int P(int sem9 10 //声明一个v操11 int W(int sem12 13 //声明一个删>14 int del_sem(i15 16 #endif 1 #include <myhead.h> …

【Python 千题 —— 基础篇】列表的最大值与最小值(for 循环版)

题目描述 题目描述 输出列表的最大值与最小值。题中有一个包含数字的列表 [11, 39, 100, 48, 392, 10, 9]&#xff0c;使用 for 循环输出这个列表的最大值与最小值。 输入描述 无输入。 输出描述 输出列表的最大值与最小值。 示例 示例 ① 输出&#xff1a; 列表的最…

【GitLab】-HTTP 500 curl 22 The requested URL returned error: 500~SSH解决

写在前面 本文主要介绍通过SSH的方式拉取GitLab代码。 目录 写在前面一、场景描述二、具体步骤1.环境说明2.生成秘钥3.GitLab添加秘钥4.验证SSH方式4.更改原有HTTP方式为SSH 三、参考资料写在后面系列文章 一、场景描述 之前笔者是通过 HTTP Personal access token 的方式拉取…