CMake 使用介绍

发布时间: 更新时间: 总字数:4711 阅读时间:10m 作者:IP:上海 网址

CMake是比make更为高级跨平台编译工具,它跨平台、开源的构建系统。

介绍

CMake通过CMakeLists.txt文件,使用cmake命令将CMakeLists.txt转化为makefile文件,通过make命令将源码编译为如下之一:

  • 可执行程序(bin)
  • 共享库(so, shared object)

安装

apt install cmake gcc -y
  • cmake --help-command add_custom_target

内置命令

CMake 有非常多内置命令,为了方便查阅和理解,本文将最常用、最核心的命令按照 项目配置目标与链接依赖与文件管理逻辑与控制流 四大类进行了分类汇总。

项目基础配置 (Project Setup)

这类命令通常放在 CMakeLists.txt 的最前面,用于定义项目的基本信息和全局变量。

命令 命令格式 说明 可以直接用的使用示例
cmake_minimum_required cmake_minimum_required(VERSION <min>) 声明项目所依赖的 CMake 最低版本。 cmake_minimum_required(VERSION 3.10)
project project(<name> [VERSION <ver>] [LANGUAGES <lang>]) 定义项目名称、版本号及使用的编程语言(默认C和CXX)。 project(MyApp VERSION 1.0.0 LANGUAGES CXX)
set set(<variable> <value>...) 设置普通变量、缓存变量或环境变量的值。 set(CMAKE_CXX_STANDARD 17)
set(SRC_FILES main.cpp auth.cpp)
message message([<mode>] "text" ...) 在终端输出日志信息。常用模式有 STATUS (普通), WARNING (警告), FATAL_ERROR (报错并终止)。 message(STATUS "当前构建类型: ${CMAKE_BUILD_TYPE}")
option option(<variable> "help text" [value]) 提供一个可以由用户在外部覆盖的布尔选项(ON/OFF)。 option(BUILD_TESTS "Build test programs" ON)

构建目标与依赖链接 (Targets & Linking)

这是现代 CMake (Modern CMake) 的核心部分。现代 CMake 推荐以“目标(Target)”为中心进行属性设置。

命令 命令格式 说明 可以直接用的使用示例
add_executable add_executable(<name> [source1...]) 添加一个可执行文件目标,并指定其源文件。 add_executable(my_app main.cpp util.cpp)
add_library add_library(<name> [STATIC | SHARED] [source...]) 添加一个库目标(STATIC 静态库 / SHARED 动态库)。 add_library(my_lib SHARED math.cpp)
target_link_libraries target_link_libraries(<target> <PUBLIC|PRIVATE|INTERFACE> <lib>...) 为目标链接其他库。PRIVATE 表示仅自己用,PUBLIC 自己和依赖方都用。 target_link_libraries(my_app PRIVATE my_lib)
target_include_directories target_include_directories(<target> <PUBLIC|PRIVATE|INTERFACE> <dir>...) 为特定目标指定头文件搜索路径,替代传统的 include_directories target_include_directories(my_lib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
target_compile_options target_compile_options(<target> <PUBLIC|PRIVATE|INTERFACE> <opt>...) 为特定目标添加编译选项(如警告级别、优化参数)。 target_compile_options(my_app PRIVATE -Wall -Wextra)

文件与依赖管理 (Files & Dependencies)

用于寻找系统第三方库、添加子模块以及处理文件系统的操作。

命令 命令格式 说明 可以直接用的使用示例
add_subdirectory add_subdirectory(source_dir [binary_dir]) 引入并执行一个子目录中的 CMakeLists.txt add_subdirectory(src)
add_subdirectory(third_party/fmt)
find_package find_package(<PackageName> [version] [REQUIRED]) 查找并加载外部第三方库(如 OpenCV, Boost 等)。配合 REQUIRED 找不到则报错。 find_package(OpenCV 4.0 REQUIRED)
target_link_libraries(my_app PRIVATE ${OpenCV_LIBS})
file file(<GLOB|MAKE_DIRECTORY|COPY|READ|WRITE> ...) 执行文件系统操作。常用 GLOB 收集文件(但不推荐用于源码),MAKE_DIRECTORY 创目录。 file(GLOB_RECURSE CPP_FILES "src/*.cpp")
file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/out)
configure_file configure_file(<input> <output>) 复制文件并替换其中的变量(将 @VAR@${VAR} 替换为 CMake 中的实际值)。 configure_file(config.h.in ${CMAKE_BINARY_DIR}/config.h)
include include(<file|module>) 载入并执行另一段 CMake 脚本(.cmake 文件)或自带的 CMake 模块。 include(FetchContent)
install install(TARGETS <target>... DESTINATION <dir>) 定义 make install 时的安装规则。可安装目标、文件或目录。 install(TARGETS my_app DESTINATION bin)
install(FILES README.md DESTINATION docs)

逻辑控制与列表操作 (Control Flow & Lists)

用于编写条件判断、循环和处理 CMake 中的数组(List)。

命令 命令格式 说明 可以直接用的使用示例
if / elseif / else / endif if(<condition>) ... endif() 条件判断。条件可以是变量是否存在、字符串比较、系统架构判断等。 if(WIN32)
message(STATUS "Windows")
elseif(APPLE)
message(STATUS "macOS")
endif()
foreach / endforeach foreach(<loop_var> <items>) ... endforeach() 遍历列表中的每一个元素。 set(MY_LIST a.cpp b.cpp)
foreach(f ${MY_LIST})
message(STATUS "File: ${f}")
endforeach()
list list(<APPEND|LENGTH|GET|REMOVE_AT|...> <list> ...) 对列表进行操作(追加、获取长度、删除指定元素等)。 set(MY_LIST "a;b")
list(APPEND MY_LIST "c") # 结果: a;b;c
function / endfunction function(<name> [arg1...]) ... endfunction() 定义一个函数。函数内有独立的变量作用域。 function(PrintMsg msg)
message(STATUS "MSG: ${msg}")
endfunction()
PrintMsg("Hello")
macro / endmacro macro(<name> [arg1...]) ... endmacro() 定义一个宏。与函数类似,但宏没有独立的作用域(直接在当前作用域展开)。 macro(AddDef arg)
add_compile_definitions(${arg})
endmacro()

CMake 常用变量

变量名 作用说明 使用示例
【路径与目录相关】
CMAKE_SOURCE_DIR 顶层 CMakeLists.txt 所在的绝对路径(即整个源码树的根目录)。 include_directories(${CMAKE_SOURCE_DIR}/include)
CMAKE_BINARY_DIR 顶层构建目录的绝对路径(即运行 cmake 命令的所在目录,通常是 build/)。 set(EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR}/bin)
CMAKE_CURRENT_SOURCE_DIR 当前正在处理的 CMakeLists.txt 所在的绝对路径。 aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/src SRC)
CMAKE_CURRENT_BINARY_DIR 当前正在处理的 CMakeLists.txt 对应的构建绝对路径。 configure_file(config.in ${CMAKE_CURRENT_BINARY_DIR}/config.h)
【项目相关】
PROJECT_NAME project() 命令设置的当前项目名称。 add_executable(${PROJECT_NAME} main.cpp)
PROJECT_SOURCE_DIR 最近一次调用 project()CMakeLists.txt 所在源码目录。 message(STATUS "Project src: ${PROJECT_SOURCE_DIR}")
PROJECT_BINARY_DIR 最近一次调用 project() 对应的构建目录。 set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib)
【编译与构建控制】
CMAKE_BUILD_TYPE 控制构建类型,常用值:Debug, Release, RelWithDebInfo, MinSizeRel set(CMAKE_BUILD_TYPE "Release")
CMAKE_CXX_STANDARD 指定全局的 C++ 标准(如 11, 14, 17, 20)。 set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
CMAKE_C_COMPILER 指定 C 语言的编译器路径(通常需在命令行或最开头设置)。 set(CMAKE_C_COMPILER "gcc")
CMAKE_CXX_COMPILER 指定 C++ 语言的编译器路径。 set(CMAKE_CXX_COMPILER "g++")
CMAKE_CXX_FLAGS 传递给 C++ 编译器的基础编译选项。 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -O3")
CMAKE_CXX_FLAGS_DEBUG 专门针对 Debug 模式的 C++ 编译选项(同理有 _RELEASE 等)。 set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -g -O0")
BUILD_SHARED_LIBS 全局开关,设为 ON 时,add_library 默认编译为动态链接库(Shared)。 set(BUILD_SHARED_LIBS ON)
【安装与依赖查找】
CMAKE_INSTALL_PREFIX 执行 make install 时的默认安装根路径(Linux 下通常默认为 /usr/local)。 set(CMAKE_INSTALL_PREFIX "/opt/myapp")
CMAKE_MODULE_PATH 指定 CMake 查找自定义模块(FindXXX.cmake)的额外路径。 list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
CMAKE_PREFIX_PATH find_package(), find_library() 等命令提供额外的搜索前缀路径。 list(APPEND CMAKE_PREFIX_PATH "/usr/local/Qt5")
【系统与平台标识】
WIN32 如果目标系统是 Windows,则该变量为 True if(WIN32)
  # Windows specific settings
endif()
UNIX 如果目标系统是 UNIX 或类 UNIX(包括 Linux, macOS),则为 True if(UNIX)
  # Unix specific settings
endif()
APPLE 如果目标系统是 macOS (Apple),则为 True if(APPLE)
  # macOS specific settings
endif()

变量使用示例

  1. 设置变量:使用 set(变量名 变量值)
    cmake
    set(MY_CUSTOM_VAR "Hello World")
  2. 读取变量:使用 ${变量名} 进行取值和字符串拼接。
    cmake
    message(STATUS "The value is: ${MY_CUSTOM_VAR}")
  3. 打印调试信息:常使用 message(STATUS "...") 来在 CMake 配置阶段打印变量的值,以验证路径或选项是否正确:
    cmake
    message(STATUS "Current Build Type is: ${CMAKE_BUILD_TYPE}")

动态库加载与 RPATH 相关

CMake 中 动态库运行时搜索路径(RPATH - Run-time search path) 非常核心变量。

在 Linux/UNIX 系统下,程序运行加载动态库时,如果不借助环境变量(如 LD_LIBRARY_PATH),就会依赖程序本身内部记录的 RPATH 去寻找。

变量名 作用说明 使用示例
CMAKE_INSTALL_RPATH 指定程序安装后的 RPATH。
当执行 make install 后,目标文件会被打上这个 RPATH 标记,决定了它在安装目录下运行时去哪里寻找依赖的动态库。
set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib")

# 或者使用相对路径(以自身所在目录为基准)
set(CMAKE_INSTALL_RPATH "$ORIGIN/../lib")
CMAKE_BUILD_RPATH 指定在构建目录(Build Tree)下生成目标的 RPATH。
主要用于在 build 文件夹中直接运行或调试程序时,让程序能正确找到刚编译好的或第三方依赖的动态库。
set(CMAKE_BUILD_RPATH "${CMAKE_BINARY_DIR}/lib")

# CMake 3.14+ 支持
CMAKE_BUILD_WITH_INSTALL_RPATH 编译阶段直接写入安装时的 RPATH。
默认情况下(OFF),CMake 在编译时会写入针对构建目录的 RPATH,在执行 make install 时再把 RPATH 替换/修改为 CMAKE_INSTALL_RPATH
如果设为 ON,CMake 构建时将直接写入安装 RPATH,安装时不再进行修改动作。
set(CMAKE_BUILD_WITH_INSTALL_RPATH ON)

RPATH 示例

CMake 默认的 RPATH 策略是:在构建树(Build tree)中带有全部 RPATH,但在安装(Install)时会清空 RPATH。

cmake
# 1. 告诉 CMake 在安装时保留 RPATH,而不是移除它
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)

# 2. 设置安装后的 RPATH
# "$ORIGIN" 代表可执行文件运行时所在的目录(Linux特有),这样支持绿色免安装(整体目录拷贝)
set(CMAKE_INSTALL_RPATH "$ORIGIN/../lib")

# 3. 如果希望编译时直接就打上 install 的 RPATH,不再在安装时去 relink(重新链接)
# (这对于构建和安装路径结构保持一致的项目很有用,能加快安装速度)
set(CMAKE_BUILD_WITH_INSTALL_RPATH ON)

ORIGIN 变量

$ORIGIN 并不是 CMake 的内置变量,而是 Linux/ELF 系统的动态链接器(Dynamic Linker)能识别的一个特殊字符串(运行时标记)

  • 运行时动态路径标记(配合 RPATH 使用)
标记名称 作用说明 使用示例
$ORIGIN
(Linux)
代表当前可执行文件或动态库在运行时的真实绝对路径。
使用它设置 RPATH,可以将寻找依赖库的绝对路径转化为相对路径。即使整个程序安装目录被移动到别的盘符,依然能找到依赖库。
set(CMAKE_INSTALL_RPATH "$ORIGIN/../lib")
@executable_path
(macOS)
代表当前可执行文件所在的目录。
macOS 下的动态加载器(dyld)专有标记,作用类似于 Linux 的 $ORIGIN,专门相对于主程序找依赖。
set(CMAKE_INSTALL_RPATH "@executable_path/../lib")
@loader_path
(macOS)
代表加载当前模块的实体所在的目录。
如果是在主程序中找库,它等同于 @executable_path;但如果是“插件A”找“库B”,它代表插件A的所在目录。更为通用。
set(CMAKE_INSTALL_RPATH "@loader_path/../lib")

在实际开发中,我们通常希望编译出来的程序目录(比如包含了 bin/lib/),直接打包发给用户解压就能运行。这就需要写一段跨平台的 CMake 脚本来分别处理 Linux 和 macOS 的相对路径标记:

cmake
# 针对不同操作系统,设置相对自身的 RPATH
if(UNIX AND NOT APPLE)
    # Linux 系统使用 $ORIGIN
    # 注意:在 CMake 中,单美元符号 $ 后面不加花括号 {},CMake 会将其视为普通字符串
    set(CMAKE_INSTALL_RPATH "$ORIGIN/../lib")

elseif(APPLE)
    # macOS 系统使用 @loader_path
    set(CMAKE_INSTALL_RPATH "@loader_path/../lib")
endif()

# 其他配套设置(确保安装时写入且应用这些规则)
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
set(CMAKE_BUILD_WITH_INSTALL_RPATH ON)

读取环境变量

CMakeLists.txt 中读取环境变量非常简单,主要是通过 $ENV{变量名} 的语法来实现。

cmake
# 打印系统的 PATH 环境变量
message(STATUS "当前的 PATH 环境变量为: $ENV{PATH}")

# 获取当前用户的 HOME 目录
message(STATUS "当前用户的 HOME 目录为: $ENV{HOME}")

# 读取名为 MY_CUSTOM_DIR 的环境变量,赋值给 CMake 变量 MY_DIR
set(MY_DIR "$ENV{MY_CUSTOM_DIR}")

# 后续使用 CMake 变量
include_directories(${MY_DIR}/include)

# 判断环境变量是否存在
# 检查名为 MY_SDK_PATH 的环境变量是否已定义
if(DEFINED ENV{MY_SDK_PATH})
    message(STATUS "找到 SDK 路径: $ENV{MY_SDK_PATH}")
    set(SDK_PATH $ENV{MY_SDK_PATH})
else()
    message(WARNING "未设置 MY_SDK_PATH 环境变量!")
endif()

# 读取环境变量并设置默认值
if(DEFINED ENV{CUSTOM_INSTALL_PREFIX})
    set(CMAKE_INSTALL_PREFIX $ENV{CUSTOM_INSTALL_PREFIX})
    message(STATUS "使用环境变量指定的安装路径: ${CMAKE_INSTALL_PREFIX}")
else()
    set(CMAKE_INSTALL_PREFIX "/usr/local/myapp")
    message(STATUS "使用默认安装路径: ${CMAKE_INSTALL_PREFIX}")
endif()

Python 环境

在 Linux 和 CMake 的开发环境中,Python_SITELIB(在较新的 CMake 版本中通常具体表现为 Python3_SITELIB 或 Python2_SITELIB)代表了当前找到的 Python 环境中,用于存放第三方纯 Python 库(.py 文件)的默认目录路径

CMake 3.12 引入的现代方法,去寻找 Python 示例,例如:

find_package(Python3 COMPONENTS Interpreter REQUIRED)

使用

编译

CMake 通常的编译步骤:

mkdir build && cd build
cmake ..
make

说明:

  • mkdir build 创建编译目录
  • cmake .. 指向CMakeLists.txt所在的目录,cmake会生成很多编译的中间文件以及makefile文件
  • make 根据生成makefile文件,编译程序

CMAKE_BUILD_TYPE

cmake 模式:

  • cmake -DCMAKE_BUILD_TYPE=Release
  • cmake -DCMAKE_BUILD_TYPE=Debug
  • cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo

区别:

  • man objcopy
    • Release --strip-debug 不从源文件中复制调试符号或部分
      • 调试时,可以指定 symbol gdb -s xxx.symbol 或在 gdb 命令中加载 symbol-file xxx.symbol
    • Debug --only-keep-debug 剥离文件,删除不会被 –strip-debug 剥离的部分内容,保留调试部分

CMAKE_VERBOSE_MAKEFILE

set(CMAKE_VERBOSE_MAKEFILE ON)

# 方式一
make VERBOSE=1

# 方式二
export VERBOSE=1
make

compile_commands.json

compile_commands.json 文件能够有效提高一些工具(比如说ccls1, vscode2)的代码跳转、补全等功能,参考

cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON --build .
make

示例

  • CMakeLists.txt 示例
# 1. 要求的cmake最低版本
cmake_minimum_required(VERSION 3.2)

# 2. 添加c++11标准支持
#set( CMAKE_CXX_FLAGS "-std=c++11" )

# 3. 指定项目的名称,一般和项目的文件夹名称对应
PROJECT(test_sqrt)

# 4. 头文件
INCLUDE_DIRECTORIES(
include
)

# 源文件目录
AUX_SOURCE_DIRECTORY(src DIR_SRCS)

# 5. 通过设定SRC变量,将源代码路径都给SRC,如果有多个,可以直接在后面继续添加。若不添加编译能够通过,但是执行的时候会出现各种问题,比如 "symbol lookup error xxxxx , undefined symbol"
SET(SRC
${DIR_SRCS}
)

# 6. 编译主函数,生成可执行文件
# 设置路径
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/build/bin)

# 可执行文件生成
ADD_EXECUTABLE(${PROJECT_NAME} ${SRC})

# 7. 创建共享库/静态库
# 设置路径
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/build/lib)

set(LIB_NAME test_sqrt_lib)
# 创建共享库(把工程内的cpp文件都创建成共享库文件,方便通过头文件来调用)
# 这时候只需要cpp,不需要有主函数
# ${PROJECT_NAME}是生成的库名 表示生成的共享库文件就叫做 lib工程名.so
# 也可以专门写cmakelists来编译一个没有主函数的程序来生成共享库,供其它程序使用
# SHARED为生成动态库,STATIC为生成静态库
add_library(${LIB_NAME} STATIC ${SRC})

# 8. 链接库文件
# 把刚刚生成的${PROJECT_NAME}库和所需的其它库链接起来
# 如果需要链接其他的动态库,-l后接去除lib前缀和.so后缀的名称,以链接 libtestsqrt.so 为例,-ltestsqrt
TARGET_LINK_LIBRARIES(${PROJECT_NAME} m)
  • 环境初始化
# 容器内编译
$ docker run --rm -it gcc:9.5.0 bash

# 安装依赖
$ sed "s#http://deb.debian.org/debian#https://mirrors.tuna.tsinghua.edu.cn/debian/#g" -i /etc/apt/sources.list
$ apt update
$ apt install cmake -y

# 源码初始化,CMakeLists.txt 参考示例文件
mkdir -p test_sqrt/src/ test_sqrt/include/

cat << EOF > test_sqrt/src/main.c
#include "../include/m.h"
#include <stdio.h>
int main(int argc, char** argv)
{
    double a = 81.0;
    double b = 0.0;

    printf("input a: %f\n", a);
    b = cal_sqrt(a);
    printf("sqrt result: %f\n",b);
    return 0;
}
EOF

cat << EOF > test_sqrt/src/m.c
#include "../include/m.h"

double cal_sqrt(double value)
{
    return sqrt(value);
}
EOF

cat << EOF > test_sqrt/include/m.h
#ifndef B_FILE_HEADER_INC
#define B_FIEL_HEADER_INC

#include<math.h>

double cal_sqrt(double value);

#endif
EOF
  • 编译
root@2f5346b34906:/# mkdir build && cd build
root@2f5346b34906:/test_sqrt/build# cmake ..
-- The C compiler identification is GNU 9.5.0
-- The CXX compiler identification is GNU 9.5.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/local/bin/c++
-- Check for working CXX compiler: /usr/local/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: /test_sqrt/build
root@2f5346b34906:/test_sqrt/build# make
Scanning dependencies of target test_sqrt
[ 16%] Building C object CMakeFiles/test_sqrt.dir/src/m.c.o
[ 33%] Building C object CMakeFiles/test_sqrt.dir/src/main.c.o
[ 50%] Linking C executable bin/test_sqrt
[ 50%] Built target test_sqrt
Scanning dependencies of target test_sqrt_lib
[ 66%] Building C object CMakeFiles/test_sqrt_lib.dir/src/m.c.o
[ 83%] Building C object CMakeFiles/test_sqrt_lib.dir/src/main.c.o
[100%] Linking C static library libtest_sqrt_lib.a
[100%] Built target test_sqrt_lib

# 二进制
root@2f5346b34906:/test_sqrt/build# bin/test_sqrt
input a: 81.000000
sqrt result: 9.000000

一个直接可用的现代 CMake 综合模板

一个标准 C++ 项目的起手式:

cmake
# 1. 基础配置
cmake_minimum_required(VERSION 3.15)
project(MyAwesomeProject VERSION 1.0.0 LANGUAGES CXX)

# 设置 C++ 标准
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# 2. 收集源文件(显式列出推荐做法)
set(APP_SOURCES
    src/main.cpp
    src/utils.cpp
)

# 3. 添加一个库 (假设有一个库目录)
add_library(MathLib STATIC src/math.cpp)
target_include_directories(MathLib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)

# 4. 声明可执行文件
add_executable(MyApp ${APP_SOURCES})

# 5. 链接依赖与头文件
target_link_libraries(MyApp PRIVATE MathLib)
target_include_directories(MyApp PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src)

# 6. 控制与输出
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
    message(STATUS "当前是 Debug 模式,开启额外警告")
    target_compile_options(MyApp PRIVATE -Wall -Wextra -g)
endif()

参考

  1. https://cmake.org/cmake/help/v3.1/
  2. https://github.com/Kitware/CMake/blob/master/Help/guide/tutorial/A%20Basic%20Starting%20Point.rst