CMake

本节将从一个简单的例子入手,带领大家了解CMake的基本用法,并一步步构建一个项目。

什么是CMake

CMake 是个一个开源的跨平台自动化建构系统,用来管理软件建置的程序,并不依赖于某特定编译器,并可支持多层目录、多个应用程序与多个函数库。

CMake 通过使用简单的配置文件 CMakeLists.txt,自动生成不同平台的构建文件(如 Makefile、Ninja 构建文件、Visual Studio 工程文件等),简化了项目的编译和构建过程。

CMake 本身不是构建工具,而是生成构建系统的工具,它生成的构建系统可以使用不同的编译器和工具链。

安装CMake

使用VS2022的同学理论上可以跳过这一步。

我们使用Windows下的二进制安装,打开官网下载地址,选择Windows x64 Installer下载。

注意选中加入环境变量的选项。

工程初始化

首先创建一个文件夹,例如cmake_tutorial,在文件夹中创建一个src的文件夹,在src文件夹下新建一个main.cpp文件。

注意不要在任何路径中包含中文字符,养成良好的编程习惯。

你可以在VS2022中创建一个空项目,然后创建一个main.cpp文件;或者直接在文件夹中新建文本文档,然后重命名将其后缀改为.cpp

打开main.cpp,输入以下内容:

#include <iostream>

int main() {
    std::cout << "Hello, World!" << std::endl;
    return 0;
}

对于习惯C语言的你,里面的一些语法可能有些陌生,但是不用担心,我们会在后续的章节中详细讲解。

现在我们的文件目录结构如下:

cmake_tutorial
└── src
    └── main.cpp

我们新建一个CMakeLists.txt文件,输入以下内容:

cmake_minimum_required(VERSION 3.16)
project(cmake_tutorial LANGUAGES CXX)

这两行是CMake的基本语法,第一行指定了CMake的最低版本,第二行指定了项目的名称和语言。CXX表示使用C++语言,XX是因为一些历史原因。其中cmake_tutorial是项目的名称,你可以根据自己的项目名称进行修改。

然后我们需要告诉CMake如何编译我们的项目,我们在CMakeLists.txt中添加以下内容:

add_executable(${PROJECT_NAME} src/main.cpp)

这一行告诉CMake生成一个可执行文件,可执行文件的名称为${PROJECT_NAME},源文件为src/main.cpp${xxx}表示CMake的变量,${PROJECT_NAME}是CMake自动生成的变量,是我们在project()中设定的项的名称。

然后在VS2022中打开cmake_tutorial文件夹,选择合适的启动项,点击运行。

更复杂的项目

接下来我们将项目进行扩展,添加一个math文件夹,然后在math文件夹下新建一个add.hadd.cpp文件。

在新建文件过程中VS会提供一些建议,我们目前可以忽略。

add.h

#ifndef __ADD_H__
#define __ADD_H__

int add(int a, int b);
float addf(float a, float b);

#endif // __ADD_H__

这里#ifndef#define#endif是为了防止头文件被重复包含,也可以在头文件顶部使用#pragma once(不是C++标准,但是大多数编译器都支持)。

add.cpp

#include "add.h"

int add(int a, int b) {
    return a + b;
}

float addf(float a, float b) {
    return a + b;
}

现在我们的文件目录结构如下:

cmake_tutorial
└── src
    ├── math
    │   ├── add.h
    │   └── add.cpp
    └── main.cpp

接下来我们继续配置CMake,在CMakeLists.txt前两行后添加:

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

这两行告诉CMake使用C++17标准,并且强制使用这个标准。

然后修改和添加以下内容:

set(SRC "${PROJECT_SOURCE_DIR}/src/")

file(GLOB_RECURSE PRJ_SRC "${SRC}*.cpp")

add_executable(${PROJECT_NAME} 
    ${PRJ_SRC}
)

include_directories(${PROJECT_NAME} PRIVATE 
    ${SRC}
)

set(SRC "${PROJECT_SOURCE_DIR}/src/")定义了一个变量SRC,表示源文件的路径。其中${PROJECT_SOURCE_DIR}是CMake自动生成的变量,表示项目的根目录。

file(GLOB_RECURSE PRJ_SRC "${SRC}*.cpp")定义了一个变量PRJ_SRC,表示项目中所有的.cpp文件。GLOB_RECURSE表示递归搜索,*表示任意字符,*.cpp会匹配所有的.cpp文件。

add_executable(${PROJECT_NAME} ${PRJ_SRC})告诉CMake生成一个可执行文件,可执行文件的名称为${PROJECT_NAME},源文件为PRJ_SRC

include_directories(${PROJECT_NAME} PRIVATE ${SRC})告诉CMake在编译时包含SRC目录,在*.cpp中使用#include "add.h"时,CMake会在SRC目录中查找。

最后我们在main.cpp中测试我们的修改:

#include <iostream>
#include "math/add.h"

int main() {
    std::cout << add(1, 2) << std::endl;
    return 0;
}

然后在重新运行项目,你会看到输出3

如果出现错误,可以尝试重新生成CMake缓存(右键CMakeLists.txt -> 删除缓存并重新配置)。

至此,在当前的项目基础上,你已经可以使用CMake来构建一个简单的项目了。

你可能会注意到,#include后出现了"math/add.h"<iostream>,这两种方式的区别在于:前者的引用只会在当前目录下查找,后者优先在系统的标准库目录下查找。

CMake进阶

参考官方文档,也可以在网络上搜索一些中文的教程。

powered by Gitbook文档修改时间: 2024-09-01 09:54:26

results matching ""

    No results matching ""