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

在 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”。所有其他存储库定义都必须给定一个显式名称。

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

您可以直接执行单个发布任务,也可以执行 publish,它将运行所有可用的发布任务。在此示例中,publish 将只运行 publishMyLibraryPublicationToMavenRepository

基本发布到 Ivy 存储库非常相似:您只需使用 Ivy 发布插件,将 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')
}