ps:本文是对cmake的基础讲解,掌握后解决70-80%情况是足以应对的,后续会对cmake有进阶内容。
一 前言
CMake 是一个工具,帮助开发者管理和自动化软件项目的构建过程。它使用一个叫做CMakeLists.txt 的文本文件来描述项目的组织结构、编译选项和依赖关系。这个工具的优点是开源且具有移植性好。 简单举个例子,我们在Linux上编写C/C++程序,在编写完成后需要使用gcc对源文件手动编译。如果项目中的文件比较少的情况下,可以每次通过命令手动编译。但是如果一个程序需要用到100,1000个文件难道每次还要自己手动写吗,就要借助构建生成工具有两种解决方案:1)Makefile 2)cmake
1.1 cmake 和 Makefile
二者都是构建生成工具,cmake比Makefile更高级,cmake跨平台性更好,Makefile 可能会涉及到有关操作系统和编译器的命令和语法,这使得同一个项目在不同平台上可能需要不同的 Makefile 语法。
1.2 cmake的基本流程
-
编写 CMakeLists.txt 文件:在项目的目录下创建一个名为 CMakeLists.txt 的文件,这个文件描述了项目的构建信息,包括项目名称、源文件、依赖库等。
-
生成构建文件:在项目的构建目录(可以是在源码目录外的任何位置)执行 cmake +CMakeLists.txt文件相对于现在位置的所在路径 命令来生成相应的构建系统文件。见下面的例子中:因为我们是在编写CMakeLists.txt文件的同级目录下创建的build目录,所以相对于build的目录来说CMakeLists.txt就是在上一级中,所以加上 .. 语句。
mkdir build
cd build
cmake ..
这会在当前的 build 目录下生成适合于当前平台的一套构建生成文件
3. 生成可执行程序:可以通过执行 make 命令,就可以生成一个目标文件在指定的目录下。这里的make就是操作的Makefile文件,学过Makefile的同学比较清楚。
二 简单使用
2.1 CMakeLists.txt 文件编写时三个基础指令及执行cmake文件命令
cmake最重要的就是编写 CMakeLists.txt 文本文件,三个基础指令
cmake_minimum_required(xxx) //指定可以执行此 CMakeLists.txt 文本文件的最低cmake版本,如果安装的cmake版本小于指定的版本,就不会被执行.可写可不写.project(xxx) 通过 project 命令可以指定项目的名称、版本号和编写语言等.但是我们一般只写一个项目名称就可以了,没必要写后面的.
project(MyProjectVERSION 1.0DESCRIPTION "A sample C++ project"LANGUAGES CXX //CXX就是C++的意思
)add_executable(目标程序名称, 依赖的源文件) //如果依赖多个源文件,用空格隔开或者用 : 隔开
用cmake +要执行的 CMakeLists.txt 文件路径就会生成一堆文件,这里面最重要的就是Makefile,再执行make就会生成源文件对应的可执行程序文件。
2.2 注释的使用
单行注释是 # 多行注释是#[[ ]] 将注释的内容写在框框之中
2.3 set的用法
set是用来定义变量的,cmake下一切皆字符串string
set(var value)
var为变量名,value是变量值
在变量定义好了之后,怎么使用变量呢?
${value} 这样使用一个变量
set的三个主要用处: 1)如果一个可执行程序生成要用到多个源文件,就可以用set提高效率。
2)指定编译时使用的C++标准
设置 CMAKE_CXX_STANDARD 这个宏就相当于指定了C++标准,11代表C++11。当然不止这一种方式还有一种方式:在执行cmake指令时指定
3)指定生成的可执行程序路径,就是生成的可执行程序存在哪个地方
set(EXECUTABLE_OUTPUT_PATH XXX)
EXECUTABLE_OUTPUT_PATH和指定C++标准一样,是个固定语法,后面跟路径即可,绝对路径和相对路径都可以,如果指定的路径不存在的话,会帮忙一层层创建出来
另外说一句,cmake和Makefile有个区别是,Makefile会根据修改时间判断要不要重新生成,而cmake是只要生成了不删除就不会重新生成。
2.4 查找-保存目标目录源文件命令
有两种方式:分别是aux 和 file
aux_source_directory(dirpath var)
dirpath是查找某目录下的所有源文件,将所有源文件的名称以字符串形式保存在 var 变量中.file(GLOB/GLOB_RECURSE 变量名 要搜索的文件路径和文件类型)
GLOB 和 GLOB的区别在于:假如指定了一个目录,这个目录下还有子目录文件,GLOB_RECURSE会递归式查找目录,而GLOB不会
变量名是保存按条件搜索出来的文件名称
要搜索的文件路径和文件类型以空格为分割线 eg: ${src} *.cc
文件路径不必多说,绝对路径和相对路径都可以. 文件类型就是想把什么类型的文件保存到变量中
PROJECT_SOURCE_DIR是个宏,在使用cmake +路径 生成一堆一堆cmake文件时,这个宏就是跟的那个路径。
2.5指定头文件查找路径
在一个大项目中,源文件在一个目录下,头文件在一个目录下,源文件中包含头文件eg:#include<head.h> 会在源文件的同级目录下查找和在环境变量中查找,但是不想把头文件的目录路径加在环境变量中,就要在编写CMakeLists.txt文件中指定一下头文件查找路径。
include_directories(xxx)
将com.h头文件放到head目录下
指定了到head目录下查找需要用到的头文件