[英]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
}
我在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
但是,我不確定是否有其他工件會破壞某些東西。
當我自己添加第二個工件時似乎不是問題。
也許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
的附加依賴testA
( myConfiguration '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.