前言
本文算是对官方文档的翻译内容吧,不算多么深的技术。也将其中的代码发布到Github。跟官网一样,也是一步步的来。
开始(Step 1)
大部分基础项目都是从源代码文件编译成可执行文件。对于一个简单的项目来说,CMakeLists.txt
只需要三行就可以解决。
创建一个CMakeLists.txt
文件,在Step1
的文件夹中:
# 设置cmake最低的版本号
cmake_minimum_required(VERSION 3.10)
# 设置项目名
project(Tutorial)
# 添加可执行的文件
add_executable(Tutorial tutorial.cc)
注意在这个例子中使用了小写的命令。大写、小写或者大小写都用的命令在CMake
中都是被支持的。
tutorial.cc
的源代码是一个能够计算一个数的平方根。
添加版本号和头文件
第一个功能是我们给可执行文件和项目添加版本号。尽管我们可以在源代码中这样操作,但是使用CMake
可以提供更大的灵活性。
首先,修改CMakeLists.txt
文件以使用project()
命令设置项目名称和版本号:
# 设置项目名和版本号
project(Tutorial VERSION 1.0)
之后,配置头文件将版本号传给源代码:
configure_file(tutorial.h.in tutorial.h)
由于已配置的文件将被写入二叉树,因此我们必须将该目录添加到路径列表中以搜索包含文件。将代码添加到CMakeLists.txt
文件的末尾:
target_include_directories(Tutorial PUBLIC
"${PROJECT_BINARY_DIR}"
)
在源目录中创建tutorial.h.in
:
#define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@
#define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@
当CMake
配置头文件的时候,@Tutorial_VERSION_MAJOR@
和@Tutorial_VERSION_MINOR@
都会被替换掉。
下一步,修改tutorial.cc
,包含头文件tutorial.h
。
最后,通过更新tutorial.cc
来打印版本号:
if (argc < 2) {
// 打印版本号
std::cout << argv[0] << " Version " << Tutorial_VERSION_MAJOR << "."
<< Tutorial_VERSION_MINOR << std::endl;
std::cout << "Usage: " << argv[0] << " number" << std::endl;
return 1;
}
指定C++标准
# 指定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 25
the sqrt of 25 is 5
添加库文件(Step 2)
现在我们向我们的项目中添加一个库文件。这个库文件将会包含我们自己实现的求一个数的平方根。然后可执行文件使用此库而不是编译器提供的标准·平方根函数。
作为教程,我们将这个库文件放在名为MathFunctions
的子目录中。这个子目录包含着``mysqrt.h的头文件和
mysqrt.cc的源代码文件。这个源代码文件中包含一个叫
mysqrt的函数提供了与编译器的
sqrt`函数类似的功能。
将下面这行添加到MathFuntions
目录下的CMakeLists.txt
中:
add_library(MathFunctions mysqrt.cc)
为了能够调用库文件,我们将Step2
文件夹中的CMakeLists.txt
文件中添加一个add_subdirectory()
以便构建该库。我们将新库添加到可执行文件并将MathFunctions
作为包含文件以便可以找到mysqrt.h
头文件。
# 设置cmake最低的版本号
cmake_minimum_required(VERSION 3.10)
# 设置项目名和版本号
project(Tutorial VERSION 1.0)
# 指定C++标准
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)
configure_file(tutorial.h.in tutorial.h)
# 添加可执行的文件
add_executable(Tutorial tutorial.cc)
# 添加MathFunctions库
add_subdirectory(MathFunctions)
# 添加可执行程序
add_executable(Tutorial tutorial.cc)
target_link_libraries(Tutorial PUBLIC MathFunctions)
# 将二叉树添加到包含文件的搜索路径以便让我们能够找到tutorial.h
target_include_directories(Tutorial PUBLIC
"${PROJECT_BINARY_DIR}"
"${PROJECT_SOURCE_DIR}/MathFunctions"
)
对于大型的项目来说,CMakeLists.txt
可以设置MathFunctions
库设为可选。
option(USE_MYMATH "Use tutorial provided math implementation" ON)
# 配置头文件以传递某些CMake设置到源代码
configure_file(tutorial.h.in tutorial.h)
此设置存储在缓存中,因此用户无需在每次构建目录上运行CMake时都设置该值。
下一个更改是使编译和链接MathFunctions
库成为条件:
if(USE_MYMATH)
add_subdirectory(MathFunctions)
list(APPEND EXTRA_LIBS MathFunctions)
list(APPEND EXTRA_INCLUDES "${PROJECT_SOURCE_DIR}/MathFunctions")
endif()
# 添加可执行程序
add_executable(Tutorial tutorial.cc)
target_link_libraries(Tutorial PUBLIC ${EXTRA_LIBS})
# 将二叉树添加到包含文件的搜索路径以便让我们能够找到tutorial.h
target_include_directories(Tutorial PUBLIC
"${PROJECT_BINARY_DIR}"
${EXTRA_INCLUDES}
)
注意使用变量EXTRA_LIBS
来收集所有可选库,以供以后链接到可执行文件中。
变量EXTRA_INCLUDES
用于可选的头文件。当处理许多可选组件时,这是一种经典方法。
对源代码的相应更改非常简单。
首先,如果需要,在tutorial.cc
中包含MathFunctions.h
头文件
#ifdef USE_MYMATH
#include "MathFunctions.h"
#endif
然后相同的文件中使USE_MYMATH
控制使用那个平方根函数
#ifdef USE_MYMATH
const double outputValue = mysqrt(inputValue);h
#else
const double outputValue = sqrt(inputValue);
#endif
之后在tutorial.h.in
中添加:
#cmakedefine USE_MYMATH