Cmake 使用基本教程
首先创建一个项目
mkdir Tutorial
cd Tutorial
touch tutorial.cxx
tutorial.cxx内容如下:
第一步:从最基础开始
最简单的应用是在项目根目录下创建一个CMakeLists.txt文件,内容如下:
# 设置cmake最小要求版本
cmake_minimum_required(VERSION 3.10)
# 设置项目名称
project(Tutorial)
# 添加可执行文件
add_executable(Tutorial tutorial.cxx)
CMake支持大写,小写和大小写混合命令,上述示例使用小写方式。
添加版本号和配置头文件
第一个功能cmake_minimum_required是为我们的可执行文件和项目提供版本号。 虽然我们可以仅在源代码中执行此操作,但是使用CMakeLists.txt可提供更大的灵活性
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
// 配置选项和设置项目配置
#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;
}
指定c++标准
通过在tutorial.cxx中用std :: stod替换atof,将一些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_minimum_required(VERSION 3.10)
# 设置项目名称和版本
project(Tutorial VERSION 1.0)
# 指定c++标准
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)
构建和测试
运行cmake或cmake-gui以配置项目, 然后使用所选的构建工具进行构建。 或者切换到根目录下, 然后运行以下命令
mkdir step1_build
cd step1_build
cmake ../step1
cmake --build .
切换到构建Tutorial的目录(可能是make目录或Debug或Release构建配置子目录),然后运行以下命令
Tutorial 4294967296
Tutorial 10
Tutorial
第二步:添加一个库依赖
将库放入名为MathFunctions的子目录中。该目录已包含头文件MathFunctions.h和源文件mysqrt.cxx。
然后,在子目录MathFunctions目录的CMakeLists.txt文件中添加如下内容:
add_library(MathFunctions mysqrt.cxx)
为了利用新库,我们将在顶级CMakeLists.txt文件中添加add_subdirectory调用,以便构建该库。 将新库添加到可执行文件,并将MathFunctions添加为包含目录,以便可以找到mqsqrt.h头文件。 现在,顶层CMakeLists.txt文件的最后添加如下几行:
# 添加MathFunctions库
add_subdirectory(MathFunctions)
# 添加可执行文件
add_executable(Tutorial tutorial.cxx)
# 添加编译链接库
target_link_libraries(Tutorial PUBLIC MathFunctions)
# 将二叉树添加到包含文件的搜索路径
# 这样我们就可以找到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)
# 配置头文件以传递某些CMake设置到源代码中
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_executable(Tutorial tutorial.cxx)
target_link_libraries(Tutorial PUBLIC ${EXTRA_LIBS})
# 将二叉树添加到包含文件的搜索路径,这样我们就可以找到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可执行文件。
使用ccmake或CMake GUI更新USE_MYMATH的值。重新生成并再次运行本教程。 sqrt或mysqrt哪个函数可提供更好的结果。