2-添加库

    本节将学习如何在项目中创建和使用库,还将看到如何使库的使用成为可选的。

    本节中使用的示例代码下载见step1-简单开始cmake实践-CSDN博客

练习1 -创建一个库

    要在CMake中添加一个库,使用add_library()命令并指定哪些源文件应该组成该库。
    我们可以使用一个或多个子目录组织项目,而不是将所有源文件放在一个目录中。在本例中,我们将专门为库创建一个子目录。在这里,我们可以添加一个新的CMakeLists.txt文件和一个或多个源文件。在顶级的CMakeLists.txt文件中,我们将使用add_subdirectory()命令将子目录添加到构建中。
    创建库之后,使用target_include_directories()和target_link_libraries()将其连接到可执行目标。

目标

    添加并使用库。

开始

    在本练习中,我们将在项目中添加一个库,其中包含我们自己的用于计算数字平方根的实现。然后,可执行文件可以使用这个库,而不采用编译器提供的标准平方根函数。
    在本教程中,我们将把库放入名为MathFunctions的子目录中。这个目录已经包含了头文件MathFunctions.h和mysqrt.h。还提供了它们各自的源文件MathFunctions.cxx和mysqrt.cxx。我们不需要修改这些文件。mysqrt.cxx有一个名为mysqrt的函数,它提供了与编译器的SQRT函数类似的功能。MathFunctions.cxx包含一个函数SQRT,用于隐藏我们自己写的SQRT函数的实现细节。
     从在本文提供的代码实例文件夹下/Step2目录中,从TODO 1开始,完成TODO 6。
    首先,在MathFunctions子目录中填写一行CMakeLists.txt。
    接下来,编辑顶层的CMakeLists.txt。
    最后,使用tutorial.cxx中新创建的MathFunctions库。

操作

    在MathFunctions目录下的CMakeLists.txt文件中,我们使用add_library()创建了一个名为MathFunctions的库目标。库的源文件作为参数传递给add_library()。这看起来像下面这行:

// TODO 1: MathFunctions/CMakeLists.txt
add_library(MathFunctions MathFunctions.cxx mysqrt.cxx)

    为了使用新库,我们将在顶级CMakeLists.txt文件中添加add_subdirectory()调用,以便库将被构建。

// TODO 2: CMakeLists.txt
add_subdirectory(MathFunctions)

    接下来,使用target_link_libraries()将新的库目标链接到可执行目标。

// TODO 3: CMakeLists.txt

target_link_libraries(Tutorial PUBLIC MathFunctions)

    最后,我们需要指定库的头文件位置。修改现有的target_include_directories()调用,将MathFunctions子目录添加为包含目录,这样就可以找到MathFunctions.h头文件。

// TODO 4: CMakeLists.txt
target_include_directories(Tutorial PUBLIC
                          "${PROJECT_BINARY_DIR}"
                          "${PROJECT_SOURCE_DIR}/MathFunctions"
                          )

    现在让我们使用库。在tutorial.cxx中包含MathFunctions.h:

// TODO 5: tutorial.cxx

#include "MathFunctions.h"

    最后,用包装函数mathfunctions::sqrt替换sqrt。

// TODO 6: tutorial.cxx

  const double outputValue = mathfunctions::sqrt(inputValue);

编译和运行

mkdir Step2_build
cd Step2_build
cmake ../Step2
cmake --build .

    尝试使用编译好的项目,并确保它仍然产生准确的平方根值。

./Tutorial 4294967296
./Tutorial 10
./Tutorial

练习2 -添加选项

    现在让我们在MathFunctions库中添加一个选项,允许开发人员选择自定义的平方根实现或内置的标准实现。
    CMake可以使用option()命令执行此操作。这为用户提供了一个可以在配置cmake构建时更改的变量。

目标

    添加不使用MathFunctions函数的编译选项。

步骤

     首先使用MathFunctions/CMakeLists.txt中的option()命令创建一个变量USE_MYMATH。在同一个文件中,使用该选项将编译定义传递给MathFunctions库。
    然后,更新MathFunctions,基于USE_MYMATH重定向编译。
    最后,当USE_MYMATH打开时,通过在MathFunctions/CMakeLists.txt的USE_MYMATH块中使其成为自己的库。

操作

    第一步是在MathFunctions/CMakeLists.txt中添加一个选项,默认值为ON,可由用户更改。

// TODO 7: MathFunctions/CMakeLists.txt
option(USE_MYMATH "Use tutorial provided math implementation" ON)

    接下来,使用这个新选项使库与mysqrt函数的构建和链接成为有条件的选项。
    创建一个if()语句来检查USE_MYMATH的值。在if()块中,放入target_compile_definitions()命令和编译定义USE_MYMATH。

// TODO 8: MathFunctions/CMakeLists.txt
if (USE_MYMATH)
  target_compile_definitions(MathFunctions PRIVATE "USE_MYMATH")
endif()

条件判断

  • if (USE_MYMATH)
    

    这里使用了 CMake 的 if 命令来判断变量 USE_MYMATH 是否为真(即非空或者非零)。如果 USE_MYMATH 被定义为 ONTRUE、非空字符串或者被设置为一个非零数值,条件判断将会成立。

  • 目标编译定义

  1. target_compile_definitions(MathFunctions PRIVATE "USE_MYMATH")
    

    如果 USE_MYMATH 的条件成立,那么就会为目标 MathFunctions 添加一个编译定义。在这里,编译定义是 "USE_MYMATH"。这意味着在编译 MathFunctions 库或可执行文件时,会将 "USE_MYMATH" 添加到编译器的预处理器定义中。

  2. PRIVATE 关键字PRIVATE 关键字指定了这个编译定义的作用域。在 CMake 中,PRIVATE 表示这个定义只会影响到 MathFunctions 目标本身及其直接依赖的其他目标。这意味着其他使用 MathFunctions 的目标或库不会自动继承 "USE_MYMATH" 这个定义,除非它们也显式地声明。

    这段代码的作用是根据 USE_MYMATH 变量的值来决定是否为 MathFunctions 添加一个编译定义 "USE_MYMATH"。这样的做法通常用于根据不同的构建选项或条件,启用或禁用特定的功能或代码路径。

    当USE_MYMATH为ON时,编译定义USE_MYMATH将被设置。然后,我们可以使用这个编译定义来启用或禁用源代码的部分。
    接下来在MathFunctions.cxx文件中,我们让USE_MYMATH控制使用哪个平方根函数:

#ifdef USE_MYMATH
  return detail::mysqrt(x);
#else
  return std::sqrt(x);
#endif

    接下来,如果定义了USE_MYMATH,我们需要包含mysqrt.h。

// TODO 10: MathFunctions/MathFunctions.cxx

#ifdef USE_MYMATH
#  include "mysqrt.h"
#endif

    最后,在使用std::sqrt时,我们需要包含cmath。

// TODO 11 : MathFunctions/MathFunctions.cxx

#include <cmath>

    此时,如果USE_MYMATH为OFF, mysqrt.cxx不会被使用,但它仍然会被编译,因为MathFunctions目标有mysqrt.cxx列在来源下面。
    有几种方法可以解决这个问题。第一个选项是使用target_sources()来添加mysqrt.cxx从USE_MYMATH块中取出。另一个选择是在USE_MYMATH块中创建一个额外的库,它负责编译mysqrt.cxx。在本教程中,我们将创建一个额外的库。
    首先,在USE_MYMATH中创建一个名为SqrtLibrary的库,其源代码为mysqrt.cxx。

// TODO 12 : MathFunctions/CMakeLists.txt

  add_library(SqrtLibrary STATIC
              mysqrt.cxx
              )

  # TODO 6: Link SqrtLibrary to tutorial_compiler_flags

  target_link_libraries(MathFunctions PRIVATE SqrtLibrary)
endif()

    接下来,当启用USE_MYMATH时,我们将SqrtLibrary链接到MathFunctions。

// TODO 13 : MathFunctions/CMakeLists.txt

  target_link_libraries(MathFunctions PRIVATE SqrtLibrary)

    最后,我们可以从MathFunctions库源列表中删除mysqrt.cxxcxx,因为它将在包含SqrtLibrary时被拉入。

// TODO 14 : MathFunctions/CMakeLists.txt

add_library(MathFunctions MathFunctions.cxx)

    通过这些更改,mysqrt函数现在对于正在构建和使用MathFunctions库的人来说完全是可选的。用户可以切换USE_MYMATH来操作编译中使用的库。

编译并运行

    由于我们已经在练习1中配置了编译目录,我们可以通过简单地调用以下命令进行编译:

cd ../Step2_build
cmake --build .

    现在让我们将USE_MYMATH的值更新为OFF。

cmake ../Step2 -DUSE_MYMATH=OFF

    现在,用下面的代码重新编译代码:

cmake --build .

    然后,再次运行可执行文件,以确保它在USE_MYMATH设置为OFF时仍然工作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值