必读干货|使用Cmake管理C++项目简明教程

news2025/2/6 17:25:47

一、背景

Cmake是 kitware公司以及一些开源开发者在开发几个工具套件(VTK)的过程中衍生品,最终形成体系,成为一个独立的开源项目。其官方网站是 cmake.org,可以通过访问官方网站获得更多关于cmake的信息。

它是一个跨平台的编译(Build)工具,可以用简单的语句来描述所有平台的编译过程。CMake能够输出makefile文件,然后系统会根据这个makefile文件内容编译整个工程。

图1 kitware公司和Cmake套件

软件开发有以下三个步骤:

1.编译源代码;

2.链接到其他库;

3.将应用程序打包为库或二进制文件。

假如我们有一个大型的C++项目,由非常多的互相调用的工程共同组成,一些用于生成库文件,一些用于实现逻辑功能。他们之间的调用关系复杂而严格,如果想在这样复杂的框架下进行二次开发,显然只拥有它的源码是远远不够的,还需要清楚的明白这几十个项目之间的复杂关系。即使是原作者给出了相关的结构文档,对新手来说建立工程的过程依旧是漫长而艰辛的,开发人员的核心业务是软件开发,而不是软件构建。Cmake目的是实现软件构建流程的自动化,并且是跨平台的。

原作者只需要生成一份CMakeLists.txt文档,框架的使用者们只需要在下载源码的同时下载作者提供的CMakeLists.txt,就可以利用CMake,在原作者的帮助下进行工程的搭建。Cmake编写的过程实际上是编程的过程,不过你需要编写的是 CMakeLists.txt(一般情况下每个目录一个),使用的是“Cmake”语言和语法。

刚入门的开发者拿到Cmakelist看着一脸雾水,里面众多的语法指令不知道是什么含义甚至不能自己修改,本文接下来将介绍Cmakelist的各种重要的变量、指令、语句及其作用。

图2 Cmake的构建流程

二、安装

大多数Linux的操作系统会在系统中直接包含,不必手动安装。其他操作系统,比如:Windows或者某些Linux系统,可以从Cmake官网上下载安装包进行安装:cmake.org/HTML/Download。安装步骤省略,可以借鉴网上其他资料。

三、使用

因为cmake会生成一些中间文件(CMakeFiles,CMakeCache.txt, cmake_install.cmake, Makefile),所以最好在项目源代码目录重新建一个文件夹存放生成的中间文件,即外部编译。在中间文件夹中依次执行编译指令cmake ..,make,那么编译器会按照生成的Makefile中的指令编译C++工程。如果要对编译的结果清理,使用make clean 指令即可。在 Windows 上,还可以使用 CMakeSetup (GUI)进行工程构建。

make install命令将编译好的目标文件默认直接安装到/usr/local目录,如果想安装到其他目录,可以使用make install DESTDIR=< install_path >。

本文接下来介绍Cmakelist的编写方法,这是开发者最关心的地方。Cmakelist编写指令时不区分大小写,为了统一风格,本文使用大写字母。

四、基础指令

要编译非常简单的C++工程,工程不依赖第三方库,那么Cmakelist中至少包含以下内容:

#声明要求的最低Cmake版本

CMAKE_MINIMUM_REQUIRED(VERSIN 2.8)

#Cmake工程名。这个指令隐式的定义了两个 cmake变量: PROJECT_BINARY_DIR以及PROJECT_SOURCE_DIR。分别指向项目的编译路径和工程路径。

PROJECT (HELLO)

#生成可执行文件,${}来引用变量。

ADD_EXECUTABLE(Executable program name ${ Source files })

到这里,一个可执行程序就生成了。如果要管理依赖第三方库的工程,就需要加入一些额外指令。除此之外,还有一些Cmake中重要的变量和语句需要掌握,才能使用起来得心应手。在下面列出:

五、重要的变量

#Cmake版本

CMAKE_SYSTEM_VERSION

#可执行文件的输出路径

EXECUTABLE_OUTPUT_PATH

#库文件输出路径

LIBRARY_OUTPUT_PATH

#安装路径

CMAKE_INSTALL_PREFIX

Note:该变量可以在Cmakelist中显式地定义,即:SET(CMAKE_INSTALL_PREFIX < install_path >);也可以作为命令行参数传递:cmake -DCMAKE_INSTALL_PREFIX=< install_path > ;还可以在cmake完成后使用make install DESTDIR=< install_path >指定安装路径。

#工程编译时存放二进制文件的目录。

CMAKE_BINARY_DIR

#将添加的头文件搜索路径放在已有路径的前面。

CMAKE_INCLUDE_DIRECTORIES_BEFORE

#将添加的头文件搜索路径放在已有路径的后面。

CMAKE_INCLUDE_DIRECTORIES_ AFTER

#工程顶层目录

CMAKE_SOURCE_DIR

#定义自己的 cmake模块所在的路径

CMAKE_MODULE_PATH

#控制库的默认编译方式

BUILD_SHARED_LIBS

#设置 C++/C的编译选项,也可以通过指令 ADD_DEFINITIONS()添加

CMAKE_CXX_FLAGS/ CMAKE_CXX_FLAGS

Note:该指令非常重要,因为它能选择C++/C工程的编译器行为。有时候我们依赖的第三方库的编译方式与自己项目的编译方式不一致时,编译会通过,但是运行时出现非常隐蔽的bug。此时就需要检查,项目中各种库的编译行为是否一致。

# 设置构建类型,类型选项有Debug/Release。当使用GDB调试工程时要使用Debug选项。该变量可以通过命令行:cmake ­DCMAKE_BUILD_TYPE=Release或指令SET(CMAKE_BUILD_TYPE [type])设置。

CMAKE_BUILD_TYPE

六、重要的指令和语句

#查看Cmake生成的详细编译信息,相当于执行make VERBOSE=1。当构建失败并且需要找出原因时使用该条指令非常有帮助。

SET(CMAKE_VERBOSE_MAKEFILE on )

#显式的为变量赋值,非常重要

SET(VAR [VALUE] [CACHE TYPE DOCSTRING [FORCE]])

#用来寻找第三方库的Find<name>.cmake模块,该模块里提供了库的头文件路径和库文件路径。如果找不到,通过设置 CMAKE_MODULE_PATH 变量来告诉 Cmake 在哪里找到它。

FIND_PACKAGE(<name> [major.minor] [QUIET] [NO_MODULE] [[REQUIRED|COMPONENTS] [componets...]])

Note:编译一个链接第三方库的软件时,我们需要知道该库的头文件路径、库文件路径、要链接的库的文件名。使用第三方库时必须在Cmakelist中提供这些信息。

#向终端输出用户定义的信息,显示状态信息、警告或错误。包含了三种类型:SEND_ERRO、SATUS、FATAL_ERROR。

MESSAGE([SEND_ERROR | STATUS | FATAL_ERROR] "message to display"...)

例:MESSAGE(STATUS "This is SOURCE dir "${HELLO_SOURCE_DIR})

#添加可执行文件

ADD_EXECUTABLE(<name> IMPORTED [GLOBAL])

#向当前工程添加存放源文件的子目录,并指定中间二进制和目标二进制存放的位置。

ADD_SUBDIRECTORY(source_dir [binary_dir] )

#生成库。生成的库的类型有三种:SHARED,动态库;STATIC,静态库;MODULE,在使用 dyld的系统有效。

ADD_LIBRARY(libname [SHARED|STATIC|MODULE] [EXCLUDE_FROM_ALL] source1 source2 ... sourceN)

#设置输出目标的属性

SET_TARGET_PROPERTIES(target1 target2 ...PROPERTIES prop1 value1 prop2 value2 ...)

例:设置目标库的名称:SET_TARGET_PROPERTIES(taget_name PROPERTIES OUTPUT_NAME "hello")

#设置动态库的版本号,VERSION指代动态库版本,SOVERSION指代 API版本。

SET_TARGET_PROPERTIES(hello PROPERTIES VERSION 1.2 SOVERSION 1)

#向工程添加多个特定的头文件搜索路径。系统默认的头文件路径是/usr/include和/usr/local/include,如果不是,需要在Cmakelist中显式的定义。

INCLUDE_DIRECTORIES([AFTER|BEFORE] [SYSTEM] dir1 dir2 ...)

#将目标文件链接到第三方库,非常重要的语句

TARGET_LINK_LIBRARIES(target library1<debug | optimized> library2...)

#在指定路径中搜索文件名,指定路径指的是环境变量CMAKE_INCLUDE_PATH中包含的所有路径。

FIND_PATH(filename)

#向 C/C++编译器添加-D定义。修改预处理器设置

ADD_DEFINITIONS()

#定义 target依赖的其他 target,确保在编译本 target之前,其他的 target已经被构建

ADD_DEPENDENCIES()

#搜索一个目录下所有的源代码文件并将列表存储在一个变量,可以与ADD_EXECUTABLE连用。

AUX_SOURCE_DIRECTORY(. SRC_LIST)

ADD_EXECUTABLE(main ${SRC_LIST})

#if语句, 如果表达式内容不是:空,0,N, NO, OFF, FALSE, NOTFOUND或<var>_NOTFOUND时,表达式为真。

IF(expression)

…..

ELSE(expression)

…..

ENDIF(expression)

#列表变量遍历语句

FOREACH(loop_var)

...

ENDFOREACH(loop_var)

#while语句

WHILE(condition)

...

ENDWHILE(condition)

本文提到的变量、语句、指令包含了Cmakelist编写时最常见、最重要的部分,编写Cmake的过程其实就是编程的过程。

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

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

相关文章

【大数据存储技术】「#3」将数据从Hive导入到MySQL

文章目录准备工作安装Hive、MySQL和SqoopHive预操作启动MySQL、hadoop、hive创建临时表inner_user_log和inner_user_info使用Sqoop将数据从Hive导入MySQL启动hadoop集群、MySQL服务将前面生成的临时表数据从Hive导入到 MySQL 中查看MySQL中user_log或user_info表中的数据准备工…

网页爬虫的本质

1.网页结构分析 提取其中一部分核心介绍 &#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Title</title> </head> <body> <div class"item masonry-brick&quo…

数据管理篇之计算管理

第13章 计算管理 目的&#xff1a;降低计算资源的消耗&#xff0c;提高任务执行的性能&#xff0c;提升任务产出的时间。 1.系统优化 HBO HBO &#xff08;History-Based Optimizer&#xff0c;基于历史的优化&#xff09;是根据任务历史执行情况为任务分配更合理的资源&…

在霍格沃兹测试开发学社学习是种怎样的体验?

霍格沃兹我怎么了解到的 我是河北某二本院校软工专业的学生&#xff0c;大三开始学校来了很多宣讲和实训的公司&#xff0c;都是为我们以后的职业发展做参考。学校有软件测试课程&#xff0c;有一次老师无意提到了霍格沃兹测试开发学社举办的高校“火焰杯”知识竞赛&#xff0…

三角函数sin cos tan和弧度,度等定义及其相关

在此做一个温习及记录&#xff0c;做一个总结&#xff0c;免得到处找。 正弦、余弦和正切是 三角法 里的主要函数&#xff0c;它们是基于一个 直角三角形而建立的。 英文释义&#xff1a; 正弦 &#xff08;sine&#xff09;, 余弦 &#xff08;cosine&#xff09; 和 正切 &a…

毕业设计 单片机心率血氧健康监测手表 - 物联网 嵌入式

文章目录0 前言1 简介2 主要器件3 实现效果4 设计原理4.1 **硬件准备**4.2 **传感器和算法**5 部分核心代码5 最后0 前言 &#x1f525; 这两年开始毕业设计和毕业答辩的要求和难度不断提升&#xff0c;传统的毕设题目缺少创新和亮点&#xff0c;往往达不到毕业答辩的要求&…

VRRP负载均衡模式配置实用吗?

在前面的文章中&#xff0c;我们知道了VRRP单备份组可以快速实现主备切换&#xff08;&#xff09;&#xff0c;轻轻松松将业务中断时间压缩到1秒钟以内&#xff1b;也对比测试了策略路由进行主备切换的过程&#xff08;&#xff09;&#xff0c;虽然能轻松实现主备设备之间的流…

计算机毕业设计php基本微信小程序的贵小团校园社团小程序

项目介绍 随着信息技术和网络技术的飞速发展,人类已进入全新信息化时代,传统管理技术已无法高效,便捷地管理信息。为了迎合时代需求,优化管理效率,各种各样的管理系统应运而生,各行各业相继进入信息管理时代,贵小团校园社团小程序就是信息时代变革中的产物之一。 任何系统都要遵…

计算机毕业设计django基于Python在线酒店管理系统

项目介绍 21世纪的今天,随着社会的不断发展与进步,人们对于信息科学化的认识,已由低层次向高层次发展,由原来的感性认识向理性认识提高,管理工作的重要性已逐渐被人们所认识,科学化的管理,使信息存储达到准确、快速、完善,并能提高工作管理效率,促进其发展。 论文主要是对在线…

Java面试--SpringBoot启动流程

一、SpringBoot是什么 SpringBoot 是依赖于 Spring 的&#xff0c;比起 Spring&#xff0c;除了拥有 Spring 的全部功能以外&#xff0c;SpringBoot 无需繁琐的 Xml 配置&#xff0c;这取决于它自身强大的自动装配功能&#xff1b;并且自身已嵌入Tomcat、Jetty 等 web 容器&am…

C. Another Array Problem(思维)

Problem - C - Codeforces 给你一个有n个整数的数组a。允许你对它进行以下操作&#xff0c;次数不限&#xff08;0次或更多&#xff09;。 选择2个指数i,j&#xff0c;其中1≤i<j≤n&#xff0c;用|ai-aj|替换所有i≤k≤j的ak。 打印最终数组中所有元素的最大和&#xff0c…

TensorFlow之回归模型-1

1 基本概念 回归模型 一个回归模型会生成一个数值类型的预测结果&#xff0c;而一个分类模型会生成一个分类类型的预测结果&#xff0c;例如&#xff0c;如下列举一些回归模型&#xff1a; 一个模型预测一个商品房的价格走向&#xff0c;例如&#xff0c;某个时间点的总体市场…

大一学生《Web编程基础》HTML实例网页代码 HTML+CSS+JS 黑色横排的个人主页作品

&#x1f389;精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业…

【MySQL】-事务以及隔离性问题

作者&#xff1a;学Java的冬瓜 博客主页&#xff1a;☀冬瓜的主页&#x1f319; 专栏&#xff1a;【MySQL】 分享&#xff1a;落霞与孤鹜齐飞&#xff0c;秋水共长天一色。——《滕王阁序》 主要内容&#xff1a;事务的概念&#xff0c;代码使用&#xff0c;事务的四大性质、隔…

Shell是运维人员必须掌握的技能

文章目录Shell是运维人员必须掌握的技能Shell、Python 和 Perl1) Perl 语言2) Python 语言3) ShellShell是运维人员必须掌握的技能 Linux 运维人员就是负责 Linux 服务器的运行和维护。随着互联网的爆发&#xff0c;Linux 运维在最近几年也迎来了春天&#xff0c;出现了大量的…

Stm32标准库函数4——BlueTooth采集串口AD数据发送给电脑或者单片机

#include "stm32f10x.h" //在该头文件中默认定义系统时钟为72M #include "delay.h" #include "sys.h" #include "usart.h" #include "adc.h" //将USB转串口模块的Txd引脚电平通过蓝牙模块传送到单片机Rxd&#xff1b;同时…

Linux编辑器-vim的使用

vi/vim的区别简单点来说&#xff0c;它们都是多模式编辑器&#xff0c;不同的是vim是vi的升级版本&#xff0c;它不仅兼容vi的所有指令&#xff0c;而且还有一些新的特性在里面。例如语法加亮&#xff0c;可视化操作不仅可以在终端运行&#xff0c;也可以运行于xwindow、 mac o…

Unity Addressables资源管理 分析器 AnalyzeRule

Addressables资源管理总目录 0.窗口位置 打开的窗口 1.Fixable Rules 可修复的规则 1.1 Check Duplicate Bundle Dependencies 检查重复的Bundle依赖项 此规则通过扫描所有使用BundledAssetGroupSchemas的组&#xff0c; 并投影asset组布局来检查可能冗余的asset。 …

微服务框架 SpringCloud微服务架构 微服务面试篇 54 微服务篇 54.6 Nacos与Eureka的区别有哪些?【服务发现】

微服务框架 【SpringCloudRabbitMQDockerRedis搜索分布式&#xff0c;系统详解springcloud微服务技术栈课程|黑马程序员Java微服务】 微服务面试篇 文章目录微服务框架微服务面试篇54 微服务篇54.6 Nacos与Eureka的区别有哪些&#xff1f;【服务发现】54.6.1 Nacos 的服务拉取…

基于STM32单片机智能自动伸缩衣架雨滴重量光强温度检测伸缩速度可调-蓝牙版

实践制作DIY- GC0010-智能自动伸缩衣架 一、功能说明&#xff1a; 基于STM32单片机设计-智能自动伸缩衣架 功能介绍&#xff1a; 基于STM32F103C系列&#xff0c;LCD1602显示器&#xff0c;光敏电阻采集光强&#xff0c;雨滴传感器&#xff0c;ULN2003控制步进电机&#xff0…