cmake简单使用

简介

理论上,任意一个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.mfbz.cn/a/151349.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Python数据容器通用操作

通用操作 1.数据容器可以从以下视角进行简单的分类2.数据容器特点对比3.数据容器的通用操作4.功能总览5.字符串大小比较 1.数据容器可以从以下视角进行简单的分类 是否支持下标索引 支持&#xff1a;列表、元组、字符串 --序列类型不支持&#xff1a;集合、字典 --非序列类型 …

【C++干货铺】解密vector底层逻辑

个人主页点击直达&#xff1a;小白不是程序媛 C系列专栏&#xff1a;C干货铺 代码仓库&#xff1a;Gitee 目录 vector介绍 vector的使用 vector的定义和使用 vector的空间增长问题 vector的增删查改 解密vector及模拟实现 成员变量 成员函数 构造函数 拷贝构造函数…

分类预测 | Matlab实现PSO-LSTM-Attention粒子群算法优化长短期记忆神经网络融合注意力机制多特征分类预测

分类预测 | Matlab实现PSO-LSTM-Attention粒子群算法优化长短期记忆神经网络融合注意力机制多特征分类预测 目录 分类预测 | Matlab实现PSO-LSTM-Attention粒子群算法优化长短期记忆神经网络融合注意力机制多特征分类预测分类效果基本描述程序设计参考资料 分类效果 基本描述 1…

飞书开发学习笔记(七)-添加机器人及发送webhook消息

飞书开发学习笔记(七)-添加机器人及发送webhook消息 一.添加飞书机器人 1.1 添加飞书机器人过程 在群的右上角点击折叠按键…选择 设置 群机器人中选择 添加机器人 选择自定义机器人&#xff0c;通过webhook发送消息 弹出的信息中有webhook地址&#xff0c;选择复制。 安…

【Linux专题】SFTP 用户配置 ChrootDirectory

【赠送】IT技术视频教程&#xff0c;白拿不谢&#xff01;思科、华为、红帽、数据库、云计算等等https://xmws-it.blog.csdn.net/article/details/117297837?spm1001.2014.3001.5502 红帽认证 认证课程介绍&#xff1a;红帽RHCE9.0学什么内容&#xff0c;新版有什么变化-CSDN…

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

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

修改树莓派4b密码

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

Java 设计模式——中介者模式

目录 1.概述2.结构3.案例实现3.1.抽象中介类3.2.抽象同事类3.3.具体同事类3.4.具体中介类3.5.测试 4.优缺点5.使用场景 1.概述 &#xff08;1&#xff09;一般来说&#xff0c;同事类之间的关系是比较复杂的&#xff0c;多个同事类之间互相关联时&#xff0c;他们之间的关系会…

IDEA这样配置Maven:让你一遍就能学会!

一、安装Maven环境 1.1 下载并安装Maven Maven官网&#xff1a;http://maven.apache.org/download.cgi 建议放在非系统盘目录下&#xff0c;可在根目录新建&#xff08;D:/maven&#xff09;目录用于存放Maven&#xff0c;或者如图&#xff0c;路径中不要有中文。 1.2 配置M…

AIGC实战——变分自编码器(Variational Autoencoder, VAE)

AIGC实战——变分自编码器 0. 前言1. 变分自编码器1.1 基本原理1.2 编码器 2. 构建VAE编码器2.1 Sampling 层2.2 编码器2.3 损失函数2.4 训练变分自编码器 3. 变分自编码器分析小结系列链接 0. 前言 我们已经学习了如何实现自编码器&#xff0c;并了解了自编码器无法在潜空间中…

轻量封装WebGPU渲染系统示例<33>- 单精度浮点纹理(源码)

在WebGPU中创建纹理使用纹理很方便&#xff0c;只是js中只有Float32Array而默认不支持Float16Array&#xff0c;所以略微费点事。不过网上的大神多的是&#xff0c;摇摇小手就能获得解决方案。 废话多了容易挨胖揍&#xff0c;看代码。 js中float16单精度float数值转换: // …

[C/C++] 数据结构 链表OJ题:相交链表(寻找两个链表的相交起始结点)

题目描述: 给你两个单链表的头节点 headA 和 headB &#xff0c;请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点&#xff0c;返回 null 。 图示两个链表在节点 c1 开始相交&#xff1a; 题目数据 保证 整个链式结构中不存在环。 注意&#xff0c;函数返…

JSP 购物商城系统eclipse定制开发mysql数据库BS模式java编程servlet

一、源码特点 java 购物商城系统是一套完善的web设计系统 系统采用serlvetdaobean 模式开发&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模 式开发。开发环境为TOMCAT7.0,eclipse开发&#xff0c;数…

CentOS停更在即,国内厂商该如何应对?KeyarchOS X2Keyarch 迁移体验

一、CentOS 停更危机二、关于浪潮信息KeyarchOS三、浪潮信息 KeyarchOS License 应用迁移实践第一步&#xff1a;迁移前验证第二步&#xff1a;迁移第三步&#xff1a;迁移后验证 四、写在最后 一、CentOS 停更危机 自 1993 年开始&#xff0c;红帽 Linux 已经陪伴开发者们走过…

荧光量子效率积分球检测薄膜需要注意什么

荧光量子效率积分球是一种特殊的积分球&#xff0c;它可以用于测量荧光材料在特定波长下的荧光量子效率。它由一个具有高朗伯特性的漫反射材料制成&#xff0c;具有高达99%的反射率和朗伯特性。荧光量子效率积分球的使用方法包括将样品放置在积分球的样品口中&#xff0c;调整激…

【C++高阶(二)】熟悉STL中的map和set --了解KV模型和pair结构

&#x1f493;博主CSDN主页:杭电码农-NEO&#x1f493;   ⏩专栏分类:C从入门到精通⏪   &#x1f69a;代码仓库:NEO的学习日记&#x1f69a;   &#x1f339;关注我&#x1faf5;带你学习C   &#x1f51d;&#x1f51d; map和set 1. 前言2. map和set介绍3. pair结构介…

JWT登录认证(1登录)

JwtUtil package com.lin.springboot01.utils; import com.auth0.jwt.JWT; import com.auth0.jwt.algorithms.Algorithm; import java.util.Date; import java.util.Map;public class JwtUtil {private static final String KEY "liner2332";//接受业务数据&#xf…

Python in Visual Studio Code 2023年11月发布

排版&#xff1a;Alan Wang 我们很高兴地宣布 Visual Studio Code 的 Python 和 Jupyter 扩展将于 2023 年 11 月发布&#xff01; 此版本包括以下公告&#xff1a; 改进了使用 Shift Enter 在终端中运行当前行弃用内置 linting 和格式设置功能对 Python linting 扩展的改进重…

linux安装nginx并配置服务的详细步骤

文章目录 依赖安装安装gcc环境安装 pcre安装zlib安装openssl 安装Nginx在nginx官网下载安装包将安装包上传linux解压文件手动创建用户和用户组编译目录编译源码并安装启动查看进程 设置nginx服务并开机自启 依赖安装 nginx安装前需要一些依赖&#xff0c;如果已经安装了则忽略…

大数据Doris(二十三):取消导入与其他导入案例参考

文章目录 取消导入与其他导入案例参考 一、取消导入
最新文章