CMake 系列(一):编译第一个可执行文件

本篇将演示如何用 CMake 配置并构建一个最简单的项目:整个项目只有一个源文件,最终生成一个可执行文件。我们以 C++ 为例进行讨论。

提示:本示例在 CMake 3.5 或更高版本中有效,并已在 GNU/Linux、macOS 和 Windows 上测试通过。

具体实施

我们希望将以下源代码编译为单个可执行文件:

#include <cstdlib>
#include <iostream>
#include <string>

std::string say_hello() { return std::string("Hello, CMake world!"); }

int main() {
  std::cout << say_hello() << std::endl;

  return EXIT_SUCCESS;
}

除了源文件之外,我们还需要向 CMake 提供项目的配置描述。该描述使用 CMake 语言编写,我们把 CMake 指令放入一个名为 CMakeLists.txt 的文件中。

注意:文件名区分大小写,必须命名为 CMakeLists.txt,CMake 才能够解析。

示例中,我们使用一个简单的 CMakeLists.txt 来构建 “Hello world” 可执行文件:

cmake_minimum_required(VERSION 3.5 FATAL_ERROR)

project(recipe-01 LANGUAGES CXX)

add_executable(hello-world hello-world.cpp)

注意:CMake 语言指令不区分大小写,但是参数区分大小写。

提示:CMake 中,C++ 是默认的编程语言。不过,我们还是建议使用 LANGUAGES 选项在 project() 命令中显式地声明项目的语言。

要配置项目并生成构建器,我们必须通过命令行界面(CLI)运行 CMake。CMake CLI 提供了许多选项,cmake --help 会输出列出所有可用选项的完整帮助信息,其中的大多数选项会让您访问 CMake 手册查看详细信息,后面的内容中我们还会对这些选项有更多了解。通过下列命令生成构建器:

$ mkdir -p build
$ cd build
$ cmake ..

这里,我们创建了一个目录 build(生成构建器的位置),进入 build 目录,并通过指定 CMakeLists.txt 的位置(本例中位于父目录中)来调用 CMake。也可以使用以下命令实现相同的效果:

$ cmake -H. -Bbuild

该命令是跨平台的,使用了 -H 和 -B 两个 CLI 选项:-H 表示在当前目录中搜索根 CMakeLists.txt 文件,-Bbuild 告诉 CMake 在名为 build 的目录中生成所有文件。

注意:cmake -H. -Bbuild 也属于 CMake 的标准使用方式。不过,我们将使用传统方法:创建一个构建目录,进入其中,并通过将 CMake 指向 CMakeLists.txt 的位置来配置项目。

运行 cmake 命令会输出一系列状态消息,显示配置信息:

$ cmake ..
-- The CXX compiler identification is GNU 8.1.0
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/user/cmake-cookbook/chapter-01/recipe-01/cxx-example/build

注意:在与 CMakeLists.txt 相同的目录中执行 cmake .,原则上足以配置一个项目。然而,CMake 会将所有生成的文件写到项目的根目录中,这是一个源内构建,通常不推荐,因为它会混合源代码和生成文件的目录树。我们推荐的是源外构建。

工作原理

CMake 是一个构建系统生成器,它描述了构建系统(如 Unix Makefile、Ninja、Visual Studio 等)应当如何操作才能编译代码,然后为所选的构建系统生成相应的指令。默认情况下,在 GNU/Linux 和 macOS 系统上,CMake 使用 Unix Makefile 生成器;在 Windows 上,Visual Studio 是默认的生成器。下一篇中我们将进一步接触生成器,后面的章节中还会重新讨论它。

GNU/Linux 上,CMake 默认生成 Unix Makefile 来构建项目。要构建示例项目,我们运行以下命令:

$ cmake --build .

最后,CMake 不强制指定构建目录的名称或位置,我们完全可以把它放在项目路径之外。这样做同样有效:

$ mkdir -p /tmp/someplace
$ cd /tmp/someplace
$ cmake /path/to/source
$ cmake --build .

由 CMake 生成的构建系统(即上面示例中的 Makefile),将包含为给定项目构建目标文件、可执行文件和库的目标及规则。hello-world 可执行文件是当前示例中的唯一目标,运行以下命令可以查看:

$ cmake --build . --target help
The following are some of the valid targets for this Makefile:
... all (the default if no target is provided)
... clean
... depend
... rebuild_cache
... hello-world
... edit_cache
... hello-world.o
... hello-world.i
... hello-world.s

CMake 生成的目标比构建可执行文件的目标要多,可以使用 cmake --build . --target <target-name> 语法来构建指定的目标。对于更复杂的项目,CMake 还会通过测试阶段和安装规则生成额外的目标。

系列导航


   转载规则


《CMake 系列(一):编译第一个可执行文件》 由 吴杭沉 采用 知识共享署名 4.0 国际许可协议 进行许可。
 上一篇
CMake 系列(二):切换构建生成器 CMake 系列(二):切换构建生成器
CMake 是一个构建系统生成器,可以使用单个 CMakeLists.txt 为不同平台上的不同工具集配置项目。您可以在 CMakeLists.txt 中描述构建系统必须执行的操作,以配置并编译代码;基于这些指令,CMake 将为所选的构建
2022-03-22
下一篇 
CMake 系列导读:从第一个可执行文件到工程化构建的完整路径 CMake 系列导读:从第一个可执行文件到工程化构建的完整路径
这个系列把 CMake 的核心用法整理成了一条由浅入深的完整路径:从把单个源文件编译成可执行文件的第一步开始,经过构建类型与编译器选项的精细控制,进入操作系统与外部库的环境检测,再到函数、宏、模块化的工程化组织,最后以动态库链接和 GDB
2022-03-14
  目录