参考官方cmake3.24教程翻译
https://cmake.org/cmake/help/v3.24/guide/tutorial/index.html
https://gitlab.kitware.com/cmake/cmake/-/tree/master/Help/guide/tutorial
step2
https://cmake.org/cmake/help/v3.24/guide/tutorial/Adding%20a%20Library.html
我的仓库 :
https://github.com/FRBoiling/cmake-tutorial.git
现在,我们将向项目添加一个库。这个库将包含我们自己的计算数字平方根的实现。然后,可执行文件就可以使用这个库,而不是编译器提供的标准平方根函数。
在本教程中,我们将把库放入名为MathFunctions的子目录中。这个目录包含一个头文件MathFunctions.h和一个源文件mysqrt.cxx。源文件有一个名为mysqrt的函数,它提供了与编译器的sqrt函数类似的功能。
将以下一行CMakeLists.txt文件添加到MathFunctions目录:
进入项目文件夹Step2,创建子目录MathFunctions,这个目录包含一个头文件MathFunctions.h、一个源文件mysqrt.cxx和一个CMakeLists.txt文件
mkdir Step2 Step2_build
cd Step2
mkdir MathFunctions
cd MathFunctions
touch MathFunctions.h mysqrt.cxx CMakeLists.txt
MathFunctions.h 内容如下:
double mysqrt(double x);
mysqrt.cxx 中内容如下:
#include
// 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;
}
CMakeLists.txt 内容如下
add_library(MathFunctions mysqrt.cxx)
项目结构如下:
为了使用新库,我们将在顶级目录(Step2)CMakeLists.txt文件中添加一个add_subdirectory()调用,以便构建库。我们将新的库添加到可执行文件中,并添加MathFunctions作为include目录,以便可以找到MathFunctions.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"
)
现在让我们将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(tutorial_config.h.in tutorial_config.h)
该选项将显示在cmake-gui和ccmake中,其默认值为ON,用户可以更改该值。该设置将存储在缓存中,这样用户就不需要每次在构建目录上运行CMake时都设置该值。
下一个更改是将构建和链接MathFunctions库设置为条件。为此,我们将创建一个if语句来检查该选项的值。在if块中,放入上面的add_subdirectory()命令和一些附加的列表命令,以存储链接到库所需的信息,并将子目录作为include目录添加到教程目标中。顶级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中包括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
最终 Step2/CMakeLists.txt内容如下
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)
# should we use our own math functions
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)
# add the MathFunctions library
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}
)
tutorial.cxx 内容如下
#include
#include
#include
#include
#include "tutorial_config.h"
#ifdef USE_MYMATH
#include "math_functions.h"
#endif
int main(int argc, char *argv[])
{
// if(argc<2){
// fprintf(stdout, "Uage: %s number\n", argv[0]);
// return 1;
// }
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;
}
// double inputValue = atof(argv[1]);
const double inputValue = std::stod(argv[1]);
#ifdef USE_MYMATH
const double outputValue = mysqrt(inputValue);
#else
const double outputValue = sqrt(inputValue);
#endif
fprintf(stdout, "The square root of %g is %g\n", inputValue, outputValue);
return 0;
}
1、Why is it important that we configure tutorial_config.h.in after the option for USE_MYMATH?
2、What would happen if we inverted the two?
运行cmake可执行文件或cmake-gui来配置项目,然后使用您选择的构建工具构建它。然后运行构建的Tutorial可执行文件。
现在让我们更新USE_MYMATH的值。
最简单的方法是在终端中使用cmake-gui或ccmake。
你也可以通过从命令行修改这个选项,如下
哪个函数给出更好的结果,sqrt还是mysqrt?