Ivy Publish插件提供了以Apache Ivy格式发布构建工件的功能,通常将其发布到存储库以供其他构建或项目使用. 发布的内容是由构建创建的一个或多个工件,以及一个Ivy 模块描述符 (通常为ivy.xml ),该描述描述了工件和工件的依赖项(如果有).

Gradle(请参阅声明依赖项 )和其他了解Ivy格式的工具可以使用已发布的Ivy模块. 您可以在发布概述中了解发布的基础知识.

Usage

要使用Ivy Publish插件,请在构建脚本中包括以下内容:

例子1.应用Ivy Publish插件
build.gradle
plugins {
    id 'ivy-publish'
}
build.gradle.kts
plugins {
    `ivy-publish`
}

常春藤发布插件使用命名的项目延期publishing类型的PublishingExtension . 此扩展提供了一个命名出版物的容器和一个命名存储库的容器. Ivy Publish插件可与IvyPublication出版物和IvyArtifactRepository仓库一起使用.

Tasks

generateDescriptorFileForPubNamePublicationGenerateIvyDescriptor

为名为PubName的发布创建一个Ivy描述符文件,填充已知的元数据,例如项目名称,项目版本和依赖项. 描述符文件的默认位置是build / publications / $ pubName / ivy.xml .

publishPubNamePublicationToRepoNameRepositoryPublishToIvyRepository

PubName发布发布到名为RepoName的存储库. 如果您的存储库定义中没有明确的名称,则RepoName将为" Ivy".

publish

取决于 :全部publish PubName PublicationTo RepoName Repository任务

将所有定义的发布发布到所有定义的存储库的聚合任务.

Publications

此插件提供出版物类型的IvyPublication . 要了解如何定义和使用发布,请参见基本发布部分.

您可以在Ivy发布中配置以下四项主要内容:

您可以在完整的发布示例中看到所有这些内容. IvyPublication的API文档包含其他代码示例.

Identity values for the published project

生成的Ivy模块描述符文件包含用于标识模块的<info>元素. 默认标识值从以下派生:

覆盖默认身份值很容易:在配置IvyPublication时只需指定organisationmodulerevision属性. 可以通过descriptor属性设置statusbranch -请参见IvyModuleDescriptorSpec .

descriptor属性还可用于将其他自定义元素添加为<info>元素的子元素,如下所示:

例子2.定制发布标识
build.gradle
publishing {
    publications {
        ivy(IvyPublication) {
            organisation = 'org.gradle.sample'
            module = 'project1-sample'
            revision = '1.1'
            descriptor.status = 'milestone'
            descriptor.branch = 'testing'
            descriptor.extraInfo 'http://my.namespace', 'myElement', 'Some value'

            from components.java
        }
    }
}
build.gradle.kts
publishing {
    publications {
        create<IvyPublication>("ivy") {
            organisation = "org.gradle.sample"
            module = "project1-sample"
            revision = "1.1"
            descriptor.status = "milestone"
            descriptor.branch = "testing"
            descriptor.extraInfo("http://my.namespace", "myElement", "Some value")

            from(components["java"])
        }
    }
}
💡

某些存储库无法处理所有受支持的字符. 例如,在发布到Windows上由文件系统支持的存储库时, :字符不能用作标识符.

Gradle将处理organisationmodulerevision (以及工件的nameextensionclassifier符)的任何有效Unicode字符. 明确禁止的唯一值是\/和任何ISO控制字符. 提供的值在发布过程的早期就得到了验证.

Customizing the generated module descriptor

有时,从项目信息生成的模块描述符文件需要在发布之前进行调整. Ivy Publish Plugin为此提供了DSL. 请参阅《 DSL参考》中的IvyModuleDescriptorSpec ,以获取可用属性和方法的完整文档.

下面的示例演示如何使用DSL最常见的方面:

例子3.定制模块描述符文件
build.gradle
    publications {
        ivyCustom(IvyPublication) {
            descriptor {
                license {
                    name = 'The Apache License, Version 2.0'
                    url = 'http://www.apache.org/licenses/LICENSE-2.0.txt'
                }
                author {
                    name = 'Jane Doe'
                    url = 'http://example.com/users/jane'
                }
                description {
                    text = 'A concise description of my library'
                    homepage = 'http://www.example.com/library'
                }
            }
            versionMapping {
                usage('java-api') {
                    fromResolutionOf('runtimeClasspath')
                }
                usage('java-runtime') {
                    fromResolutionResult()
                }
            }
        }
    }
build.gradle.kts
    publications {
        create<IvyPublication>("ivyCustom") {
            descriptor {
                license {
                    name.set("The Apache License, Version 2.0")
                    url.set("http://www.apache.org/licenses/LICENSE-2.0.txt")
                }
                author {
                    name.set("Jane Doe")
                    url.set("http://example.com/users/jane")
                }
                description {
                    text.set("A concise description of my library")
                    homepage.set("http://www.example.com/library")
                }
            }
            versionMapping {
                usage("java-api") {
                    fromResolutionOf("runtimeClasspath")
                }
                usage("java-runtime") {
                    fromResolutionResult()
                }
            }
        }
    }

在此示例中,我们只是在生成的Ivy依赖项描述符中添加了一个'description'元素,但是该挂钩允许您修改生成的描述符的任何方面. 例如,您可以将用于依赖项的版本范围替换为用于生成内部版本的实际版本.

您还可以通过IvyModuleDescriptorSpec.withXml(org.gradle.api.Action)将任意XML添加到描述符文件中,但是不能使用它来修改模块标识符的任何部分(组织,模块,修订版).

可以以不再是有效的Ivy模块描述符的方式修改描述符,因此在使用此功能时必须小心.

Customizing dependencies versions

支持两种策略来发布依赖项:

Declared versions (default)

此策略使用dependencies块中的依赖项声明发布由构建脚本作者定义的版本. 发布不会考虑任何其他类型的处理,例如通过更改已解决版本的规则进行的处理.

Resolved versions

此策略可能会通过应用解决方案规则和自动冲突解决方案来发布在构建期间已解决的版本. 这样做的好处是,发布的版本对应于测试发布的工件的版本.

解析版本的示例用例:

  • 项目将动态版本用于依赖项,但更喜欢将给定版本的已解析版本公开给其使用者.

  • 依赖项锁定结合使用,您要发布锁定的版本.

  • 一个项目利用了Gradle的丰富版本约束,这些约束对Ivy进行了有损转换. 它不依赖转换,而是发布已解决的版本.

这是通过使用versionMapping DSL方法完成的,该方法允许配置VersionMappingStrategy

例子4.使用解决的版本
build.gradle
    publications {
        ivyCustom(IvyPublication) {
            versionMapping {
                usage('java-api') {
                    fromResolutionOf('runtimeClasspath')
                }
                usage('java-runtime') {
                    fromResolutionResult()
                }
            }
        }
    }
build.gradle.kts
    publications {
        create<IvyPublication>("ivyCustom") {
            versionMapping {
                usage("java-api") {
                    fromResolutionOf("runtimeClasspath")
                }
                usage("java-runtime") {
                    fromResolutionResult()
                }
            }
        }
    }

在上面的示例中,Gradle将在runtimeClasspath上解析的版本用于api声明的依赖项,这些依赖项映射到Ivy的compile配置. Gradle还将在runtimeClasspath上解析的版本用于在implementation声明的依赖项,这些依赖项映射到Ivy的runtime配置. fromResolutionResult()表示Gradle应该使用变量的默认类路径, runtimeClasspathjava-runtime的默认类路径.

Repositories

该插件提供了IvyArtifactRepository类型的存储库 . 要了解如何定义和使用存储库进行发布,请参见" 基本发布 "部分.

这是定义发布存储库的简单示例:

示例5.声明要发布到的存储库
build.gradle
publishing {
    repositories {
        ivy {
            // change to point to your repo, e.g. http://my.org/repo
            url = "$buildDir/repo"
        }
    }
}
build.gradle.kts
publishing {
    repositories {
        ivy {
            // change to point to your repo, e.g. http://my.org/repo
            url = uri("$buildDir/repo")
        }
    }
}

您将要配置的两件事是存储库:

  • 网址(必填)

  • 名称(可选)

您可以定义多个存储库,只要它们在构建脚本中具有唯一的名称即可. 您也可以声明一个(只有一个)没有名称的存储库. 该存储库将采用隐式名称" Ivy".

您还可以配置连接到存储库所需的任何身份验证详细信息. 有关更多详细信息,请参见IvyArtifactRepository .

Complete example

The following example demonstrates publishing with a multi-project build. Each project publishes a Java component configured to also build and publish Javadoc and source code artifacts. The descriptor file is customized to include the project description for each project.

例子6.发布一个Java模块
build.gradle
subprojects {
    apply plugin: 'java'
    apply plugin: 'ivy-publish'

    version = '1.0'
    group = 'org.gradle.sample'

    repositories {
        mavenCentral()
    }
    java {
        withJavadocJar()
        withSourcesJar()
    }
}

project(':project1') {
    description = 'The first project'

    dependencies {
        implementation 'junit:junit:4.12'
        implementation project(':project2')
    }
}

project(':project2') {
    description = 'The second project'

    dependencies {
        implementation 'commons-collections:commons-collections:3.2.2'
    }
}

subprojects {
    publishing {
        repositories {
            ivy {
                // change to point to your repo, e.g. http://my.org/repo
                url = "${rootProject.buildDir}/repo"
            }
        }
        publications {
            ivy(IvyPublication) {
                from components.java
                descriptor.description {
                    text = description
                }
            }
        }
    }
}
build.gradle.kts
subprojects {
    apply(plugin = "java")
    apply(plugin = "ivy-publish")

    version = "1.0"
    group = "org.gradle.sample"

    repositories {
        mavenCentral()
    }
    val java = extensions.getByType<JavaPluginExtension>()
    java.withJavadocJar()
    java.withSourcesJar()
}

project(":project1") {
    description = "The first project"

    dependencies {
        "implementation"("junit:junit:4.12")
        "implementation"(project(":project2"))
    }
}

project(":project2") {
    description = "The second project"

    dependencies {
        "implementation"("commons-collections:commons-collections:3.2.2")
    }
}

subprojects {
    configure<PublishingExtension>() {
        repositories {
            ivy {
                // change to point to your repo, e.g. http://my.org/repo
                url = uri("${rootProject.buildDir}/repo")
            }
        }
        publications {
            create<IvyPublication>("ivy") {
                from(components["java"])
                descriptor.description {
                    text.set(description)
                }
            }
        }
    }
}

结果是将为每个项目发布以下工件:

  • Gradle模块元数据文件: project1-1.0.module .

  • Ivy模块元数据文件: ivy-1.0.xml .

  • Java组件的主要JAR工件: project1-1.0.jar .

  • Java组件的Javadoc和源JAR工件(因为我们配置了withJavadocJar()withSourcesJar() ): project1-1.0-javadoc.jarproject1-1.0-source.jar .

Migrating from legacy Ivy publication

如果要迁移以前依赖于旧版发布支持的项目,则会发现以下两种解决方案之间的差异.

Configurations marked as non transitive

当配置标记为transitive = false ,这不会映射到Ivy.

Gradle将发出警告,指出已发布此类配置. 如果确实需要发布此建议,则建议使用依赖项级别transitive = false .

Forced dependencies are not mapped

尽管常春藤支持在依赖项上使用force的概念,但Gradle不会将其自身已弃用的force声明与其映射.

相反,建议使用strictly版本替换Gradle force ,该版本提供更好的语义 ,并且受Gradle Module元数据格式支持.

注意,如果绝对需要发布强制,则仍然可以修改生成的ivy.xml .