Cmake官网教程学习记录

CmakeList.txt文件编写——Cmake教程



前言

CMake 教程提供了一个循序渐进的指南,涵盖了 CMake 可帮助解决的常见构建系统问题。
开始教程前需要下载 Cmake 项目,命令如下:

git clone https://ghproxy.com/https://github.com/Kitware/Cmake.git

本教程所用文件在目录 Help/guide/tutorial 下,使用 cd 命令导航到该目录下,使用 tree 命令查看目录结构及文件。


一、CmakeList.txt 文件基本结构

tutorial.cxx,CmakeList.txt,TutorialConfig.h.in 文件内容如下:

tutorial.cxx

// A simple program that computes the square root of a number
#include <cmath>
// #include <cstdlib> // TODO 5: Remove this line
#include <iostream>
#include <string>

// TODO 11: Include TutorialConfig.h
#include "TutorialConfig.h"

int main(int argc, char *argv[]) {
    if (argc < 2) {
        // TODO 12: Create a print statement using Tutorial_VERSION_MAJOR
        //          and Tutorial_VERSION_MINOR
        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;
        }

        std::cout << "Usage: " << argv[0] << " number" << std::endl;
        return 1;
    }

    // convert input to double
    // TODO 4: Replace atof(argv[1]) with std::stod(argv[1])
    const double inputValue = std::stod(argv[1]);

    // calculate square root
    const double outputValue = sqrt(inputValue);
    std::cout << "The square root of " << inputValue << " is " << outputValue
              << std::endl;
    return 0;
}

CmakeList.txt

# TODO 1: Set the minimum required version of CMake to be 3.10
cmake_minimum_required(VERSION 3.10)
# TODO 2: Create a project named Tutorial
project(Tutorial VERSION 1.0)
# TODO 7: Set the project version number as 1.0 in the above project command

# TODO 6: Set the variable CMAKE_CXX_STANDARD to 11
#         and the variable CMAKE_CXX_STANDARD_REQUIRED to True
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)
# TODO 8: Use configure_file to configure and copy TutorialConfig.h.in to
#         TutorialConfig.h
configure_file(TutorialConfig.h.in TutorialConfig.h)
# TODO 3: Add an executable called Tutorial to the project
# Hint: Be sure to specify the source file as tutorial.cxx
add_executable(Tutorial tutorial.cxx)
# TODO 9: Use target_include_directories to include ${PROJECT_BINARY_DIR}
target_include_directories(Tutorial PUBLIC "${PROJECT_BINARY_DIR}")

TutorialConfig.h.in

// the configured options and settings for Tutorial
// TODO 10: Define Tutorial_VERSION_MAJOR and Tutorial_VERSION_MINOR
#define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@
#define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@

1.1 最简单的结构

最基本的项目是由源代码文件构建的可执行文件。对于简单的项目,只需一个三行的 CMakeLists.txt 文件即可。这将是我们教程的起点。在 Step1 目录下创建一个 CMakeLists.txt 文件,其内容如下

cmake_minimum_required(VERSION 3.10)

# 设置项目名称
project(Tutorial)

# 添加可执行文件
add_executable(Tutorial tutorial.cxx)

请注意,本示例在 CMakeLists.txt 文件中使用了小写命令。CMake 支持大写、小写和混合大小写命令。tutorial.cxx 的源代码位于 Step1 目录中,可用于计算一个数字的平方根。

1.2 添加版本号和配置头文件

我们要添加的第一个功能是为可执行文件和项目提供版本号。虽然我们可以只在源代码中这样做,但使用 CMakeLists.txt 提供了更大的灵活性。

首先,修改 CMakeLists.txt 文件,使用 project 命令来设置项目名称和版本号。

cmake_minimum_required(VERSION 3.10)

# 设置项目名称和版本
project(Tutorial VERSION 1.0)

然后,配置一个头文件,将版本号传递给源代码:

configure_file(TutorialConfig.h.in TutorialConfig.h)

由于配置文件将被写入二叉树,我们必须将该目录添加到搜索包含文件的路径列表中。在 CMakeLists.txt 文件末尾添加以下几行:

target_include_directories(Tutorial PUBLIC
                           "${PROJECT_BINARY_DIR}"
                           )

使用您喜欢的编辑器,在源代码目录下创建 TutorialConfig.h.in,内容如下:

// the configured options and settings for Tutorial
#define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@
#define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@

当 CMake 配置此头文件时,@Tutorial_VERSION_MAJOR@ 和 @Tutorial_VERSION_MINOR@ 的值将被替换。

接下来修改 tutorial.cxx,使其包含已配置的头文件 TutorialConfig.h。

最后,我们按如下方法更新 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;
  }

1.3 指定 C++ 标准

接下来,让我们在 tutorial.cxx 中将 atof 替换为 std::stod,为项目添加一些 C++11 功能。同时,移除 #include 。

const double inputValue = std::stod(argv[1]);

我们需要在 CMake 代码中明确说明它应该使用正确的标志。在 CMake 中启用对特定 C++ 标准的支持的最简单方法是使用 CMAKE_CXX_STANDARD 变量。在本教程中,将 CMakeLists.txt 文件中的 CMAKE_CXX_STANDARD 变量设为 11,并将 CMAKE_CXX_STANDARD_REQUIRED 设为 True。确保将 CMAKE_CXX_STANDARD 声明添加到 add_executable 的调用之上。

cmake_minimum_required(VERSION 3.10)

# 设置项目名称和版本
project(Tutorial VERSION 1.0)

# 指定 C++ 标准
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)

1.4 构建和测试

运行 cmake 可执行文件或 cmake-gui 配置项目,然后使用所选的构建工具构建项目。

例如,我们可以从命令行导航到 CMake 源代码树的 Help/guide/tutorial 目录,然后创建一个构建目录:

mkdir Step1_build

接下来,导航至构建目录并运行 CMake 来配置项目并生成本地构建系统:

cd Step1_build
cmake ../Step1

然后调用构建系统来实际编译/链接项目:

cmake --build .

最后,尝试用这些命令使用新构建的 Tutorial:

./Tutorial 4294967296
./Tutorial 10
./Tutorial

二、添加库文件

现在,我们将为项目添加一个库。这个库将包含我们自己实现的计算数字平方根的方法。这样,可执行文件就可以使用这个库,而不是编译器提供的标准平方根函数。

在本教程中,我们将把该库放入名为 MathFunctions 的子目录中。该目录已包含一个头文件 MathFunctions.h 和一个源文件 mysqrt.cxx。源文件中有一个名为 mysqrt 的函数,其功能与编译器的 sqrt 函数类似。

在 MathFunctions 目录中添加以下一行 CMakeLists.txt 文件:

add_library(MathFunctions mysqrt.cxx)

为了使用新库,我们将在顶层 CMakeLists.txt 文件中添加 add_subdirectory 调用,以便联编该库。我们将新库添加到可执行文件中,并将 MathFunctions 添加为包含目录,以便找到 mysqrt.h 头文件。现在,顶层 CMakeLists.txt 文件的最后几行应该如下所示:

# add the MathFunctions library
add_subdirectory(MathFunctions)

# add the executable
add_executable(Tutorial tutorial.cxx)

target_link_libraries(Tutorial PUBLIC MathFunctions)

# add the binary tree to the search path for include files
# so that we will find TutorialConfig.h
target_include_directories(Tutorial PUBLIC
                          "${PROJECT_BINARY_DIR}"
                          "${PROJECT_SOURCE_DIR}/MathFunctions"
                          )

现在,让我们将 MathFunctions 库作为可选项。虽然对于本教程来说,确实没有必要这样做,但对于大型项目来说,这是经常发生的事情。第一步是在 CMakeLists.txt 文件的顶层添加一个选项。

option(USE_MYMATH "Use tutorial provided math implementation" ON)

# configure a header file to pass some of the CMake settings
# to the source code
configure_file(TutorialConfig.h.in TutorialConfig.h)

该选项将显示在 cmake-gui 和 ccmake 中,默认值为 ON,用户可自行更改。该设置将保存在缓存中,因此用户无需每次在编译目录上运行 CMake 时都设置该值。

下一个变化是使 MathFunctions 库的构建和链接成为有条件的。为此,我们将顶层 CMakeLists.txt 文件的末尾改成下面的样子:

if(USE_MYMATH)
  add_subdirectory(MathFunctions)
  list(APPEND EXTRA_LIBS MathFunctions)
  list(APPEND EXTRA_INCLUDES "${PROJECT_SOURCE_DIR}/MathFunctions")
endif()

# add the executable
add_executable(Tutorial tutorial.cxx)

target_link_libraries(Tutorial PUBLIC ${EXTRA_LIBS})

# add the binary tree to the search path for include files
# so that we will find TutorialConfig.h
target_include_directories(Tutorial PUBLIC
                           "${PROJECT_BINARY_DIR}"
                           ${EXTRA_INCLUDES}
                           )

注意使用 EXTRA_LIBS 变量来收集任何可选的库,以便以后链接到可执行文件中。变量 EXTRA_INCLUDES 同样用于可选头文件。这是处理许多可选组件的经典方法,我们将在下一步介绍现代方法。

对源代码的相应修改相当简单。首先,在 tutorial.cxx 中,如果需要,请包含 MathFunctions.h 头文件:

#ifdef USE_MYMATH
#  include "MathFunctions.h"
#endif

然后,在同一文件中,让 USE_MYMATH 控制使用哪个平方根函数:

#ifdef USE_MYMATH
  const double outputValue = mysqrt(inputValue);
#else
  const double outputValue = sqrt(inputValue);
#endif

由于源代码现在要求 USE_MYMATH,因此我们可以在 TutorialConfig.h.in 中加入以下一行:

#cmakedefine USE_MYMATH

练习: 为什么我们必须在 USE_MYMATH 选项之后配置 TutorialConfig.h.in?如果将两者颠倒过来会发生什么?

运行 cmake 可执行文件或 cmake-gui 配置项目,然后使用所选的构建工具构建项目。然后运行已构建的 Tutorial 可执行文件。

现在让我们更新 USE_MYMATH 的值。最简单的方法是在终端使用 cmake-gui 或 ccmake。或者,如果你想通过命令行更改该选项,也可以试试看:

cmake ../Step2 -DUSE_MYMATH=OFF

重建并重新运行教程。

sqrt 和 mysqrt 哪个函数的结果更好?

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码
< <上一篇
下一篇>>