可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
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.