注:
- 文章参考: CMake Tutorial, 但操作方法和步骤与原文不同.
- 文章所有操作均在VSCode中完成.点击Windows 上VS Code + CMake + MSYS2 打造C++开发环境, 获取配置VSCode开发环境的详细步骤.
- 点击CMake 教程, 进入CMake教程主页.
现在我们将向我们的项目添加一个库。这个库将包含我们自己的计算一个数的平方根的实现。可执行程序可以使用这个库,而不是编译器提供的标准平方根函数。
在本教程中,我们将把库放到一个名为MathFunctions的子目录中。该目录已经包含一个头文件MathFunctions.h和一个源文件mysqrt.cxx。源文件有一个名为mysqrt的函数,它提供了类似于编译器的sqrt函数的功能。
- 在上一节的工程目录下, 创建名为MathFunctions的文件夹
- 在文件夹MathFunctions中新建名为MathFunctions.h的头文件, 文件内容如下:
#ifndef _MATH_FUNCTIONS_H_ #define _MATH_FUNCTIONS_H_ double mysqrt(double x); #endif
- 在文件夹MathFunctions中新建名为mysqrt.cxx的源文件, 文件内容如下:
#include#include "MathFunctions.h" // a hack square root calculation using simple operations double mysqrt(double x) { if (x <= 0) { return 0; } double result = x; // do ten iterations for (int i = 0; i < 10; ++i) { if (result <= 0) { result = 0.1; } double delta = x - (result * result); result = result + 0.5 * delta / result; std::cout << "Computing sqrt of " << x << " to be " << result << std::endl; } return result; }
- 在文件夹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"
)
- 在tutorial.cxx中包含MathFunctions.h, 并将sqrt()函数替换为mysqrt()函数
... // 包含头文件 #include... int main(int argc, char* argv[]) { ... // 将`sqrt()`替换为`mysqrt()` const double outputValue = mysqrt(inputValue); ... }
- 点击状态栏中的build按钮,重新构建.
- 在终端中输入.buildtutorial.exe 100, 运行结果如下所示.
现在让我们将MathFunctions库设为可选的。通过设置一个USE_MYMATH的开关, 让CMake决定使用MathFunctions中的mysqrt()或是cmath中的sqrt(). 对于本教程来说,确实没有必要这样做,但对于大型项目来说,这种情况很常见。
- 在顶级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和cmake中显示,默认值为ON,用户可以更改。这个设置将被存储在缓存中,这样用户就不需要每次在构建目录上运行CMake时都要设置这个值。下面我将介绍使用vscode修改该选项的方法
-
下一个修改是让MathFunctions库的构建和链接成为有条件的。为此,我们将创建一个if语句来检查选项的值。在if块中,将上面的add_subdirectory()命令和一些额外的列表命令放在一起,以存储链接到库所需的信息,并将子目录添加为教程目标中的包含目录。顶层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做如下修改:
... #ifdef USE_MYMATH #include "MathFunctions.h" #else #include#endif ... int main(int argc, char* argv[]) { ... #ifdef USE_MYMATH const double outputValue = mysqrt(inputValue); #else const double outputValue = sqrt(inputValue); #endif ... }
- 由于源代码现在需要USE_MYMATH,我们可以将它添加到TutorialConfig.h.in,如下所示:
#cmakedefine USE_MYMATH
- 使用vscode可以修改该选项是否启用.
- 打开命令托盘(Ctrl + Shift + P), 输入"cme", 选择CMake: Edit CMake Cache(UI)
- 在搜索框中输入"use_", 点击"USE_MYMATH"后的复选框, 可在"ON"|"OFF"间切换.
当USE_MYMATH设置为ON时, 调用mysqrt()的代码行变为启用状态, 相应的, 调用sqrt()的代码行变为禁用状态.反之亦然.
分别将USE_MYMATH设置为ON和OFF, 构建并运行, 查看运行结果.



