[GRADLE-2363] Binary plugin used in custom script - project.tasks.withType not working Created: 26/Jun/12  Updated: 17/Jan/17  Resolved: 16/Jan/17

Status: Resolved
Project: Gradle
Affects Version/s: None
Fix Version/s: None

Type: Improvement
Reporter: Gradle Forums Assignee: Unassigned
Resolution: Won't Fix Votes: 2


 Description   

Hi,

I have a problem that is probably related to my question here:
[1]http://forums.gradle.org/gradle/topic...

My binary plugin `nsis` (dependency name: `gradle-nsis-plugin`) contains a task class `NsisTask`and a plugin class `NsisPlugin`. The plugin does not define any task instances, but only tries to configure the tasks of type `NsisTask`, specifically some convention mappings.

My build consists of multiple projects. The relevant subproject `client` applies a custom script `gradle/distribution.gradle`, which defines an `NsisTask`. Problem is, on task execution the convention mapping properties are not set.

Here's the code:

      1. NsisPlugin.groovy

class NsisPlugin implements Plugin<Project> {
void apply(Project project) {
// ...
project.extensions.create("nsis", NsisExtension )
project.tasks.withType(NsisTask) { task ->
// can't find that output
println "found nsis task $task"
configureTaskDefaults(task, project)
}
}

private def configureTaskDefaults(NsisTask task, Project project) {
// can't find that output
println "configure task $task"
task.conventionMapping.with {
nsisHome =

{project.nsis.nsisHome}

verbosity =

{project.nsis.verbosity}

defines =

{project.nsis.defines}

nsisClasspath =

{project.configurations.nsis}

}
}
}

      1. NsisTask.groovy

class NsisTask extends DefaultTask
{
@InputFiles
FileCollection nsisClasspath

@InputFile
File script

@OutputFile
File outputFile
// ...

@TaskAction
void run() {
ant.taskdef(name:"nsis",classname:"com.danielreese.nsisant.Task", classpath:getNsisClasspath().asPath)
ant.nsis(script:getScript().absolutePath, verbosity: getVerbosity()) {
define(name: "NSIS_HOME", value: getNsisHome().toString())
define(name: "outputFile", value: getOutputFile().absolutePath)
// ...
}
}
}

      1. client/build.gradle

apply from: "gradle/distribution.gradle"

      1. client/gradle/distribution.gradle

import com.inxmail.gradle.plugins.*
apply plugin: "nsis"

nsis {
nsisHome = "/usr/share/nsis"
verbosity = 1
define "version", project.majorVersion
define "product_version", project.version
}

task prepareNsis(type:Copy) {
into

{file("$buildDir/tmp/nsis/$installer.name")}

from

{zipTree(installerTask.call().archivePath)}

into("inst") {
from("../install/client/install/windows/inst")
from("../install/client/install/windows/icons")
}
}

task windowsExe(type:NsisTask) {
inputs.dir prepareNsis.destinationDir
dependsOn prepareNsis
outputFile = file({"$buildDir/distributions/${distBaseName}-${version}.exe"})
script = file(

{"$prepareNsis.destinationDir/inst/install.nsi"}

)
}

      1. Result:

FAILURE: Build failed with an exception.

  • What went wrong:
    A problem was found with the configuration of task ':client:windowsExe'.
    > No value has been specified for property 'nsisClasspath'.

As noted in the code, I don't find the outputs from the `tasks.withType(NsisTask)` closure, so it looks like it never finds such a task.

The confusing thing is: if I move the declaration of the task
task windowsExe(type:NsisTask) {...
into `client/build.gradle`, after the line `apply from: "gradle/distribution.gradle"`, it does work correctly.

Any idea?

A slight supection: could this be a class loader problem? Does the custom script plugin `client/gradle/distribution.gradle` maybe have a different class loader, and the class NsisTask in the type declaration there is a different instance of the class object than the one in the plugin's `tasks.withType()` call?
----------------------------------------------------------------------------------------
[1] http://forums.gradle.org/gradle/topics/inherit_inject_buildscript_dependencies_into_custom_script_within_subproject



 Comments   
Comment by Gradle Forums [ 26/Jun/12 ]

Yes, it could be a class loader problem. It could be that the only safe way is to have `buildscript` blocks in all build scripts that require them (potentially combined in a single `buildscript` block in the root project's build script), not in any script plugins. That's how I always do it, and it has served me well.

Comment by Gradle Forums [ 26/Jun/12 ]

I'm not sure I get that. Would that mean I can't use classes from binary plugins in script plugins?

Comment by Gradle Forums [ 26/Jun/12 ]

I had forgotten that those classes aren't visible to script plugins then. Our current class loading approach surely needs some improvements. I'll open an issue for this. For the time being, you can try to use something like `tasks.matching

{ it.getClass().name == ... }

` instead of `tasks.withType`.

Comment by Benjamin Muschko [ 15/Nov/16 ]

As announced on the Gradle blog we are planning to completely migrate issues from JIRA to GitHub.

We intend to prioritize issues that are actionable and impactful while working more closely with the community. Many of our JIRA issues are inactionable or irrelevant. We would like to request your help to ensure we can appropriately prioritize JIRA issues you’ve contributed to.

Please confirm that you still advocate for your JIRA issue before December 10th, 2016 by:

  • Checking that your issues contain requisite context, impact, behaviors, and examples as described in our published guidelines.
  • Leave a comment on the JIRA issue or open a new GitHub issue confirming that the above is complete.

We look forward to collaborating with you more closely on GitHub. Thank you for your contribution to Gradle!

Comment by Rainer Frey [ 15/Nov/16 ]

The build that originally triggered the issue has long been superseded, so this isn't currently relevant for me. I don't have an example to test right now either.

Still, this describes a curious and unexpected limitation, that I personally find worth having fixed.

As this issue has been created from a forum entry, it is not associated with my account, and I don't have any permission to change the description to fit the new guidelines.

Comment by Benjamin Muschko [ 16/Jan/17 ]

Seems like you can't reproduce the issue anymore. I suggest you open a new issue on GitHub if you still run into a similar issue.

Comment by Rainer Frey [ 17/Jan/17 ]

I can live with this not being fixed. But I certainly did not write that I can't reproduce this anymore. I wrote that I abandoned the original case and don't have a test case to try to reproduce. Also, as seen above, someone from the Gradle team at that time did confirm that it was a valid issue with a known root cause and that it was worthwhile to look into it.

IMO the Gradle team is much better suited to verify whether that root cause is still there than me. I voiced my opinion that this would be worth it, but you don't react to that statement at all. I don't mind if you disagree and do not find it worthwhile. But don't put it on me whether any effort will be made on this confirmed limitation.

Comment by Benjamin Muschko [ 17/Jan/17 ]

I believe the issue you are describing occurs because a script plugin has a different ClassLoader hierarchy than your "main" build script. The way to "work around" the issue is to declare the plugin classpath in the same script plugin that also uses the import. I guess I misunderstood you that you cannot reproduce the issue anymore. Given that there are ways to still use the functionality, I am not going to pursue the issue any further. Please open an issue on GitHub if you are still interested in pursuing a better solution for the problem (either as documentation or code).

Generated at Wed Jun 30 12:19:52 CDT 2021 using Jira 8.4.2#804003-sha1:d21414fc212e3af190e92c2d2ac41299b89402cf.