定义一个工件以用作另一个项目中的依赖项

Define an artifact to be used as a dependency in another project

TL;DR

我正在尝试配置两个 Gradle 项目,其中一个项目使用另一个项目构建的文件。 第一个项目由 includeBuild 添加到第二个项目,文件在第二个项目中定义为依赖项。

项目testA

settings.gradle:

rootProject.name = 'testA'

build.gradle:

group = 'org.test'
version = '0.0.0.1_test'

task someZip (type: Zip) {
    from './settings.gradle'
    archiveName = 'xxx.zip'
    destinationDir = file("${buildDir}/test")
}

artifacts {
    //TODO add something here?
}

项目testB

settings.gradle:

rootProject.name = 'testB'

if (System.getenv('LOCAL_COMPILATION') == 'true') {
    includeBuild '../testA'
}

build.gradle:

if (System.getenv('LOCAL_COMPILATION') != 'true') {
    repositories {
        maven { url '192.168.1.100' }
    }
}

configurations {
    magic
}

dependencies {
    magic 'org.test:xxx:0.0.0.+@zip'
}

task ultimateZip (type: Zip) {
    from configurations.magic
    archiveName = 'ultimate.zip'
    destinationDir = file("${buildDir}/ultimate-test")
}

描述

您可能注意到该示例有一个使用 maven 存储库的选项。我想强调的是,最终将有可能做到这一点。 使用 Maven 存储库不是这个问题的重点,但是,除了解决方案之外,不应干扰它。 (换句话说,您可以假设 System.getenv('LOCAL_COMPILATION') == 'true'。)

问题是如何以其他项目能够识别的方式定义工件。

首选解决方案应该类似于 Java 插件所做的,因为我在我的项目中使用 jar 依赖项并且它们通过 includeBuild 和存储库工作。

以下设置应该有效(使用 Gradle 5.5.1 测试)。它主要对应于您的原始设置,但 XXX.

指示的更改除外

项目testA

settings.gradle:

rootProject.name = 'testA'

build.gradle:

group = 'org.test'
version = '0.0.0.1_test'

task someZip (type: Zip) {
    from './settings.gradle'
    archiveName = 'xxx.zip'
    destinationDir = file("${buildDir}/test")
}

// XXX (replaced your empty "artifacts" block)
configurations.create('default')
def myArtifact = artifacts.add('default', someZip) {
    name = 'xxx'
}

// XXX (only added to show that publishing works)
apply plugin: 'maven-publish'
publishing {
    repositories {
        maven { url = 'file:///tmp/my-repo' }
    }
    publications {
        myPub(MavenPublication) {
            artifactId myArtifact.name
            artifact myArtifact
        }
    }
}

项目testB

settings.gradle:

rootProject.name = 'testB'

if (System.getenv('LOCAL_COMPILATION') == 'true') {
    // XXX (added a dependency substitution to let Gradle know that
    //      "org.test:xxx" corresponds to the testA project)
    includeBuild('../testA') {
        dependencySubstitution {
            substitute module('org.test:xxx') with project(':')
        }
    }
}

build.gradle:

if (System.getenv('LOCAL_COMPILATION') != 'true') {
    repositories {
        // XXX (only changed to show that resolution still works after
        //      publishing)
        maven { url = 'file:///tmp/my-repo' }
    }
}

configurations {
    magic
}

dependencies {
    magic 'org.test:xxx:0.0.0.+@zip'
}

task ultimateZip (type: Zip) {
    from configurations.magic
    archiveName = 'ultimate.zip'
    destinationDir = file("${buildDir}/ultimate-test")
}

根据评论中的要求,这里有一些关于创建的 default 配置和项目 testA 添加的工件的更多解释。

Gradle 中的复合构建当前具有替代项目依赖项的限制 “will always point to the default configuration of the target project”。在您的示例中,这意味着 testA 需要在 default 配置中发布。因此,我们首先创建 default 配置。请注意,一些插件(如 java)已经创建了此配置;使用此类插件无需自己创建。

它似乎没有在任何地方明确提及,但正如您自己已经发现的那样,项目的 PublishedArtifacts(用 project.artifacts 声明)对于 Gradle 来找出复合构建中的依赖关系。因此,我们确保使用 this APItestA 中声明这样的 PublishedArtifact。工件(例如,它的扩展)是根据 someZip 任务的属性配置的。该名称似乎不是取自您示例中的 someZip 任务,因为您手动设置了 archiveName;因此我们需要明确声明它。如果您在 someZip 中使用 archiveBaseName = 'xxx',那么在添加工件时不需要闭包。