How can plugin programmatically configure maven-publish publishing and allow build.gradle to modify it

匿名 (未验证) 提交于 2019-12-03 02:06:01

问题:

I have project wide settings in a plugin, called parent, that attempts to apply the maven-publish plugin and then programmatically configure the publishing extension. This seems to work but when I apply this plugin in a build.gradle script I can not configure publishing extension to set the project specific publications.

I receive the error:

  Cannot configure the 'publishing' extension after it has been accessed. 

My intent was to set up the publishing repository in the parent plugin and then let each build.gradle script add the appropriate publications.

Is there a way to do this?

Currently ParentPlugin.groovy looks like:

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 fails when it tries to configure the publishing extension.

apply plugin: 'parent'  publishing {         publications {             mavenJava(MavenPublication) {                 groupId 'agroup'                 artifactId 'anartifactid'                 version '1.0.0-SNAPSHOT'                  from components.java             }         } } 

Is this possible? Is there another way I should be approaching this?

回答1:

To deal with this, I wrote another plugin, which can delay modifications to the publication while also avoid a "reading" of the extension, which would put it in the "configured" state. The plugin is called nebula-publishing-plugin, the code for the "lazy" block can be found in the github repo. It looks like this:

/**  * 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     } } 

You would then call it like this:

withMavenPublication { MavenPublication t ->         def webComponent = project.components.getByName('web')         // TODO Include deps somehow         t.from(webComponent)     } 

The plugin is available in jcenter() as 'com.netflix.nebula:nebula-publishing-plugin:1.9.1'.



回答2:

NOTE regarding repositories{} and publications{} for plugin maven-publish:

Topic: How to workaround this perplexing gradle fatal error message: Cannot configure the 'publishing' extension after it has been accessed

First thing to try (deep magic): (note "project." prefix is optional) -- Configure publications and repositories not like this:

project.publishing {publications {...}} project.publishing {repositories {...}} 

but instead like this recommended style:

project.publishing.publications {...} project.publishing.repositories {...} 

It would be instructive for a gradle guru to explain why this trick works.

Another known workaround is to make sure that each apply of plugin maven-publish is in the same project code block as project.publishing.repositories and project.publishing.publications. But that is more complex and harder to do than the first thing to try, since by default the CBF applies maven-publish and a second apply of it may itself cause the same error. maven-publish is normally applied in pub/scripts/publish-maven.gradle, unless PUB_PUBLISH_MAVEN is set to override that file location, in which case the caller should apply plugin maven-publish. See https://orareview.us.oracle.com/29516818 for how this not-preferred workaround can be done (for project emcapms) while still using the CBF.

P.S. Someday I'll write this up with minimal code examples. But I'm putting this hard-won knowedge out there now to save other folks from wasting days on this common maven-publish issue.



回答3:

A little bit late, but I found a solution that does not require an additional plugin: (This has been taken from one of my internal plugins, that can work with old and new publishing, thus the ...withType... stuff.

instead of:

    project.plugins.withType(MavenPublishPlugin) {         project.publishsing {             publications {                 myPub(MavenPublication) {                     artifact myJar                 }             }         }     } 

do this:

    project.plugins.withType(MavenPublishPlugin) {         project.extensions.configure PublishingExtension, new ClosureBackedAction( {             publications {                 myPub(MavenPublication) {                     artifact myJar                 }             }         })     } 

This will not resolve the Extension immediately, but will apply the configuration at the time when it gets first resolved by someone. Of course it would perfectly make sense to use this style of configuration in your project-wide plugin to configure the repositories and use the publication extension in the build scripts as usual. This would avoid confusion for buildscript authors.



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!