我在一个名为parent的插件中有项目范围设置,它尝试应用maven-publish插件,然后以编程方式配置发布扩展。这似乎有效,但是当我在build.gradle脚本中应用此插件时,我无法配置发布扩展来设置项目特定的出版物。
我收到错误:
Cannot configure the 'publishing' extension after it has been accessed.
我的目的是在父插件中设置发布存储库,然后让每个build.gradle脚本添加相应的发布。
有办法做到这一点吗?
目前ParentPlugin.groovy看起来像:
def void apply(Project project) {
project.getProject().apply plugin: 'maven-publish'
def publishingExtension = project.extensions.findByName('publishing')
publishingExtension.with {
repositories {
maven {
mavenLocal()
credentials {
username getPropertyWithDefault(project.getProject(), 'publishUserName', 'dummy')
password getPropertyWithDefault(project.getProject(), 'publishPassword', 'dummy')
}
}
}
}
}
我的客户端build.gradle在尝试配置发布扩展时失败。
apply plugin: 'parent'
publishing {
publications {
mavenJava(MavenPublication) {
groupId 'agroup'
artifactId 'anartifactid'
version '1.0.0-SNAPSHOT'
from components.java
}
}
}
这可能吗?还有另一种方法我应该接近这个吗?
答案 0 :(得分:16)
有关插件maven-publish的存储库{}和出版物{}的说明:
主题:如何解决这个令人困惑的gradle致命错误消息: 无法配置'发布'访问后的扩展
首先尝试(深刻的魔法): (注意"项目。"前缀是可选的) - 配置出版物和存储库不,如下所示:
project.publishing {publications {...}}
project.publishing {repositories {...}}
但是喜欢这种推荐的风格:
project.publishing.publications {...}
project.publishing.repositories {...}
对于一个傻瓜大师解释为什么这个技巧有效会有所帮助。
另一个已知的解决方法是确保每次应用插件 maven-publish与项目代码块相同 project.publishing.repositories和project.publishing.publications。 但这比第一件尝试更复杂,更难做, 因为默认情况下CBF应用maven-publish和第二次应用它 可能会导致同样的错误。 maven-publish通常应用于pub / scripts / publish-maven.gradle, 除非PUB_PUBLISH_MAVEN设置为覆盖该文件位置, 在这种情况下,调用者应该应用插件maven-publish。 有关这不是首选的方法,请参阅https://orareview.us.oracle.com/29516818 可以在使用CBF时完成解决方法(对于项目emcapms)。
P.S。有一天,我会用最少的代码示例来编写它。但是我现在把这个来之不易的知识放在那里,以免其他人在这个普通的maven-publish问题上浪费时间。
答案 1 :(得分:7)
为了解决这个问题,我编写了另一个插件,它可以延迟对发布的修改,同时还可以避免“读取”扩展,这会使其处于“已配置”状态。该插件名为nebula-publishing-plugin,“懒惰”块的代码可以在github repo中找到。它看起来像这样:
/**
* All Maven Publications
*/
def withMavenPublication(Closure withPubClosure) {
// New publish plugin way to specify artifacts in resulting publication
def addArtifactClosure = {
// Wait for our plugin to be applied.
project.plugins.withType(PublishingPlugin) { PublishingPlugin publishingPlugin ->
DefaultPublishingExtension publishingExtension = project.getExtensions().getByType(DefaultPublishingExtension)
publishingExtension.publications.withType(MavenPublication, withPubClosure)
}
}
// It's possible that we're running in someone else's afterEvaluate, which means we need to run this immediately
if (project.getState().executed) {
addArtifactClosure.call()
} else {
project.afterEvaluate addArtifactClosure
}
}
然后你会call it like this:
withMavenPublication { MavenPublication t ->
def webComponent = project.components.getByName('web')
// TODO Include deps somehow
t.from(webComponent)
}
该插件在jcenter()中以'com.netflix.nebula:nebula-publishing-plugin:1.9.1'的形式提供。
答案 2 :(得分:6)
有点晚了,但我找到了一个不需要额外插件的解决方案: (这是从我的一个内部插件中获取的,可以使用旧的和新的发布,因此... withType ... stuff。
而不是:
project.plugins.withType(MavenPublishPlugin) {
project.publishsing {
publications {
myPub(MavenPublication) {
artifact myJar
}
}
}
}
这样做:
project.plugins.withType(MavenPublishPlugin) {
project.extensions.configure PublishingExtension, new ClosureBackedAction( {
publications {
myPub(MavenPublication) {
artifact myJar
}
}
})
}
这不会立即解析扩展,但会在某人首次解析时应用配置。 当然,在项目范围的插件中使用这种配置样式来配置存储库并像往常一样在构建脚本中使用发布扩展是完全有意义的。这样可以避免构建作者的混淆。