本文是自己在学习CMake过程中的简单记录。主要内容来自CMake官方教程,有一些自己的理解,也不知道是否正确,请酌情参考。
简介(Introduction)
CMake教程是按步骤进行的学习向导。Cmake涵盖内容多,使用例子学习Cmake各部分是如何工作的,易于理解。
步骤(Steps)
本教程例子的源代码可从CMake官方提供的地址下载。每一步一个文件夹,包括代码,可供学习使用。本教程是分步进行的,每一步都是对上一步的修改完善。
CMake教程——步骤1:开始(CMake Tutorial--Step 1: A Basic Starting Point)
如何开始学习CMake?本步骤,介绍CMake的基本语法(syntax)、命令(commands)以及变量(variables)。介绍完基础知识后,会通过三个小练习来创建一个简单的CMake项目(project)。
本步骤的每次练习都会用到一些背景知识。会列出练习的目标,可供参考的资料。编辑文件(Files to Edit)
章节下的文件都位于Step1
文件夹下,文件中都有步骤(TODO)
提示。每个步骤(TODO)
表示有一行或两行代码需要修改或增加。步骤(TODO)
需要按序号顺序来完成,例如,需先完成步骤1(TODO 1)
再完成步骤2(TODO 2)
。开始(Getting Started)
章节下,会给一些提示,帮助读者完成练习。生成运行(Build and Run)
章节,则一步一步地生成、测试练习。最后,给出练习的参考答案。
需要注意的是,本教程每步是基于上一步的,例如进行步骤2,需要完成步骤1。
练习1:建立基本的项目(Exercise 1 - Building a Basic Project)
最基本的Cmake项目是由一个单独的源文件生成可执行文件,这样简单的项目,只需要一个由三行命令组成的CMakeList.txt
文件。
注意:对于CMake,命令中的字母大写、小写或者大小写都有,CMake都能识别出,但是本教程建议使用小写字母。
每个项目中最顶层的CMakeList.txt
,最开始需要的命令是声明所需CMake的最低版本,命令是cmake_minimum_required()(给出的链接,命令的使用帮助,看不太明白)。使用此命令来指定CMake的版本,以确保接下来的CMake函数和设置可以运行。
使用命令project() ,来指定项目名。每个项目都需要此条命令,并且紧跟在cmake_minimum_required()
命令之后。此命令还可以指定项目的其他信息如语言、版本号等。
最后,CMake使用命令add_executable() ,来从指定的源文件创建可执行文件。
目标(Goal)
学习如何创建最简单的CMake项目
参考资料(Helpful Resources)
需编辑的文件(Files to Edit)
CMakeLists.txt
开始(Getting Started)
在文件夹Help/guide/tutorial/Step1
提供了源文件tutorial.cxx
,由于计算数值的平方根。本步骤不需要修改此文件。
在此文件夹下,需要修改完成CMakeLists.txt
文件,需要完成第一步(TODO 1)
到第一步TODO 3
。
练习答案(Soution)
(本节本来在练习的最后,我感觉放在这里,更适合新手学习使用。)
CMakeLists.txt
文件第一行需要使用命令 cmake_minimum_required()
设置CMake的版本:
- 第一步(TODO 1),在文件
CMakeLists.txt
中:cmake_minimum_required(VERSION 3.10)
下一步使用命令project()
,创建项目,并命名:
- 第二步(TODO 2),在文件
CMakeLists.txt
中:project(Tutorial)
最后一条命令是,add_executable()
:
- 第三步(TODO 3),在文件
CMakeLists.txt
中:add_executable(Tutorial tutorial.cxx)
生成运行
完成第一步(TODO 1)
到第一步TODO 3
后,就可以生成运行项目了。首先,运行cmake,或cmake-gui,配置(configure)项目,然后使用选择的生成工具生成。
例如,在文件夹Help/guide/tutorial
(我的是D:\VisualStudioProjects\cmake-3.26.0-rc6-tutorial-source
)下,运行命令行,创建生成目录:mkdir Step1_build
接下来,进入Step1_build
文件夹下,运行cmake
配置项目、生成本地构建系统:cd Step1_build
cmake ../Step1
PS D:\VisualStudioProjects\cmake-3.26.0-rc6-tutorial-source> mkdir Step1_build
目录: D:\VisualStudioProjects\cmake-3.26.0-rc6-tutorial-source
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 3/11/2023 7:00 PM Step1_build
PS D:\VisualStudioProjects\cmake-3.26.0-rc6-tutorial-source> cd .\Step1_build\
PS D:\VisualStudioProjects\cmake-3.26.0-rc6-tutorial-source\Step1_build> cmake ../Step1
-- Building for: Visual Studio 17 2022
-- The C compiler identification is MSVC 19.35.32215.0
-- The CXX compiler identification is MSVC 19.35.32215.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: D:/Program Files/Microsoft Visual Studio/2022/Community/VC/Tools/MSVC/14.35.32215/bin/Hostx64/x64/cl.exe - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: D:/Program Files/Microsoft Visual Studio/2022/Community/VC/Tools/MSVC/14.35.32215/bin/Hostx64/x64/cl.exe - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done (7.1s)
-- Generating done (0.1s)
-- Build files have been written to: D:/VisualStudioProjects/cmake-3.26.0-rc6-tutorial-source/Step1_build
PS D:\VisualStudioProjects\cmake-3.26.0-rc6-tutorial-source\Step1_build>
接下来,调用构建系统完成项目的编译/链接(compile/link):cmake --buid .
PS D:\VisualStudioProjects\cmake-3.26.0-rc6-tutorial-source\Step1_build> cmake --build .
MSBuild version 17.5.0+6f08c67f3 for .NET Framework
Checking Build System
Building Custom Rule D:/VisualStudioProjects/cmake-3.26.0-rc6-tutorial-source/Step1/CMakeLists.txt
tutorial.cxx
Tutorial.vcxproj -> D:\VisualStudioProjects\cmake-3.26.0-rc6-tutorial-source\Step1_build\Debug\Tutorial.exe
Building Custom Rule D:/VisualStudioProjects/cmake-3.26.0-rc6-tutorial-source/Step1/CMakeLists.txt
PS D:\VisualStudioProjects\cmake-3.26.0-rc6-tutorial-source\Step1_build>
最后,进入Debug
文件夹下,运行生成的Tutorial
程序:
PS D:\VisualStudioProjects\cmake-3.26.0-rc6-tutorial-source\Step1_build> cd .\Debug\
PS D:\VisualStudioProjects\cmake-3.26.0-rc6-tutorial-source\Step1_build\Debug> .\Tutorial.exe 10
The square root of 10 is 3.16228
PS D:\VisualStudioProjects\cmake-3.26.0-rc6-tutorial-source\Step1_build\Debug>
练习2:指定C++标准(Exercise 2 - Specifying the C++ Standard)
CMade有些特殊的变量(variables)或由后台生成,或由项目代码设置对CMAke有特殊用途。这些变量的前缀是CMAKE_
。在自己项目中命名变量时避免使用此前缀。其中的两个变量是,CMAKE_CXX_STANDARD、CMAKE_CXX_STANDARD_REQUIRED,这两个变量可赋值。这两个变量组合使用,可指定生成项目所需的C++标准。
目标(Goal)
添加要求C++11标准的特性(feature)。
资料(Helpful Resources)
需编辑的文件(Files to Edit)
CMakeLists.txt
tutorial.cxx
开始(Getting Started)
继续在Step1
文件夹下进行编辑。从TODO 4
到TODO 6
。
首先,编辑文件tutorial.cxx
,增加要求C++11标准的特性。然后,更新CMakelists.txt
以要求C++11。
练习答案(Solution)
在文件tutorial.cxx
中,使用语句std::stod
替换atof
,以要求使用C++11标准的特性。
- TODO 4,在文件
tutorial.cxx
中:const double inputValue = std::stod(argv[1]);
TODO 5
,删除#include <cstdlib>
。
在CMake中使用 CMAKE_CXX_STANDARD
变量来指定使用的C++标准。本教程中,在文件CMakeLists.txt
中,设置 CMAKE_CXX_STANDARD
变量值为11
,变量CMAKE_CXX_STANDARD_REQUIRED
值为True
。 CMAKE_CXX_STANDARD
命令要放在add_executable()
命令之前。
TODO 6,在文件
CMakeLists.tx
中:set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED True)
生成运行(Build and Run)
由于已经创建了生成目录且以在练习1中运行了CMake,所以可以跳过生成步骤:
cd Step1_build
cmake --build .
测试新生成的Tutorial.exe
:
Tutorial 4294967296
Tutorial 10
Tutorial
练习3:添加版本号和配置好的头文件(Exercise 3 - Adding a Version Number and Configured Header File)
有时需要在源代码中使用在CMakelists.txt
文件中定义的变量。本练习中,我们打印输出项目版本。
使用配置头文件(configured header file)。在输入文件中定义变量。这些变量语法特殊,类似@VAR@
这样。然后,使用命令configure_file(),复制输入文件到输出文件,并且使用CMakelists.txt
文件中VAR
的值去替换输入文件中的变量值。
虽然可以直接在源码中编辑版本号,但是使用此特性,可以创建单一的版本号源避免存在多个副本。
目标(Goal)
定义、输出项目版本号。
资料
需编辑的文件
CMakeLists.txt
tutorial.cxx
开始
继续编辑文件夹Step1
下的文件,从TODO 7
到TODO 12
。在CMakeLists.txt
文件中加入项目版本号,且在此文件中,使用命令configure_file()
复制输入文件到输出文件,并且替换输入文件中的变量值。
接下来,创建文件TutorialConfig.h.in
(在文件夹Step1
下已经有此文件),使用命令configure_file()
传入的变量来定义版本号。
最后,更新tutorial.cxx
文件以打印出版本号。
练习答案
首先,在CMakeLists.txt
文件中,修改命令project()
以定义项目名和项目版本号。CMake调用命令project()
时,会在后台定义变量Tutorial_VERSION_MAJOR
、Tutorial_VERSION_MINOR
并赋值。
TODO 7
,在文件CMakeLists.txt
中:project(Tutorial VERSION 1.0)
接下来使用configure_file()
命令,以把指定的CMake变量值替换输入文件中的值:
TODO 8
,在文件CMakeLists.txt
中:configure_file(TutorialConfig.h.in TutorialConfig.h)
配置文件在项目二进制文件目录下写入,因此必须把此目录加入到包含头文件的搜索路径列表中。
注意:此教程中,我们不加区别地使用项目生成目录和项目二进制文件目录,它们指代的路径是一样的,不是指代的bin/
目录。
使用命令target_include_directories()
,指定可执行文件(executable target)在何处搜索头文件。
TODO 9
,在文件CMakeLists.txt
中:target_include_directories(Tutorial PUBLIC "${PROJECT_BINARY_DIR}")
TutorialConfig.h.in
作为输入来配置头文件,当CMakeLists.txt
中的命令configure_file()
调用时,文件TutorialConfig.h.
中的变量@Tutorial_VERSION_MAJOR@
和@Tutorial_VERSION_MINOR@
的值会被替换成项目中对应的版本号。
TODO 10
,在文件TutorialConfig.h.in
中:// the configured options and settings for Tutorial #define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@ #define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@
接下来,修改文件tutorial.cxx
,来包含配置好的头文件TutorialConfig.h
。
TODO 11
,在文件tutorial.cxx
中:#include "TutorialConfig.h"
最后,更新tutorial.cxx
,打印程序名和版本号:
TODO 12
,在文件tutorial.cxx
中:if (argc < 2) { // report version std::cout << argv[0] << " Version " << Tutorial_VERSION_MAJOR << "." << Tutorial_VERSION_MINOR << std::endl; std::cout << "Usage: " << argv[0] << " number" << std::endl; return 1; }
生成运行
cd Step1_build
cmake --build .
当执行程序不带数字参数时,可打印出版本号:
PS D:\VisualStudioProjects\cmake-3.26.0-rc6-tutorial-source\Step1_build\Debug> .\Tutorial.exe
D:\VisualStudioProjects\cmake-3.26.0-rc6-tutorial-source\Step1_build\Debug\Tutorial.exeVersion 1.0
Usage: D:\VisualStudioProjects\cmake-3.26.0-rc6-tutorial-source\Step1_build\Debug\Tutorial.exe number
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。