cmake
之前捯饬CLion的时候,发现有这么一个玩意:
发现,CLion和visiual stduio不一样的地方在于CLion会有一个CMakeList的txt文件,这个在visiual stduio中从来没有过,所以自己研究了一下,发现cmake是一个软件构建和编译工具。我们之前学的Makefile也是这样子的一款软件,如果有小伙伴不知道Makefile是什么的,可以点击下方的连接:
今天我们要了解的是一款更强大的软件构建和编译工具——cmake。
什么是软件构建和编译工具
在这之前,还是简单介绍一下软件构建和编译工具:
软件构建和编译工具是用于自动化软件开发过程中的构建和编译任务的工具。它们可以大大简化和加速软件开发流程,并确保软件项目的可靠性和可重复性。这些工具通常提供以下功能:
1.编译代码: 编译工具负责将源代码文件转换为可执行文件或库文件。它们将源代码翻译成计算机可以理解的二进制格式。
2.依赖管理: 许多软件项目依赖于其他软件包或库。构建工具可以自动管理这些依赖关系,确保项目所需的所有组件都是可用的,并在必要时下载或安装它们。
3.代码打包: 构建工具可以将编译后的代码打包成可部署的软件包,如可执行文件、安装程序或容器镜像等。
4.自动化测试: 构建工具可以集成自动化测试框架,并在构建过程中运行测试,以确保代码的质量和稳定性。
5.静态分析: 一些构建工具提供静态代码分析功能,可以检测代码中的潜在问题、错误或不良实践,并提供改进建议。
6.部署支持: 构建工具可以集成部署管道,简化将软件部署到生产环境的过程,并确保部署过程的可靠性和一致性。
以下是一些常见的软件构建和编译工具:
Make: 最早的构建工具之一,用于管理基于文件依赖关系的构建任务。
Apache Ant: 用于 Java 应用程序的构建工具,基于 XML 配置文件。
Apache Maven: 用于 Java 应用程序的构建工具和项目管理工具,支持依赖管理、项目结构标准化等功能。
Gradle: 用于构建 Java 和 Android 应用程序的灵活构建工具,支持 Groovy 和 Kotlin 语言。
GNU Autotools: 用于 Unix 系统的自动配置和构建工具套件,包括 Autoconf、Automake 和 Libtool。
CMake: 跨平台的开源构建系统,用于管理跨平台项目的构建过程。
MSBuild: 由 Microsoft 开发的构建引擎,用于构建 .NET Framework 和 .NET Core 应用程序。
Webpack: 用于构建现代 Web 应用程序的模块化打包工具。
Bazel: 由 Google 开发的构建工具,用于构建和测试多语言项目。
这些构建和编译工具提供了广泛的功能和支持,可以满足不同类型的软件项目的需求。选择合适的工具取决于项目的特性、开发团队的偏好以及特定的技术栈和环境。
简单来说,有了这些软件,我们编译代码的时候效率会大大提升,省时省力。
cmake
了解这么多,我们来看看cmake
CMake是一个跨平台的安装(编译)工具,可以用简单的语句来描述所有平台的安装(编译过程)。它能够输出各种各样的makefile或者project文件,能测试编译器所支持的C++特性,类似于UNIX下的automake。CMake的组态档取名为CMakeLists.txt。
CMake并不直接建构出最终的软件,而是产生标准的建构档(如Unix的Makefile或Windows Visual C++的projects/workspaces),然后再依一般的建构方式使用。这使得熟悉某个集成开发环境(IDE)的开发者可以用标准的方式建构他的软件,这种可以使用各平台的原生建构系统的能力是CMake和SCons等其他类似系统的区别之处。
CMake的特点主要有:
开放源代码,使用类BSD许可发布。
简化编译构建过程和编译过程。
CMake的使用步骤大致如下:
编写CMakeLists.txt文件。
创建一个build目录(可选),用来存放cmake生成的文件。
进入build目录,执行cmake …命令,将CMakeLists.txt文件转化为make所需的makefile文件。其中,路径“…”表示CMakeLists.txt所在目录(路径可以根据自己CMakeLists.txt所在目录更改)。
在build目录下,执行make命令,生成目标可执行文件。
在CMake中,还提供了许多命令和变量来定制构建过程,如设置编译器选项、链接库、包含目录等。这些都可以通过编辑CMakeLists.txt文件来实现。
总的来说,CMake是一个强大而灵活的跨平台编译工具,可以帮助开发者更方便地构建和编译软件项目。
安装cmake
windows
windows下访问官网,下载对应版本即可:
大家可以点击这里跳转:
windows大家了解即可,我们主要来看Linux下的:
Linux
Linux下,不同版本的安装方式可能不一样,我这里是apt安装(Centos是yum)
我们可以用cmake --version查看版本:
通过cmake编译代码
准备CMakeLists.txt
首先我们先创建一个CMakeLists.txt(注意,这里千万不能写错哦):
然后我们进入CMakeLists.txt中去编辑:
注释
cmake的单行注释以#开头:
块状注释
cmake的多行注释以 #[[ 注释内容 ]] :
cmake_minimum_required:确定cmake的最低版本
我们首先写的第一行是确定cmake的最低版本:
这个其实可加可不加,不加可能会有警告。
project:定义工程名称:
project:定义工程名称:
这个其实是一个比较简单的,它其实还有其他的参数:
# PROJECT 指令的语法是:
project(<PROJECT-NAME> [<language-name>...])
project(<PROJECT-NAME>
[VERSION <major>[.<minor>[.<patch>[.<tweak>]]]]
[DESCRIPTION <project-description-string>]
[HOMEPAGE_URL <url-string>]
[LANGUAGES <language-name>...])
比如说:
add_executable:定义工程会生成一个可执行程序
add_executable:定义工程会生成一个可执行程序:
add_executable(可执行程序名 源文件名称)
准备生成可执行文件
这样一个最简单的CMakeLists.txt文件我们就写好了,因为我们执行命令之后会有一大堆的其他文件冒出来,所以我们新建一个文件夹,用来存放我们执行命令后产生的一系列多的文件:
我们进入这个文件:
然后我们要执行最重要的一步,执行cmake,但在这之前,我们要确定CMakeLists.txt在哪里,我们创建了Building文件夹,我们现在在我们创建了Building文件夹,那么我们的CMakeLists.txt就在上一级的目录(CMake_Test)里:
这个时候就会帮我们构建:
这个时候,我们看看Building文件下出现了什么:
我们发现有一个Makefile,我们再执行一下make指令:
这个时候显示他已经帮我们构建好了Mybin,我们显示看看:
我们执行一下Mybin:
执行成功。
set
设置变量
现在有一个问题add_executable如果依赖的文件很多,写起来就会很长:
其实,我们可以将我们的文件名设置成为一个变量,这样我们用起来就方便多了,要设置变量,我们要使用set:
SET(VAR [VALUE] [CACHE TYPE DOCSTRING [FORCE]])
比如说这样:
如果我们要使用这个变量,我们要加上$:
指定输出路径
set除了设置变量,还可以设置输出路径,设置路径专门有一个宏:EXECUTABLE_OUTPUT_PATH:
EXECUTABLE_OUTPUT_PATH 是 CMake 中的一个变量,用于指定最终生成的可执行文件的存放目录。当你在 CMakeLists.txt 文件中使用 add_executable 命令来添加一个可执行目标时,CMake 会根据EXECUTABLE_OUTPUT_PATH 变量的值来决定将生成的可执行文件放在哪个目录下
这个路径可以是绝对路径,也可以是相对路径:
CMake 会根据当前的处理上下文(通常是 CMakeLists.txt 文件所在的目录)来解释这个相对路径。这意味着相对路径是相对于当前正在处理的 CMakeLists.txt 文件所在的目录,而不是相对于最终构建出的二进制文件所在的目录。
假如有这么一个目录结构:
my_project/
CMakeLists.txt
src/
main.cpp
bin/
并且这样设置:
set(EXECUTABLE_OUTPUT_PATH bin)
这样设置后,CMake 会将生成的可执行文件放在 my_project/bin 目录中,因为 bin 是相对于 CMakeLists.txt 文件所在目录(my_project/)的相对路径。
设置C++标准
set还可以设置编译时的C++的标准,我们也有一个宏:**CMAKE_CXX_STANDARD **:
# 增加-std=c++11
set(CMAKE_CXX_STANDARD 11)
现在我们来测试一下,我把Building这个文件夹删除:
重新创建一个文件夹reBuilding,然后执行cmake:
这个时候,我们看看文件的变化:
发现多了一个bin文件夹,我们此时再执行make:
我们执行一下:
运行成功。
搜索文件
我们已经会了set设置变量来简化了,但这样还是很麻烦,我们希望cmake可以自动帮我们找到源文件进行编译。
aux_source_directory 命令可以查找某个路径下的所有源文件
aux_source_directory 命令可以查找某个路径下的所有源文件:
aux_source_directory(< dir > < variable >)
比如说:
我们可以删除reBuilding里面的所有东西,重建,实验一下:
file
我们也可以用file来搜索:
file(GLOB/GLOB_RECURSE 变量名 要搜索的文件路径和文件类型)
这里有两个参数:
GLOB: 将指定目录下搜索到的满足条件的所有文件名生成一个列表,并将其存储到变量中。
GLOB_RECURSE:递归搜索指定目录,将搜索到的满足条件的文件名生成一个列表,并将其存储到变量中。
这里我们可以只用GLOB,因为我们没有递归:
我们清空reBuilding里面的内容,然后再来一次:
然后make的时候报错了:
因为我们没有指定搜索文件的类型,我们加上:
就OK了~。
指定头文件目录
在编译项目源文件的时候,很多时候都需要将源文件对应的头文件路径指定出来,这样才能保证在编译过程中编译器能够找到这些头文件,并顺利通过编译。在CMake中设置要包含的目录也很简单,通过一个命令就可以搞定了,他就是include_directories:
include_directories(headpath)
插件配置
如果大家vscode可以连上Linux,可以安装这几个插件,代码可以自动补全:
直接在插件搜索就行了,如果vscode没有脸上Linux的,可以点击这里,手把手教你配置: