绝大多数软件项目构建的东西都旨在以某种方式被使用。它可以是其他软件项目使用的库,也可以是面向最终用户的应用程序。发布是将构建的项目提供给消费者的过程。

在 Gradle 中,该过程如下所示

  1. 定义要发布什么

  2. 定义要发布到哪里

  3. 执行发布

这些步骤中的每一个都取决于您要将工件发布到的存储库类型。最常见的两种类型是与 Maven 兼容和与 Ivy 兼容的存储库,或者简称为 Maven 和 Ivy 存储库。

从 Gradle 6.0 开始,Gradle 模块元数据 将始终与 Ivy XML 或 Maven POM 元数据文件一起发布。

Gradle 通过在 Maven 发布插件Ivy 发布插件 的形式提供一些预打包的基础设施,使发布到这些类型的存储库变得容易。这些插件允许您配置要发布的内容,并以最少的努力执行发布。

publishing process
图 1. 发布过程

让我们更详细地看一下这些步骤

发布内容

Gradle 需要知道要发布哪些文件和信息,以便消费者可以使用您的项目。这通常是 工件 和 Gradle 称为 发布 的元数据的组合。发布的具体内容取决于它发布到的存储库类型。

例如,一个发布到 Maven 存储库的发布包含

  • 一个或多个工件 - 通常由项目构建,

  • Gradle 模块元数据文件,它将描述已发布组件的变体,

  • Maven POM 文件将标识主工件及其依赖项。主工件通常是项目的生产 JAR,辅助工件可能包括“-sources”和“-javadoc”JAR。

此外,Gradle 将发布所有上述内容的校验和,以及 签名(如果配置为这样做)。从 Gradle 6.0 开始,这包括 SHA256SHA512 校验和。

发布位置

Gradle 需要知道将工件发布到哪里,以便消费者可以获取它们。这是通过 存储库 完成的,存储库存储和提供各种工件。Gradle 还需要与存储库交互,这就是为什么您必须提供存储库类型及其位置的原因。

发布方式

Gradle 自动为所有可能的发布和存储库组合生成发布任务,允许您将任何工件发布到任何存储库。如果您发布到 Maven 存储库,则任务类型为 PublishToMavenRepository,而对于 Ivy 存储库,任务类型为 PublishToIvyRepository

下面是一个演示整个发布过程的实际示例。

设置基本发布

发布的第一步,无论您的项目类型如何,都是应用相应的发布插件。如引言中所述,Gradle 通过以下插件支持 Maven 和 Ivy 存储库

这些插件提供了配置相应存储库类型发布所需的特定发布和存储库类。由于 Maven 存储库是最常用的存储库,因此它们将成为本示例以及本章中其他示例的基础。别担心,我们会解释如何调整针对 Ivy 存储库的各个示例。

假设我们正在使用一个简单的 Java 库项目,因此只应用了以下插件

build.gradle.kts
plugins {
    `java-library`
    `maven-publish`
}
build.gradle
plugins {
    id 'java-library'
    id 'maven-publish'
}

应用相应的插件后,您可以配置出版物和仓库。在本例中,我们希望将项目的生产 JAR 文件(由 `jar` 任务生成)发布到自定义 Maven 仓库。我们使用以下 `publishing {}` 块来实现,该块由 PublishingExtension 支持。

build.gradle.kts
group = "org.example"
version = "1.0"

publishing {
    publications {
        create<MavenPublication>("myLibrary") {
            from(components["java"])
        }
    }

    repositories {
        maven {
            name = "myRepo"
            url = uri(layout.buildDirectory.dir("repo"))
        }
    }
}
build.gradle
group = 'org.example'
version = '1.0'

publishing {
    publications {
        myLibrary(MavenPublication) {
            from components.java
        }
    }

    repositories {
        maven {
            name = 'myRepo'
            url = layout.buildDirectory.dir("repo")
        }
    }
}

这定义了一个名为 "myLibrary" 的出版物,由于其类型为 MavenPublication,因此可以发布到 Maven 仓库。此出版物仅包含生产 JAR 文件及其元数据,它们共同由项目的 `java` 组件 表示。

组件是定义出版物的标准方式。它们由插件提供,通常是语言或平台类型的插件。例如,Java 插件定义了 `components.java` SoftwareComponent,而 War 插件定义了 `components.web`。

该示例还定义了一个名为 "myRepo" 的基于文件的 Maven 仓库。这种基于文件的仓库对于示例来说很方便,但实际构建通常使用基于 HTTPS 的仓库服务器,例如 Maven Central 或内部公司服务器。

您可以定义一个且仅定义一个没有名称的仓库。这将转换为 Maven 仓库的隐式名称 "Maven" 和 Ivy 仓库的 "Ivy"。所有其他仓库定义都必须指定显式名称。

结合项目的 `group` 和 `version`,出版物和仓库定义提供了 Gradle 发布项目生产 JAR 所需的一切。Gradle 然后将创建一个专门的 `publishMyLibraryPublicationToMyRepoRepository` 任务来执行此操作。其名称基于模板 `publishPubNamePublicationToRepoNameRepository`。有关此任务的性质以及可能可用的其他任务的更多详细信息,请参阅相应的发布插件文档。

您可以直接执行单个发布任务,也可以执行 `publish`,这将运行所有可用的发布任务。在本例中,`publish` 将仅运行 `publishMyLibraryPublicationToMavenRepository`。

发布到 Ivy 仓库的基本操作非常相似:您只需使用 Ivy Publish 插件,将 `MavenPublication` 替换为 IvyPublication,并在仓库定义中使用 `ivy` 而不是 `maven`。

两种类型的仓库之间存在差异,特别是在它们支持的额外元数据方面——例如,Maven 仓库需要 POM 文件,而 Ivy 仓库有自己的元数据格式——因此,请参阅插件章节以获取有关如何为所使用的仓库类型配置发布和仓库的全面信息。

以上是基本用例的所有内容。但是,许多项目需要对发布的内容进行更多控制,因此我们在接下来的部分中将介绍几种常见场景。

抑制验证错误

Gradle 对生成的模块元数据进行验证。在某些情况下,验证可能会失败,表明您很可能需要修复错误,但您可能有意执行了某些操作。如果是这种情况,Gradle 将指示您可以在 GenerateModuleMetadata 任务上禁用的验证错误的名称。

build.gradle.kts
tasks.withType<GenerateModuleMetadata> {
    // The value 'enforced-platform' is provided in the validation
    // error message you got
    suppressedValidationErrors.add("enforced-platform")
}
build.gradle
tasks.withType(GenerateModuleMetadata).configureEach {
    // The value 'enforced-platform' is provided in the validation
    // error message you got
    suppressedValidationErrors.add('enforced-platform')
}