【问题标题】:Define an artifact to be used as a dependency in another project定义一个工件以用作另一个项目中的依赖项
【发布时间】:2019-07-19 10:45:20
【问题描述】:

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 artifact gradle-dependencies


    【解决方案1】:

    以下设置应该可以工作(使用 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")
    }
    

    根据 cmets 的要求,这里有更多关于创建的 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',则在添加工件时不需要闭包。

    【讨论】:

    • 这个带扩展名的东西在一个项目生成两个同名不同扩展名的文件时可能会出问题。我想我有一两个这样的项目。
    • 我不喜欢在项目testB 的设置文件中包含dependencySubstitution。有两个原因:1)我将同一个项目包含在多个其他项目中,所以会有很多重复的代码。 2) 我对includeBuild 的真实代码不仅仅是一个简单的if,而是一个检查几个不同文件夹的函数正在搜索正确的项目。如果我向它添加更多代码,它会非常混乱。是否可以将dependencySubstitution 移至项目testA?项目testBbuild.gradle 也是可以接受的,因为我可以编写一个插件来处理它。
    • 我找到了一种方法,可以在 testB 中保留对依赖项的显式声明扩展;请查看我的更新答案。至于依赖替换,不幸的是,只要您包含的项目的名称 (testA) 与其发布的模块 (xxx) 的名称不同。我不相信目前有任何方法可以将依赖替换移出settings.gradle。也就是说,是否可以将testA 重命名为xxx?然后你根本不需要替换,设置也会看起来更干净(根据我从问题中对你的设置的了解)。
    • 我认为在大多数项目的情况下,工件的名称与项目相同。我已经展示了最极端的情况。那么,名称相同时我是否不必使用dependencySubstitution
    • 是的,当您在testA/settings.gradle 中使用rootProject.name = 'xxx' 时,就不需要dependencySubstitution。当您计划稍后使用它时,您确实只需要定义myArtifact 变量。对于您提到的其他几点,我在答案的末尾添加了更多解释。
    猜你喜欢
    • 1970-01-01
    • 2021-09-30
    • 1970-01-01
    • 2019-04-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-23
    • 1970-01-01
    相关资源
    最近更新 更多