CMake教程(二):创建并使用库
前言:一个大型 C++ 项目中经常需要使用到各种第三方库,本节主要介绍如何使用 cmake 生成并使用我们自己的库。所用到的资料是 CMake
官网 3.30.3 版的 Step2 目录下的文件。
本节所用材料的文件目录结构如下:
1. 创建库
通常,第三方库会放到一个子文件夹当中。为了使顶层 CMakeLists.txt
文件能够搜索到我们编写的第三方库,需要在顶层 CMakeLists.txt
文件中使用 add_subdirectories()
指令。此外,为了生成我们自己的库,需要在第三方库所在子目录 MathFunctions
下的 CMakeLists.txt
文件中使用 add_library()
指令。
下面介绍如何生成自己的库,然后在需要生成的可执行文件中使用我们自己创建的库。
- 在
MathFunctions/CMakeLists.txt
文件添加如下指令:
add_library(MathFunctions MathFunctions.cxx mysqrt.cxx)
add_library
中 MathFunctions
是库名称,MathFunctions.cxx
和 mysqrt.cxx
生成这个库时所依赖的源代码文件。
- 修改
Step2
目录下的CMakeLists.txt
文件,添加以下两条指令:
# 把第三方库添加到项目的搜索范围中
add_subdirectories(MathFunctions)
# 生成Tutorial 可执行文件时,需要依赖库 MathFunctions
target_link_libraries(Tutorial PUBLIC MathFunctions)
# 因为我们使用了自己编写的库,所以需要确保可以找得到库相关的头文件
target_include_directories(Tutorial PUBLIC
"${PROJECT_BINARY_DIR}"
"${PROJECT_SOURCE_DIR}/MathFunctions"
)
{PROJECT_SOURCE_DIR}
是指顶层 CMake
配置文件所在的目录。
3. 修改 tutorial.cxx
文件的内容:
#include "MathFunctions.h"
// 调用自己编写的sqrt函数
const double outputValue = mathfunctions::sqrt(inputValue);
后面就是创建一个 build 目录,然后使用指令 cmake ..
和 make
命令。
2. 增加选项
在大型项目当中,会用到许多第三方库。但有时我们需要在编译源代码时,有选择地链接第三方库。例如,我们的项目用到了 Sqlite3
和 MySQL
数据库,通常在编译时只需要指定一个即可。CMake
中的 option
指令让我们使用编译选项来配置 CMake
的构建过程。
接下来,我们通过设置 USE_MYMATH
变量来控制 cmake 在构建项目时是否使用我们自己编写的数学库。
下面介绍详细的步骤。
修改 MathFunctions/CMakeLists.txt
文件,按以下步骤修改相应的文件内容:
- 使用
option
指令添加编译选项开关。
option
指令用于定义一个可选的开关,使用户可以在CMake
配置时(运行cmake命令时指定-D<VARIABLE>=<ON|OFF>
选项)设置这个开关的值为ON
或OFF
。
# 设置 USE_MYMATH 变量的默认值为ON。字符串是对这个变量含义的描述
option(USE_MYMATH "Use tutorial provided math implementation" ON)
下面我们使用 if()
语句检查 USE_MYMATH
的值。在 if()
语句块中使用 target_compile_definitions
指令向指定的目标(如可执行文件、库等)添加编译定义(Compiler Definitions)。
target_compile_definitions
if (USE_MYMATH)
target_compile_definitions(MathFunctions PRIVATE "USE_MYMATH")
endif()
- 接下来,我们需要修改
MathFunctions.cxx
文件中的内容:
#ifdef USE_MYMATH
return detail::mysqrt(x);
#else
return std::sqrt(x);
#endif
- 下面,如果宏定义了
USE_MYMATH
,那么我们需要包含mysqrt.h
文件:
#ifdef USE_MYMATH
#include "mysqrt.h"
#endif
- 然后,我们需要直接包含
cmath
头文件:
#include <cmath>
但是现在有一个问题,如果USE_MYMATH
的值是 OFF
,尽管 mysqrt.h
未被包含,但仍然需要编译,这样会拖慢编译速度。
有几种方式解决这个问题,一种是使用 target_sources()
在USE_MYMATH
语句块内部添加mysqrt.cxx
。另一种方式是在 USE_MYMATH
语句块内创建一个负责编译 mysqrt.cxx
的额外库,就是把是否编译 mysqrt.cxx
设置成依赖于 USE_MYMATH
。下面我们使用第二种方式。
修改 MathFunctions/CMakeLists.txt
文件:
if(USE_MYMATH)
add_library(SqrtLibrary STATIC
mysqrt.cxx
)
# TODO 6: Link SqrtLibrary to tutorial_compiler_flags
target_link_libraries(MathFunctions PRIVATE SqrtLibrary)
endif()
本节放上按照以上步骤填充完整代码的源文件。
各位道友,码字不易,如有收获,记得一键三连啊。