【CMake 入门与进阶(1)】一个例子搞懂什么是CMakeLists——从“Hello World”开始(附代码)

        在前面两篇内容中,我们编写了很多示例程序,但这些示例程序都只有一个.c 源文件,非常简单。因此,编译这些示例代码其实都非常简单,直接使用 GCC 编译器编译即可,连 Makefile 都不需要。但是,在实际的项目中,并非如此简单,一个工程中可能包含几十、成百甚至上千个源文件,这些源文件按照其类型、功能、模块分别放置在不同的目录中;面对这样的一个工程,通常会使用 make 工具进行管理、编译,make 工具依赖于 Makefile 文件,通过 Makefile 文件来定义整个工程的编译规则,使用 make 工具来解析 Makefile 所定义的编译规则。

        Makefile 带来的好处就是——“自动化编译”,一旦写好,只需要一个 make 命令,整个工程完全按照 Makefile 文件定义的编译规则进行自动编译,极大的提高了软件开发的效率。大都数的 IDE 都有这个工具, 譬如 Visual C++的 nmake、linux 下的 GNU make、Qt 的 qmake 等等,这些 make 工具遵循着不同的规范和标准,对应的 Makefile 文件其语法、格式也不相同,这样就带来了一个严峻的问题:如果软件想跨平台,必须要保证能够在不同平台下编译,而如果使用上面的 make 工具,就得为每一种标准写一次 Makefile,这将是一件让人抓狂的工作。

        而 cmake 就是针对这个问题所诞生,允许开发者编写一种与平台无关的 CMakeLists.txt 文件来制定整个工程的编译流程,再根据具体的编译平台,生成本地化的 Makefile 和工程文件,最后执行 make 编译。

        因此,对于大多数项目,我们应当考虑使用更自动化一些的 cmake 或者 autotools 来生成 Makefile,而不是直接动手编写 Makefile。

        本专栏我们便来学习 cmake,也是作为我们项目编程的起点。

cmake 简介

        cmake 是一个跨平台的自动构建工具,前面导语部分也已经给大家介绍了,cmake 的诞生主要是为了解决直接使用 make+Makefile 这种方式无法实现跨平台的问题,所以 cmake 是可以实现跨平台的编译工具, 这是它最大的特点,当然除了这个之外,cmake 还包含以下优点:

  • 开放源代码 我们可以直接从 cmake 官网 https://cmake.org/下载到它的源代码;
  • 跨平台 cmake 并不直接编译、构建出最终的可执行文件或库文件,它允许开发者编写一种与平台 无关的 CMakeLists.txt 文件来制定整个工程的编译流程,cmake 工具会解析 CMakeLists.txt 文件语法规则,再根据当前的编译平台,生成本地化的 Makefile 和工程文件,最后通过 make 工具来编译整个工程;所以由此可知,cmake 仅仅只是根据不同平台生成对应的 Makefile,最终还是通过 make 工具来编译工程源码,但是 cmake 却是跨平台的。
  • 语法规则简单 Makefile 语法规则比较复杂,对于一个初学者来说,通常并不那么友好,并且 Makefile 语法规则在不同平台下往往是不一样的;而 cmake 依赖的是 CMakeLists.txt 文件,该文件的语法规则与平台无关,并且语法规则简单、容易理解!cmake 工具通过解析 CMakeLists.txt 自动帮我们生成 Makefile,这样就不需要我们自己手动编写 Makefile 了。

cmake 和 Makefile

        直观上理解,cmake 就是用来产生 Makefile 的工具,解析 CMakeLists.txt 自动生成 Makefile:

         除了 cmake 之外,还有一些其它的自动构建工具,常用的譬如 automake、autoconf 等,有兴趣的朋友可以自己了解下。

cmake 的使用方法

        cmake 就是一个工具命令,在 Ubuntu 系统下通过 apt-get 命令可以在线安装,如下所示:

sudo apt-get install cmake

         安装完成之后可以通过 cmake --version 命令查看 cmake 的版本号,如下所示:

         由上图可知,当前系统安装的 cmake 对应的版本号为 3.5.1,cmake 工具版本更新也是比较快的,从官网CMake可知,cmake 最新版本为 3.22.0,不过这都没关系,其实使用哪个版本都是可以的,差别并不会太大,所以这个大家不用担心。

        安装完 cmake 工具之后,接着我们就来学习如何去使用 cmake。cmake 官方也给大家提供相应教程,链接地址如下所示:

Documentation | CMake                                                       //文档总链接地址       

CMake Tutorial — CMake 3.26.4 Documentation                //培训教程

         如果大家自学能力强,完全可以参考官方提供的培训教程学习 cmake;对于 cmake 的学习,笔者给大家两个建议:

  • 从简单开始、再到复杂!
  • 重点是自己动手多练习。

        本文我们将从一个非常简单的示例开始向大家介绍如何使用 cmake,再从这个示例进一步扩展、提出更多需求,来看看 cmake 如何去满足这些需求。

示例:单个源文件编译

        单个源文件的程序通常是最简单的,一个经典的 C 程序“Hello World”,如何用 cmake 来进行构建呢?        

//main.c
#include <stdio.h>

int main(){
    printf("Hello World!\n");
    return 0;
}

        现在我们需要新建一个CMakeLists.txt文件,CMakeLists.txt文件会被cmake工具解析,就好比是Makefile文件会被make工具解析一样;CMakeLists.txt创建完成后,在文件中写入如下内容:

project(HELLO)
add_executable(hello ./main.c)

        写入完成之后,保存退出,当前工程目录结构如下所示:

├── CMakeLists.txt
└── main.c

        在我们的工程目录下有两个文件,源文件 main.c 和 CMakeLists.txt,接着我们在工程目录下直接执行 cmake 命令,如下所示:

cmake ./

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

         执行完 cmake 之后,除了源文件 main.c 和 CMakeLists.txt 之外,可以看到当前目录下生成了很多其它的文件或文件夹,包括:CMakeCache.txt、CmakeFiles、cmake_install.cmake、Makefile,重点是生成了这个 Makefile 文件,有了 Makefile 之后,接着我们使用 make工具编译我们的工程,如下所示:

        通过make编译之后得到了一个可执行文件 hello,这个名字是在 CMakeLists.txt 文件中指定的,稍后向大家介绍。通过 file 命令可以查看到 hello 是一个 x86-64 架构下的可执行文件,所以只能在我们的 Ubuntu PC 上运行:

        为了验证 hello 可执行文件运行结果是否与源代码相同,我们直接在 Ubuntu 下运行即可,如下所示:

CMakeLists.txt 文件

        上面我们通过了一个非常简单例子向大家演示了如何使用 cmake,重点在于去编写一个 CMakeLists.txt 文件,现在来看看 CMakeLists.txt 文件中写的都是什么意思。 

        ⚫ 第一行 project(HELLO)

        project 是一个命令,命令的使用方式有点类似于 C 语言中的函数,因为命令后面需要提供一对括号, 并且通常需要我们提供参数,多个参数使用空格分隔而不是逗号“,”。

        project 命令用于设置工程的名称,括号中的参数 HELLO 便是我们要设置的工程名称;设置工程名称并不是强制性的,但是最好加上。

        ⚫ 第二行 add_executable(hello ./main.c)

        add_executable 同样也是一个命令,用于生成一个可执行文件,在本例中传入了两个参数,第一个参数表示生成的可执行文件对应的文件名,第二个参数表示对应的源文件;所以 add_executable(hello ./main.c)表示需要生成一个名为 hello 的可执行文件,所需源文件为当前目录下的 main.c。

        使用 out-of-source 方式构建

        在上面的例子中,cmake 生成的文件以及最终的可执行文件 hello 与工程的源码文件 main.c 混在了一起,这使得工程看起来非常乱,当我们需要清理 cmake 产生的文件时将变得非常麻烦,这不是我们想看到的;我们需要将构建过程生成的文件与源文件分离开来,不让它们混杂在一起,也就是使用 out-of-source 方式构建。

        将 cmake 编译生成的文件清理下,然后在工程目录下创建一个 build 目录,如下所示:

├── build
├── CMakeLists.txt
└── main.c

         然后进入到 build 目录下执行 cmake:

cd build/
cmake ../
make

         这样 cmake 生成的中间文件以及 make 编译生成的可执行文件就全部在 build 目录下了,如果要清理工程,直接删除 build 目录即可,这样就方便多了,如下图所示。

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

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

相关文章

Qt概述和项目文件介绍

注意&#xff1a;学习本专栏的内容需要了解C相关知识&#xff0c;会涉及到C基础语法和相关特性&#xff0c;可以参考我的另一个专栏 c从零开始_小梁今天敲代码了吗的博客-CSDN博客 目录 一.什么是Qt 二.Qt的案例 三.项目文件介绍 一.什么是Qt 是一个跨平台的 C 应用程序…

运维小白必学篇之基础篇第一集:Linux相关命令实验

Linux相关命令实验 实验者&#xff1a;胡 阳 命令提示符 【rootlocalhost ~】# 【当前登录系统的用户主机名 当前工作目录】提示符 &#xff08;# 表示 管理员&#xff09; &#xff08;&#xff04; 表示 普通用户&#xff09; 基本格式&#xff1a;命令 【选项】 【…

CSDN铁粉攻略

欢迎关注博主 Mindtechnist 或加入【Linux C/C/Python社区】一起学习和分享Linux、C、C、Python、Matlab&#xff0c;机器人运动控制、多机器人协作&#xff0c;智能优化算法&#xff0c;滤波估计、多传感器信息融合&#xff0c;机器学习&#xff0c;人工智能等相关领域的知识和…

Linux多Reactor多线程网络模型

多Reactor多线程网络模型是一种用于构建高性能网络应用的并发模型。它基于事件驱动的思想&#xff0c;通过使用多个Reactor线程和多个工作线程来处理并发的网络请求。 底层调用关系&#xff1a; 在多Reactor多线程网络模型中&#xff0c;通常会有一个主Reactor线程和多个工作线…

【软件测试基础】

&#x1f389;&#x1f389;&#x1f389;点进来你就是我的人了博主主页&#xff1a;&#x1f648;&#x1f648;&#x1f648;戳一戳,欢迎大佬指点! 欢迎志同道合的朋友一起加油喔&#x1f93a;&#x1f93a;&#x1f93a; 目录 1、什么是软件测试(CASE) 1.1 软件测试就是验…

FPGA采集CameraLink相机Full模式解码输出,附带工程源码和技术支持

目录 1、前言2、CameraLink协议基础3、目前我已有的CameraLink收发工程4、设计方案输入CameraLink相机视频缓存视频输出软件配置 5、vivado工程详解6、上板调试验证7、福利&#xff1a;工程代码的获取 1、前言 FPGA实现CameraLink视频编解码目前有两种方案&#xff1a; 一是使…

MyBatis 所有的 jdbcType类型

MyBatis处理MySQL字段类型date与datetime 1&#xff09; DATETIME 显示格式&#xff1a;yyyy-MM-dd HH:mm:ss 时间范围:[ 1000-01-01 00:00:00到9999-12-31 23:59:59]2&#xff09; DATE 显示格式&#xff1a;yyyy-MM-dd 时间范围&#xff1a;[1000-01-01到9999-12-31]3&#…

Unity游戏优化指南大全(持续更新中!)

Unity游戏优化指南大全 三个官方优化提示&#xff1a; 性能和优化 (Performance and Optimization) - 关于性能分析器以及性能和优化技巧的 Unity 学习教程。Best practices for performance optimization in Unity - 优化应用程序的最佳实践指南。Ultimate guide to profili…

【蓝桥刷题】备战国赛——区间修改、区间查询

蓝桥杯线段树模板题——区间修改、区间查询 &#x1f680; 每日一题&#xff0c;冲刺国赛 &#x1f680; 题目导航&#xff1a; 区间修改、区间查询 &#x1f387;思路&#xff1a;线段树 &#x1f531;思路分析&#xff1a; 本题涉及到了对区间操作的问题&#xff0c;因此&a…

软件测试目的是什么?软件测试公司可提供哪些测试服务类型?

随着科技的不断发展&#xff0c;软件行业的发展也越来越迅速。然而&#xff0c;随着软件的增多和复杂性的提高&#xff0c;开发者们需要更多的手段来确保软件质量。软件测试就是通过一系列的测试来发现软件的问题&#xff0c;从而提高软件的质量。 一、软件测试目的是什么? …

【敬伟ps教程】蒙版和通道的基础知识

文章目录 通道通道面板 Alpha 通道通道和选区的关系编辑 Alpha通道原色通道的利用 图层蒙版编辑图层蒙版快速蒙版 通道 通道是图像文件的一种颜色数据信息存储形式&#xff0c;它与图像文件的颜色模式密切相关 多个分色通道(如图:红R、绿G、蓝B)叠加在一起可以组成一幅具有颜…

【UE】制作追踪导弹

效果 步骤 1. 首先在虚幻商城下载所需素材 2. 打开“BP_West_Missile_M26” 勾选模拟物理 添加一个变量&#xff0c;命名为“Target” 该变量用来表示导弹追踪的目标&#xff0c;变量类型为actor的对象引用&#xff0c;勾选可编辑实例和生成时公开 在事件图表中添加如下节点 3…

【JavaSE】Java基础语法(二十七):Set集合和 TreeSet

文章目录 1. Set集合1.1Set集合概述和特点【应用】1.2Set集合的使用【应用】 2.TreeSet集合2.1TreeSet集合概述和特点【应用】2.2TreeSet集合基本使用【应用】2.3自然排序Comparable的使用【应用】2.4比较器排序Comparator的使用【应用】2.4两种比较方式总结 1. Set集合 1.1Se…

CNNs和视觉Transformer:分析与比较

探索视觉Transformer和卷积神经网络&#xff08;CNNs&#xff09;在图像分类任务中的有效性。 图像分类是计算机视觉中的关键任务&#xff0c;在工业、医学影像和农业等各个领域得到广泛应用。卷积神经网络&#xff08;CNNs&#xff09;是该领域的一项重大突破&#xff0c;被广…

springboot+vue高校班级管理系统 java 同学录校友录网站

本海滨学院班级回忆录管理员功能有个人中心&#xff0c;用户信息管理&#xff0c;班委信息管理&#xff0c;班级信息管理&#xff0c;加入班级管理&#xff0c;新闻信息管理&#xff0c;班级相册管理&#xff0c;活动信息管理&#xff0c;捐赠信息管理&#xff0c;论坛信息管理…

司空见惯 - 使用dBm表示功率的各种现实情况

前面一篇文章介绍过&#xff0c;使用dBm表示功率时&#xff0c;如何转换为mW。 那现实世界的实际情况中&#xff0c;使用dBm来表示电磁波的能量强度&#xff0c;列表如下&#xff1a; Power level Power Notes 526 dBm 3.61049 W 黑洞碰撞后的引力波辐射的功率&#xff0c…

Linux上安装jdk Tomcat mysql redis

1.安装JDk 1.1这里使用xshell中xfxp进行文件的上传&#xff0c;将jdk二进制包上传到Linux服务器上 下载地址&#xff1a;Java Downloads | Oracle 或者这里有下载好的安装包&#xff1a;链接&#xff1a;https://pan.baidu.com/s/1ZSJxBDzDaTwCH2IG-d2Gig 提取码&#xff1a;…

ChatGPT报错:Sorry, you have been blocked解决方法

今天打开ChatGPT&#xff0c;发现再一次报错了&#xff01; 又一次出问题了。。。。。。。无语&#xff01; 原因分析 1、内容过滤&#xff1a;某些平台或网站可能使用内容过滤系统&#xff0c;该系统可能将AlI语言模型视为潜在的风险&#xff0c;从而对其进行封锁或限制。这…

【Springboot】集成百度地图实现定位打卡功能

目录 第一章 需求分析 第二章 概要设计 第三章 详细设计 3.1 环境搭建 3.1.1 获取百度地图ak 3.1.2 创建springboot项目 3.2 配置application.properties 3.3 配置pox.xml 3.4 创建定位接口 3.5 创建前端页面 3.6 映射静态文件 第一章 需求分析 如图&#xff0c;当…

Redis数据类型之列表List

Redis数据类型之列表List list中的命令如下&#xff1a; lpush&#xff1a;从左边插入&#xff0c;插入的数据是倒叙 LPUSH key value1 [value2] 将一个或多个值插入到列表头部 lpush k1 a b c d e f ; 输出结果 f e d c b a lpop k1; 输出 f 从左边pop弹出时先弹出的是f&…