C++ 库插件提供用于构建 C++ 库的任务、约定和配置。特别是,C++ 库提供了可供消费者(即使用此插件或其他C++ 应用程序插件的项目)使用的功能。

用法

build.gradle.kts
plugins {
    `cpp-library`
}
build.gradle
plugins {
    id 'cpp-library'
}

构建变体

C++ 库插件理解以下维度。有关更多信息,请阅读构建变体简介

构建类型 - 始终设置为 *debug* 和 *release*

构建类型控制生成二进制文件的可调试性以及优化。

  • debug - 生成调试符号且不优化二进制文件

  • release - 生成调试符号并优化,但从二进制文件中提取调试符号

链接方式 - 默认为 *shared*

链接方式表示应该创建共享库还是静态库。库可以生成共享库、静态库或两者。

链接方式可以配置如下

build.gradle.kts
library {
    linkage = listOf(Linkage.STATIC, Linkage.SHARED)
}
build.gradle
library {
    linkage = [Linkage.STATIC, Linkage.SHARED]
}
目标机器 - 默认为构建主机

目标机器表示应用程序期望运行的机器。目标机器由其操作系统和架构标识。Gradle 使用目标机器根据主机机器的可用性来决定选择哪个工具链。

目标机器可以按如下方式配置

build.gradle.kts
library {
    targetMachines = listOf(machines.linux.x86_64,
        machines.windows.x86, machines.windows.x86_64,
        machines.macOS.x86_64)
}
build.gradle
library {
    targetMachines = [
        machines.linux.x86_64,
        machines.windows.x86, machines.windows.x86_64,
        machines.macOS.x86_64
    ]
}

任务

下图显示了此插件添加的任务之间的关系。

请注意,C++ 库的默认链接方式是图示的共享链接。

cpp shared library task graph
图 1. C++ 库插件默认任务图

使用静态链接时,图表变为以下内容

cpp static library task graph
图 2. C++ 库插件仅静态库任务图

变体相关的任务

C++ 库插件根据库组件的变体创建任务。有关更多信息,请阅读构建变体简介。以下图表显示了变体相关任务之间的关系。

cpp library variant task graph
图 3. C++ 库插件变体相关任务图
取决于链接属性
compileVariantCpp(例如 compileDebugCppcompileReleaseCpp)- CppCompile

依赖于:所有为编译贡献源文件的任务 :: 使用选定的编译器编译 C++ 源文件。

linkVariant(例如 linkDebuglinkRelease)- LinkSharedLibrary(共享链接)

依赖于:所有有助于链接库的任务,包括通过项目依赖项解析的项目中的 linkVariantcreateVariant 任务 :: 使用选定的链接器从已编译的目标文件链接共享库。

createVariant(例如 createDebugcreateRelease)- CreateStaticLibrary(静态链接)

使用选定的归档器从已编译的目标文件创建静态库

assembleVariant(例如 assembleDebugassembleRelease)- 任务(生命周期)

依赖于:linkVariant(共享链接)或 createVariant(静态链接):: 聚合组装此库特定变体的任务。

生命周期任务

C++ 库插件将其某些任务附加到基础插件章节中记录的标准生命周期任务——C++ 库插件会自动应用该插件

assemble - 任务(生命周期)

依赖于:当链接方式包含 shared 时为 linkDebug,否则为 createDebug。:: 聚合任务,用于组装项目中当前主机(如果存在)的共享库(如果可用)的调试变体。此任务由基础插件添加。

check - 任务(生命周期)

执行验证任务(例如运行测试)的聚合任务。某些插件会将其自己的验证任务添加到 check。例如,C++ 单元测试插件将其测试任务附加到此生命周期任务。此任务由基础插件添加。

build - 任务(生命周期)

依赖于:check, assemble :: 执行项目完整构建的聚合任务。此任务由 Base 插件添加。

clean - 删除

删除构建目录及其中的所有内容,即 layout.buildDirectory 项目属性指定的路径。此任务由 Base 插件添加。

依赖管理

与 C++ 库插件创建的任务一样,根据库组件的变体创建了多个配置。有关更多信息,请阅读构建变体简介。以下图表描述了 C++ 库插件添加的配置

cpp library configurations
图 4. C++ 库插件配置
  • 白色配置是用户应该用来声明依赖项的配置

  • 粉色表示的配置,也称为可消费配置 (C),是组件编译、链接或运行库时使用的配置

  • 蓝色配置,也称为可解析配置,用 (R) 表示,是组件内部使用的配置

以下配置用于声明依赖项

api

用于声明 API 依赖项(参见API 与实现部分)。您应该在此处声明对消费者进行编译和链接时,需要传递导出的依赖项。

implementation 扩展 api

用于声明主组件所有变体的实现依赖项(参见API 与实现部分)。您应该在此处声明纯粹内部的,不打算向任何变体的消费者公开的依赖项。

mainVariantImplementation(例如 mainDebugImplementationmainReleaseImplementation)扩展 implementation

用于声明主组件特定变体的实现依赖项(参见API 与实现部分)。您应该在此处声明纯粹内部的,不打算向此特定变体的消费者公开的依赖项。

以下配置供消费者使用

cppApiElements 扩展 mainVariantImplementation

用于针对库进行编译。此配置旨在供消费者使用,以检索针对库编译所需的所有元素。

variantLinkElements(例如 debugLinkElementsreleaseLinkElements)扩展 mainVariantImplementation

用于针对库进行链接。此配置旨在供消费者使用,以检索针对库链接所需的所有元素。

variantRuntimeElements(例如 debugRuntimeElementsreleaseRuntimeElements)扩展 mainVariantImplementation

用于执行库。此配置旨在供消费者使用,以检索针对库运行所需的所有元素。

以下配置由库本身使用

cppCompileVariant(例如 cppCompileDebugcppCompileRelease)扩展 mainVariantImplementation

用于编译库。此配置包含库的编译包含根目录,因此在调用 C++ 编译器编译时使用。

nativeLinkVariant(例如 nativeLinkDebugnativeLinkRelease)扩展 mainVariantImplementation

仅用于链接共享库。此配置包含库的库,因此在调用 C++ 链接器链接时使用。

nativeRuntimeVariant(例如 nativeRuntimeDebugnativeRuntimeRelease)扩展 mainVariantImplementation

用于执行库。此配置包含库的运行时库。

API 与实现

该插件公开了两个可用于声明依赖项的配置:apiimplementationapi 配置应用于声明由库 API 导出的依赖项,而 implementation 配置应仅用于声明组件内部的依赖项。

示例 4. 添加依赖项
build.gradle.kts
library {
    dependencies {
        api("io.qt:core:5.1")
        implementation("io.qt:network:5.1")
    }
}
build.gradle
library {
    dependencies {
        api "io.qt:core:5.1"
        implementation "io.qt:network:5.1"
    }
}

出现在 api 配置中的依赖项将传递性地暴露给库的消费者,因此将出现在消费者的编译包含根目录和链接库中。另一方面,在 implementation 配置中找到的依赖项不会暴露给消费者,因此不会泄露到消费者的编译包含根目录和链接库中。这带来了几个好处

  • 依赖项不会泄露到消费者的编译包含根目录和链接库中,因此它们永远不会意外地依赖于传递依赖项

  • 由于减少了包含根目录和链接库,编译速度更快

  • 当实现依赖项发生更改时,重新编译次数更少,因为消费者无需重新编译

约定

C++ 库插件添加了源代码和任务的约定,如下所示。

项目布局

C++ 库插件假定如下所示的项目布局。这些目录都不需要存在或包含任何内容。C++ 库插件将编译它找到的任何内容,并忽略任何缺失的内容。

src/main/cpp

C++ 源文件,扩展名为 .cpp.C++.cc

src/main/headers

私有头文件 - 编译库所需但消费者不需要的头文件

src/main/public

公共头文件 - 编译库所需并由消费者要求的头文件

您可以通过配置 library 脚本块中的 sourceprivateHeaderspublicHeaders配置项目布局

compileVariantCpp 任务

C++ 库插件为要构建的库组件的每个变体(例如 compileDebugCppcompileReleaseCpp)添加一个 CppCompile 实例。有关更多信息,请阅读构建变体简介。下面显示了一些最常见的配置选项。

compilerArgs

[]

debuggable

true

includes

configurations.cppCompileVariant + library.publicHeaders + library.privateHeaders

macros

[:]

objectFileDir

layout.buildDirectory.dir("obj/main/$variant")

optimized

调试构建类型为 false,否则为 true

positionIndependentCode

共享链接为 true,否则为 false

source

library.cppSource

systemIncludes

从工具链派生

targetPlatform

从二进制文件的 TargetMachine 派生

toolChain

根据目标机器自动选择

C++ 库插件为每个包含共享链接作为维度的库变体添加一个 LinkSharedLibrary 实例——例如 linkDebuglinkRelease。有关更多信息,请阅读构建变体简介。下面显示了一些最常见的配置选项。

debuggable

true

libs

configurations.nativeLinkVariant

linkedFile

layout.buildDirectory.dir("lib/main/$variant/libBaseName[.so|dylib]") (*nix) 或 layout.buildDirectory.dir("lib\main\$variant\baseName.dll") (Windows)

linkerArgs

[]

source

compileVariantCpp.objects

targetPlatform

从二进制文件的 TargetMachine 派生

toolChain

根据目标机器自动选择

createVariant 任务

C++ 库插件为每个包含静态链接作为维度的库变体添加一个 CreateStaticLibrary 实例——例如 createDebugcreateRelease。有关更多信息,请阅读构建变体简介。下面显示了一些最常见的配置选项。

outputFile

layout.buildDirectory.dir("lib/main/variant/libBaseName.a") (*nix) 或 layout.buildDirectory.dir("lib\main\variant\baseName.lib") (Windows)

source

compileVariantCpp.objects

staticLibArgs

[]

targetPlatform

从二进制文件的 TargetMachine 派生

toolChain

根据目标机器自动选择