版权声明:本文翻译自《CMake tutorial v3.16》。未经作者允许,严禁用于商业出版,否则追究法律责任。网络转载请注明出处!!!
CMake教程提供了逐步指南,涵盖了CMake可以帮助解决的常见构建系统问题。 了解示例项目中各个主题如何协同工作将非常有帮助。 示例的教程文档和源代码可在CMake源代码树的Help/guide/tutorial
目录中找到。 每个步骤都有其自己的子目录,其中包含可以用作起点的代码。 教程示例是渐进式的,因此每个步骤都为上一步提供了完整的解决方案。
1 基本起点(第1步)
最基本的项目是从源代码文件构建一个可执行文件。 对于简单的项目,只需三行CMakeLists.txt
文件。 这是本教程的起点。 在Step1目录中创建一个CMakeLists.txt
文件,如下所示:
cmake_minimum_required(VERSION 3.10)
# set the project name
project(Tutorial)
# add the executable
add_executable(Tutorial tutorial.cxx)
请注意,此示例在CMakeLists.txt
文件中使用小写的命令。 CMake支持大写,小写和大小写混合的命令。 Step1目录中提供了tutorial.cxx
的源代码,可用于计算数字的平方根。
1.1 添加版本号和配置头文件
我们将添加的第一个功能是为我们的可执行文件和项目提供版本号。 虽然我们可以仅在源代码中执行此操作,但是使用CMakeLists.txt
可以提供更大的灵活性。
首先,修改CMakeLists.txt
文件来设置版本号。
cmake_minimum_required(VERSION 3.10)
# set the project name and version
project(Tutorial VERSION 1.0)
###早期版本的写法
### project(Tutorial)
### set (Tutorial_VERSION_MAJOR 1)
### set (Tutorial_VERSION_MINOR 0)
然后,配置一个头文件,将版本号传递给源代码:
configure_file(TutorialConfig.h.in TutorialConfig.h)
###早期版本的写法
### configure_file ("${PROJECT_SOURCE_DIR}/TutorialConfig.h.in" "${PROJECT_BINARY_DIR}/TutorialConfig.h")
由于配置的文件将被写入二进制树中,所以我们必须将该目录添加到搜索include文件的路径列表中。在CMakeLists.txt
文件的末尾添加以下行:
#必须在add_excutable之后
target_include_directories(Tutorial PUBLIC "${PROJECT_BINARY_DIR}")
###早期版本的写法:
###可以位于任意位置,一般放在add_excutable之前
### include_directories("${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;
}
完整的CMakeLists.txt
如下:
cmake_minimum_required(VERSION 3.10)
#set project name and version
project(Tutorial VERSION 1.0)
configure_file(TutorialConfig.h.in TutorialConfig.h)
#add the executable
add_executable(Tutorial tutorial.cxx)
target_include_directories(Tutorial PUBLIC "${PROJECT_BINARY_DIR}" )
1.2 指定c++标准
接下来,通过在tutorial.cxx
中用std::stod
替换atof,将一些C ++ 11功能添加到我们的项目中。 同时,删除#include <cstdlib>
。
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_minimum_required(VERSION 3.10)
# set the project name and version
project(Tutorial VERSION 1.0)
# specify the C++ standard
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)
1.3 构建和测试
运行cmake或cmake-gui以配置项目,然后使用所选的构建工具进行构建。
例如,从命令行我们可以导航到CMake源代码树的Help /guide/tutorial
目录并运行以下命令:
mkdir Step1_build
cd Step1_build
cmake ../Step1
cmake --build .
导航到构建教程的目录(可能是make目录或Debug或Release构建配置子目录),然后运行以下命令:
Tutorial 4294967296
Tutorial 10
Tutorial
2 添加库(第2步)
现在,我们将添加一个库到我们的项目中。 该库是我们自己的实现的用于计算数字的平方根的库。 可执行文件可以使用此库,而不是使用编译器提供的标准平方根函数。
在本教程中,我们将库放入名为MathFunctions
的子目录中。 该目录已包含头文件MathFunctions.h
和源文件mysqrt.cxx
。 源文件具有一个称为mysqrt
的函数,该函数提供与编译器的sqrt
函数类似的功能。
将以下一行CMakeLists.txt
文件添加到MathFunctions
目录中:
add_library(MathFunctions mysqrt.cxx)
为了使用新的库,我们将在顶层CMakeLists.txt
文件中添加add_subdirectory
调用,以便构建该库。 我们将新的库添加到可执行文件,并将MathFunctions
添加为include目录,以便可以找到mqsqrt.h
头文件。 顶级CMakeLists.txt
文件的最后几行现在应如下所示:
# add the MathFunctions library
add_subdirectory(MathFunctions)
# add the executable
add_executable(Tutorial tutorial.cxx)
#必须位于add_excutable之后
target_link_libraries(Tutorial PUBLIC MathFunctions)
###早期版本的写法
### target_link_libraries(Tutorial 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)
#必须位于add_executable之后
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})
###早期版本的写法
### if(USE_MYMATH)
### include_directories ("${PROJECT_SOURCE_DIR}/MathFunctions")
### add_subdirectory (MathFunctions)
### set(EXTRA_LIBS ${EXTRA_LIBS} MathFunctions)
### endif(USE_MYMATH)
### include_directories("${PROJECT_BINARY_DIR}")
### add_executable(Tutorial tutorial.cxx)
### target_link_libraries(Tutorial ${EXTRA_LIBS})
请注意,使用变量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可执行文件。
使用ccmake或CMake GUI更新USE_MYMATH
的值。 重新生成并再次运行本教程。 sqrt或mysqrt哪个函数可提供更好的结果?
完整的CMakeLists.txt
文件如下:
cmake_minimum_required(VERSION 3.5)