注:
- 文章参考: 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 <iostream>
#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 <MathFunctions.h>
...
int main(int argc, char* argv[])
{
...
// 将`sqrt()`替换为`mysqrt()`
const double outputValue = mysqrt(inputValue);
...
}
- 点击状态栏中的
build按钮,重新构建. - 在终端中输入
.\build\tutorial.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 <cmath>
#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, 构建并运行, 查看运行结果.
本文指导如何在VSCode中使用CMake构建一个可选的数学库MathFunctions,包含mysqrt函数。通过CMake选项管理库的启用与编译,演示了如何在程序中条件调用。

238

被折叠的 条评论
为什么被折叠?



