插件如何以编程方式配置maven发布并允许build.gradle修改它

插件如何以编程方式配置maven发布并允许build.gradle修改它,gradle,Gradle,我在一个名为parent的插件中设置了项目范围的设置,该插件尝试应用maven发布插件,然后以编程方式配置发布扩展。这似乎可行,但当我在build.gradle脚本中应用此插件时,我无法配置发布扩展以设置特定于项目的发布 我收到错误消息: Cannot configure the 'publishing' extension after it has been accessed. 我的目的是在父插件中设置发布存储库,然后让每个build.gradle脚本添加适当的发布 有办法做到这一点吗

我在一个名为parent的插件中设置了项目范围的设置,该插件尝试应用maven发布插件,然后以编程方式配置发布扩展。这似乎可行,但当我在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')
                }

            }
        }
    }
}
My client build.gradle尝试配置发布扩展时失败

apply plugin: 'parent'

publishing {
        publications {
            mavenJava(MavenPublication) {
                groupId 'agroup'
                artifactId 'anartifactid'
                version '1.0.0-SNAPSHOT'

                from components.java
            }
        }
}

这可能吗?我还有别的办法吗

为了解决这个问题,我编写了另一个插件,它可以延迟对出版物的修改,同时也可以避免“读取”扩展,从而使其处于“已配置”状态。该插件称为nebula publishing plugin,“lazy”块的代码可以在中找到。看起来是这样的:

/**
 * 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
    }
}
project.publishing {publications {...}}
project.publishing {repositories {...}}
然后你会:


该插件在jcenter()中以“com.netflix.nebula:nebula publishing plugin:1.9.1”的形式提供。

有点晚了,但我找到了一个不需要额外插件的解决方案: (这是从我的一个内部插件中获取的,它可以处理新旧发布,因此是…withType…东西

而不是:

    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
                }
            }
        })
    }
这不会立即解析扩展,但会在某人首次解析时应用配置。
当然,在项目范围的插件中使用这种类型的配置来配置存储库并像往常一样在构建脚本中使用发布扩展是完全有意义的。这将避免构建脚本作者的混淆。

关于插件maven publish的存储库{}和发布{}的注意:

主题:如何解决这个令人困惑的gradle致命错误消息: 访问“发布”扩展后无法配置该扩展

尝试的第一件事(深层魔法): (注意“project.”前缀是可选的) --配置发布和存储库时不要这样:

/**
 * 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
    }
}
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。 请参阅,以了解这是如何不受欢迎的 在仍然使用CBF的情况下,可以(针对项目emcapms)进行变通


还有,总有一天我会用最少的代码示例来写这篇文章。但是我现在把这个来之不易的知识放在那里,以避免其他人在这个常见的maven发布问题上浪费时间。

谢谢,这很有帮助。我希望每个项目的构建都更容易。gradle允许他们使用标准发布扩展。会有吗这是我的插件公开自己的自定义发布扩展的一种方式,它允许项目在中定义发布。您刚刚帮我省去了自己弄明白这一点的工作-非常感谢!希望Gradle devs能在接下来的几个版本中解决这个问题。如果我在加载发布扩展之前尝试这样做,我会得到:>类型为“P”的扩展“PublishingExtension”不存在。当前注册的扩展类型:[DefaultExtraPropertiesExtension]。如果我以后再这样做,它将返回到>无法在访问“publishing”扩展后配置它。谢谢您,为我工作。我将“publishing{Publishings{…}}”替换为“publishing.Publishings{…}”错误消失了!感谢修复!我在尝试评估我的gradle项目时遇到了IntelliJ问题。它似乎有一个与典型的gradle构建大不相同的同步过程。它起作用了,起初我很高兴,后来我意识到这是一个黑魔法。请不要诅咒我