文章目录
- 1. CMake概述
- 2. 编写一个简单的CMakeLists.txt
- 2.1注释
- 2.1.1 注释行
- 2.1.2 块注释
- 2.1 只有源文件
- 3. CMake中set使用
- set 基本使用
- set指定使用C++标准
- set指定输出路径
- 4. 搜索文件
1. CMake概述
- CMake 是一个项目构建工具,并且是跨平台的。关于项目构建我们所熟知的还有 Makefile(通过 make 命令进行项目的构建),大多是 IDE软件都集成了 make,比如:VS的 nmake、linux下的 GNU make、Qt 的 qmake 等,如果自己动手写 makefile,会发现,
makefile 通常依赖于当前的编译平台
,而且编写 makefile 的工作量比较大,解决依赖关系时也容易出错。- 而 CMake 恰好能解决上述问题, 其允许开发者指定整个工程的编译流程,在根据编译平台, 自动生成本地化的Makefile和工程文件,最后用户只需 make 编译即可,所以可以把 CMake 看成一款自动生成 Makefile 的工具,其编译流程如下图:
2. 编写一个简单的CMakeLists.txt
系统环境:
ubuntu20.04
查看Cmake是否安装:
cmake --version
CMake优点:
- 跨平台
- 能够管理大型项目
- 简化编译构建和编译过程
- 可扩展:可以为cmake编写特定功能的模块,扩充cmake功能
2.1注释
2.1.1 注释行
CMake
使用#
进行行注释
,可以放在任何位置
# 这是一个CMakeLists.txt文件
cmake_minimum_required(VERSION 3.0.0)
2.1.2 块注释
CMake
使用#[[]]
进行块注释
#[[这是一个CMakeLists.txt文件
这是一个CMakeLists.txt文件
这是一个CMakeLists.txt文件
]]
cmake_minimum_required(VERSION 3.0.0)
2.1 只有源文件
add.cpp:
#include <stdio.h>
#include "head.h"
const char* libVersion = "Library Version 1.0";
int add(int a, int b){
return a+b;
}
div.cpp:
#include <stdio.h>
#include "head.h"
double divide(int a, int b){
return a/b;
}
mult.cpp:
#include <stdio.h>
#include "head.h"
int multiply(int a, int b){
return a*b;
}
sub.cpp:
#include <stdio.h>
#include "head.h"
int substract(int a, int b){
return a-b;
}
head.h
#include <stdio.h>
#include "head.h"
int substract(int a, int b){
return a-b;
}
main.cpp
#include <stdio.h>
#include "head.h"
int main(){
int a = 20;
int b = 12;
printf("a = %d, b= %d \n",a,b);
printf("a+b = %d \n", add(a,b));
printf("a-b = %d \n", substract(a,b));
printf("a*b = %d \n", multiply(a,b));
printf("a/b = %f \n", divide(a,b));
}
添加CMakeLists.txt文件:
cmake_minimum_required(VERSION 3.0.0)
project(CALC)
add_executable(app add.cpp div.cpp main.cpp mult.cpp sub.cpp)
cmake_minimum_required
: 指定cmake的最低版本,可选,非必须,如果不加可能会有警告project
:定义工程名称,并可指定工程的版本、工程描述、web 主页地址、支持的语言(默认情况支持所有语言),如果不需要这些都是可以忽略的,只需要指定出工程名字即可。
#PROJECT 指令的语法是:
project(<PROJECT-NAME>[<language-name>...])
project(<PROJECT-NAME>
[VERSION <major>[.<minor>[.<patch>[.<tweak>]]]]
[DESCRIPTI0N <project-description-string>]
[HOMEPAGE URL <url-string>]
[LANGUAGES <language-name>...]) # 指定语言,即cmake支持的语言
add_executable
: 定义工程会生成一个可执行程序
add_executable(可执行程序名 源文件名称)
这里的可执行程序名和project中的项目名称没有任何关系
源文件名可以是一个也可以是多个,如果有多个可以用空格或者;
间隔
# 样式1
add_executable(app add.c div.c main.c mult.c sub.c)
# 样式2
add_executable(app add.c;div.c;main.c;mult.c;sub.c)
4. 执行CMake命令
将CMakeLists.txt文件编译好之后,就可以执行cmake命令了
# cmake 命令原型
cmake CMakeLists.txt文件所在路径
执行CMakeLists.txt会生成一些文件,可以在CMakeLists.txt目录下新建build文件,进入build文件,然后执行命令cmake ..
这时候生成的文件就会在build目录下了,之后使用make
对生成的Makefile文件进行编译,得到可执行文件app
3. CMake中set使用
set 基本使用
在上面的例子中一共提供了5个源文件,假设这五个源文件需要反复被使用,每次都直接将它们的名字写出来确实是很麻烦,此时我们就需要定义一个变量,将文件名对应的字符串存储起来,在cmake 里定义变量需要使用
set
。
# SET 指令的语法是:
#[]中的参数为可选项,如不需要可以不写
SET(VAR [VALUE][CACHE TYPE DOCSTRING [FORCE]])
其中:
VAR
:变量名称
VALUE
:变量值
# 方式1:各个源文件之间使用空格间隔
# set(SRC_LIST add.c div.cmain.c mult.csub.c)
# 方式2:各个源文件之间使用分号;间隔
set(SRC_LIST add.c;div.c;main.c;mult.c;sub.c)
add_executable(app${SRC_LIST})
set中变量的值都是字符串类型
set指定使用C++标准
在编写 C++程序的时候,可能会用到C++11、C++14、C++17、C++20 等新特性,那么就需要在编译的时候在编译命令中指定出要使用哪个标准:
如果不指定则默认使用C++98标准
g++ *.cpp -std=c+=11 -o app
上面的例子中通过参数 -std=c++11
指定出要使用 C++11 标准编译程序,C++标准对应有一宏叫做DCMAKE_CXX_STANDARD
。在CMake 中想要指定C++标准有种方式:
1. 在CMakeLists.txt中通过set命令指定
# 增加 -std=c++11
set(CMAKE_CXX_STANDARD 11)
# 增加 -std=c++14
set(CMAKE_CXX_STANDARD 14)
# 增加 -std=c++17
set(CMAKE_CXX_STANDARD 17)
2.在执行cmake命令的时候指定出这个宏的值
# 增加-std=c++11
cmake CMakeLists.txt文件路径 -DCMAKE_CXX_STANDARD=11
# 增加-std=c++14
cmake CMakeLists.txt文件路径 -DCMAKE_CXX_STANDARD=14
# 增加-std=c++17
cmake CMakeLists.txt文件路径 -DCMAKE_CXX_STANDARD=17
set指定输出路径
在 CMake 中指定可执行程序输出的路径,也对应一个宏,叫做
EXECUTABLE_OUTPUT_PATH
,它的值还是通过set
set(HOME /home/robin/Linux/Sort)
set(EXECUTABLE_OUTPUT_PATH ${HOME}/bin)
- 第一行:定义一个变量用于存储一个绝对路径
- 第二行:将拼接好的路径值设置给
EXECUTABLE_OUTPUT_PATH
宏,如果这个路径中的子目录不存在会自动生成,无需自己手动创建,路径建议用绝对路径
修改之前的CMakeLists.txt文件:
cmake_minimum_required(VERSION 3.0.0)
project(test)
# 指定使用C++标准
set(CMAKE_CXX_STANDARD 11)
set(SRC add.cpp div.cpp main.cpp mult.cpp sub.cpp)
# 指定可执行文件生成路径
set(EXECUTABLE_OUTPUT_PATH /home/dabing/aa/bb/cc)
add_executable(app ${SRC})
4. 搜索文件
如果一个项目里边的源文件很多,在编写 CMakeLists.txt 文件的时候不可能将项目目录的各个文件一一罗列出来,这样太麻烦也不现实。所以,在CMake 中为我们提供了搜索文件的命令,可以使用
aux_source_directory
命令或者file
命令。
方式1:aux_source_directory
aux_source_directory(<dir> <variable>)
dir
: 要搜索的目录variable
:将dir
目录下搜索到的源文件列表存储到该变量中
cmake_minimum_required(VERSION 3.0.0)
project(test)
# 指定使用C++标准
set(CMAKE_CXX_STANDARD 11)
# aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR} SRC_LIST)
aux_source_directory(${PROJECT_SOURCE_DIR} SRC_LIST)
add_executable(app ${SRC_LIST})
方式2:file
fiLe(GLOB/GLOB_RECURSE 变量名 要搜索的文件路径和文件类型)
GLOB
:将指定目录下搜索到的满足条件的所有文件名生成一个列表,并将其存储到变量中。
GLOB_RECURSE
:递归搜索指定目录,将搜索到的满足条件的文件名生成一个列表,并将其存储到变量中。
搜索当前目录的src目录下所有源文件,并存储到变量中:
file(GLOB MAIN_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp)
file(GLOB MAIN_HEAD ${CMAKE_CURRENT_SOURCE _DIR}/include/*.h)
CMAKE_CURRENT_SOURCE_DIR
:表示当前访问的CMakeLists.txt文件所在的路径
关于要搜索的文件路径和类型可以加双引号雨可以不加:
PROJECT_SOURCE_DIR
: 是在执行cmake
命令时后面跟着的路径
file(GLOB MAIN_HEAD "${CMAKE_CURRENT_SOURCE _DIR}/include/*.h")
使用示例:
cmake_minimum_required(VERSION 3.0.0)
project(test)
# 指定使用C++标准
set(CMAKE_CXX_STANDARD 11)
file(GLOB SRC_LIST ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp)
add_executable(app ${SRC_LIST})
注意:在实际使用中aux_source_directory
使用更方便,因为file
不仅要指定路径,还要指定文件后缀
本文参考:https://www.bilibili.com/video/BV14s4y1g7Zj/?spm_id_from=333.999.0.0