簡體   English   中英

如果應用java插件,Gradle將無法在復合構建中找到zip工件

[英]Gradle is unable to find zip artifact in composite build if java plugin is applied

我有一個Gradle項目,它創建了一個zip工件。 我通過artifacts.add('default', zipTask)定義工件。 我通過includeBuild將此項目添加到另一個項目,並使用zip作為依賴項( dependencies { myConfiguration 'org.example:testA:+@zip' } )。 到現在為止還挺好。 有用。

當我將插件java添加到第一個項目時,問題就出現了。 由於某種原因,它會阻止Gradle找到zip工件。 錯誤是:

Execution failed for task ':doubleZipTask'.
> Could not resolve all files for configuration ':myConfiguration'.
   > Could not find testA.zip (project :testA).

為什么? 怎么解決?

完整的例子:

項目testA

settings.gradle

rootProject.name = 'testA'

build.gradle

plugins {
    id 'base'
    // Uncomment the line below to break the zip artifact
    //id 'java'
}

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

task zipTask(type: Zip) {
    from './settings.gradle' // just so the zip isn't empty
}

artifacts.add('default', zipTask)

項目testB

settings.gradle

rootProject.name = 'testB'

// This line may be commented out in some cases and then the artifact should be downloaded from Maven repository.
// For this question it should be always uncommented, though.
includeBuild('../testA')

build.gradle

plugins {
    id 'base'
}

configurations {
    myConfiguration
}

dependencies {
    myConfiguration 'org.test:testA:0.0.0.+@zip'
}

task doubleZipTask(type: Zip) {
    from configurations.myConfiguration
}

更新1

我在build.grade的末尾添加了一些診斷代碼:

configurations.default.allArtifacts.each() {
    println it.toString() + ' -> name: ' + it.getName() + ', extension: ' + it.getExtension()
}

並在帶有java插件的版本中打印:

ArchivePublishArtifact_Decorated testA:zip:zip: -> name: testA, extension: zip
org.gradle.api.internal.artifacts.dsl.LazyPublishArtifact@2c6aaa5 -> name: testA, extension: jar

但是,我不確定是否有其他工件會破壞某些東西。

當我自己添加第二個工件時似乎不是問題。


更新2

也許zip文件不是我的意圖的最佳代表。 畢竟,我可以在一個項目中構建java相關文件,然后將它們壓縮到另一個項目中。 但是,該問題也適用於war文件。 (War插件內部使用Java插件,因此無法單獨運行。)

該問題似乎是Gradle中的一個錯誤,其中復合構建和對工件的引用被破壞。

一些討論在這里: https//discuss.gradle.org/t/composite-build-cant-use-included-artifact-in-buildsrc-build-gradle/24978

錯誤報告: https//github.com/gradle/gradle/issues/3768

解決方法是將工件依賴項移動到任務依賴項:

plugins {
    id 'base'
}

configurations {
    myConfiguration
}

dependencies {

}

task doubleZipTask(type: Zip) {
    dependsOn gradle.includedBuild('testA').task(':zipTask')
    from configurations.myConfiguration
}

以下設置適用於Gradle 5.6(使用其他屬性時,它可能也適用於以前的版本)。 它主要對應於您的原始設置,但XXX指示的更改除外。

項目testA

settings.gradle

rootProject.name = 'testA'

build.gradle

plugins {
    id 'base'
    // Uncomment the line below to break the zip artifact
    //id 'java'
}

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

task zipTask(type: Zip) {
    from './settings.gradle' // just so the zip isn't empty
}

// XXX added an attribute to the configuration
configurations.default.attributes {
    attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE,
              project.objects.named(LibraryElements, 'my-zipped-lib'))
}

artifacts.add('default', zipTask)

項目testB

settings.gradle

rootProject.name = 'testB'

// This line may be commented out in some cases and then the artifact should be downloaded from Maven repository.
// For this question it should be always uncommented, though.
includeBuild('../testA')

build.gradle

plugins {
    id 'base'
}

configurations {
    // XXX added the same attribute as in the testA project
    myConfiguration {
        attributes {
            attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE,
                      project.objects.named(LibraryElements, 'my-zipped-lib'))
        }
    }
}

dependencies {
    myConfiguration 'org.test:testA:0.0.0.+@zip'
}

task doubleZipTask(type: Zip) {
    from configurations.myConfiguration
}

我已經使用和不使用java插件測試了這個設置。 我還測試了發布到Maven存儲庫並讓testB從那里獲取依賴,而不是從包含的testA構建。 testB工件上添加testB的附加依賴testAmyConfiguration 'org.test:testA:0.0.0.+@jar' )也有效。

關於(我相信)正在進行的一些解釋:Gradle需要一種方法來自動確定testA哪個本地組件/工件可以用來替換testB的外部依賴關系。

  • 沒有應用java插件,只有一個組件/工件,我的猜測是Gradle然后只選擇那個單獨的組件/工件。
  • 如您所見,通過應用java插件,另一個工件被添加到testA 現在Gradle應該選哪一個? 可以預期它將查看testB依賴項上指定的文件擴展名,但似乎並非如此。 似乎Gradle在替換依賴項時實際上並不在工件級別工作,而是在模塊 / 組件級別。 您可能會說我們只有一個帶有兩個工件的組件,因此選擇一個組件應該很簡單。 但似乎我們實際上有兩個相同組件的變體 ,Gradle想要選擇其中一個變體 在您自己的testB設置中,沒有任何線索可以告訴Gradle選擇哪個變體; 所以它失敗了(公認的錯誤/誤導性錯誤信息)。 在我改變的testB設置中,我提供了線索:我告訴Gradle我們想要一個具有my-zipped-lib值的特定屬性的變體。 由於我在testA的已發布配置中添加了相同的屬性,因此Gradle現在能夠選擇正確的變體(因為只有一個具有必需的屬性)。 依賴項上的文件擴展名仍然在第二步中相關:一旦Gradle選擇了組件變體,它仍然需要選擇正確的工件 - 但僅限於此。

請注意,我們實際上正在研究今天復合構建支持的內容 另請參閱Gradle問題#2529 ,其中指出“發布非jar工件的項目”並未得到很好的支持。 當我第一次看到你的問題時,我真的以為我們在這里運氣不好......但似乎還有一種方法可以再次靠近籃筐;-)


在評論中,問題出現了為什么在應用java插件時添加多個自定義工件會破壞構建。 正如我上面試圖解釋的那樣,這不是多個工件的問題,而是多個組件變體的問題 IIUIC,這些變體源於配置的不同屬性。 如果不添加此類屬性,則不會有不同的組件變體。 但是,Java插件確實添加了這樣的屬性,從而導致項目(/ component)中的組件變體不同。 如果您感興趣,可以通過在build.gradle添加以下內容來查看不同的屬性:

configurations.each { conf ->
    println "Attributes of $conf:"
    conf.attributes.keySet().each { attr ->
        println "\t$attr -> ${conf.attributes.getAttribute(attr)}"
    }
}

現在何時何地添加哪些屬性? 這取決於您的設置。 我不會盲目地為所有配置添加屬性,希望能夠神奇地解決問題。 雖然它可能會起作用(取決於你的設置),但它肯定不干凈。 如果您的項目設置與您的問題建議一樣復雜和/或特殊,那么更深入地思考您需要哪些配置以及它們應該攜帶哪些屬性可能是有意義的。 如果您不熟悉Gradle中這些配置的細微差別,那么我上面鏈接的Gradle文檔頁面的第一部分可能是一個很好的起點。 是的,我同意這樣的邏輯最好生活在Gradle插件中。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM