declaring a class in a gradle file and using it through apply from

classic Classic list List threaded Threaded
8 messages Options
Reply | Threaded
Open this post in threaded view
|

declaring a class in a gradle file and using it through apply from

Xavier Ducrohet
Hi,

trying to refactor some internal code, I'm running into another issue with 'apply from'

There's a foo.gradle file that only declares a new class extending DefaultTask, and we're trying to use it from another gradle file after doing 'apply from: foo.gradle' but it doesn't find the type.

Is there a way to make this work?
Reply | Threaded
Open this post in threaded view
|

Re: declaring a class in a gradle file and using it through apply from

johnrengelman
If I remember correctly I don't think that will work…I believe doing 'apply from: foo.gradle' the script in foo.gradle is processed with a new ClassLoader, so the classes won't be accessible to the calling script.

Generally classes like the one you are describing would be better suited to be defined in the buildSrc folder so it is compiled and added to your build's class path (http://www.gradle.org/docs/current/userguide/organizing_build_logic.html)

-- 
John Engelman

On Tuesday, January 7, 2014 at 12:38 PM, Xavier Ducrohet [via Gradle] wrote:

Hi,

trying to refactor some internal code, I'm running into another issue with 'apply from'

There's a foo.gradle file that only declares a new class extending DefaultTask, and we're trying to use it from another gradle file after doing 'apply from: foo.gradle' but it doesn't find the type.

Is there a way to make this work?



If you reply to this email, your message will be added to the discussion below:
http://gradle.1045684.n5.nabble.com/declaring-a-class-in-a-gradle-file-and-using-it-through-apply-from-tp5712170.html
To start a new topic under gradle-dev, email [hidden email]
To unsubscribe from gradle-dev, click here.
NAML

Reply | Threaded
Open this post in threaded view
|

Re: declaring a class in a gradle file and using it through apply from

Xavier Ducrohet
Yes, I'd like to have a buildSrc folder but it's challenging due to an existing folder structure.

Is there any way to point Gradle to a buildSrc located somewhere else?


On Tue, Jan 7, 2014 at 12:48 PM, johnrengelman <[hidden email]> wrote:
If I remember correctly I don't think that will work…I believe doing 'apply from: foo.gradle' the script in foo.gradle is processed with a new ClassLoader, so the classes won't be accessible to the calling script.

Generally classes like the one you are describing would be better suited to be defined in the buildSrc folder so it is compiled and added to your build's class path (http://www.gradle.org/docs/current/userguide/organizing_build_logic.html)

-- 
John Engelman

On Tuesday, January 7, 2014 at 12:38 PM, Xavier Ducrohet [via Gradle] wrote:

Hi,

trying to refactor some internal code, I'm running into another issue with 'apply from'

There's a foo.gradle file that only declares a new class extending DefaultTask, and we're trying to use it from another gradle file after doing 'apply from: foo.gradle' but it doesn't find the type.

Is there a way to make this work?



If you reply to this email, your message will be added to the discussion below:
http://gradle.1045684.n5.nabble.com/declaring-a-class-in-a-gradle-file-and-using-it-through-apply-from-tp5712170.html
To start a new topic under gradle-dev, email [hidden email]
To unsubscribe from gradle-dev, click here.
NAML



View this message in context: Re: declaring a class in a gradle file and using it through apply from
Sent from the gradle-dev mailing list archive at Nabble.com.

Reply | Threaded
Open this post in threaded view
|

Re: declaring a class in a gradle file and using it through apply from

johnrengelman
Not that I know.

You could just define a separate project that produces a Jar and then include that in your build script {}…then have some script to wire up that you need to execute the other project first then the main build.

-- 
John Engelman

On Tuesday, January 7, 2014 at 1:09 PM, Xavier Ducrohet [via Gradle] wrote:

Yes, I'd like to have a buildSrc folder but it's challenging due to an existing folder structure.

Is there any way to point Gradle to a buildSrc located somewhere else?


On Tue, Jan 7, 2014 at 12:48 PM, johnrengelman <[hidden email]> wrote:
If I remember correctly I don't think that will work…I believe doing 'apply from: foo.gradle' the script in foo.gradle is processed with a new ClassLoader, so the classes won't be accessible to the calling script.

Generally classes like the one you are describing would be better suited to be defined in the buildSrc folder so it is compiled and added to your build's class path (http://www.gradle.org/docs/current/userguide/organizing_build_logic.html)

-- 
John Engelman

On Tuesday, January 7, 2014 at 12:38 PM, Xavier Ducrohet [via Gradle] wrote:

Hi,

trying to refactor some internal code, I'm running into another issue with 'apply from'

There's a foo.gradle file that only declares a new class extending DefaultTask, and we're trying to use it from another gradle file after doing 'apply from: foo.gradle' but it doesn't find the type.

Is there a way to make this work?



If you reply to this email, your message will be added to the discussion below:
http://gradle.1045684.n5.nabble.com/declaring-a-class-in-a-gradle-file-and-using-it-through-apply-from-tp5712170.html
To start a new topic under gradle-dev, email [hidden email]
To unsubscribe from gradle-dev, click here.
NAML



View this message in context: Re: declaring a class in a gradle file and using it through apply from
Sent from the gradle-dev mailing list archive at Nabble.com.




To start a new topic under gradle-dev, email [hidden email]
To unsubscribe from gradle-dev, click here.
NAML

Reply | Threaded
Open this post in threaded view
|

Re: declaring a class in a gradle file and using it through apply from

Luke Daley-2
In reply to this post by Xavier Ducrohet

On 7 Jan 2014, at 6:37 pm, Xavier Ducrohet <[hidden email]> wrote:

> Hi,
>
> trying to refactor some internal code, I'm running into another issue with 'apply from'
>
> There's a foo.gradle file that only declares a new class extending DefaultTask, and we're trying to use it from another gradle file after doing 'apply from: foo.gradle' but it doesn't find the type.
>
> Is there a way to make this work?

Kind of.

Classes defined in script plugins are not visible to their “parents”. They are not on the compile classpath, because script plugin application happens at runtime. Moreover, class references in Groovy are not actually dynamic. So, you have to manually export the class literal across classloader boundaries, making a variable of type class available. This is usually done as a project extra property

build.gradle:
apply from: "someTaskDefinition.gradle"
task fancyTask(type: FancyTask) {}

someTaskDefinition.gradle:
class FancyTask extends DefaultTask {}
ext.FancyTask = FancyTask


In build.gradle it looks like you're using a class literal, but it's a project property whose value is a class.

--
Luke Daley
Principal Engineer, Gradleware
http://gradleware.com


---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email


Reply | Threaded
Open this post in threaded view
|

Re: declaring a class in a gradle file and using it through apply from

johnrengelman
Ah, that's really interesting. I didn't think about using Ext props to pass that along. Neat.

-- 
John Engelman

On Wednesday, January 8, 2014 at 12:35 PM, Luke Daley-2 [via Gradle] wrote:


On 7 Jan 2014, at 6:37 pm, Xavier Ducrohet <[hidden email]> wrote:

> Hi,
>
> trying to refactor some internal code, I'm running into another issue with 'apply from'
>
> There's a foo.gradle file that only declares a new class extending DefaultTask, and we're trying to use it from another gradle file after doing 'apply from: foo.gradle' but it doesn't find the type.
>
> Is there a way to make this work?

Kind of.

Classes defined in script plugins are not visible to their “parents”. They are not on the compile classpath, because script plugin application happens at runtime. Moreover, class references in Groovy are not actually dynamic. So, you have to manually export the class literal across classloader boundaries, making a variable of type class available. This is usually done as a project extra property

build.gradle:
apply from: "someTaskDefinition.gradle"
task fancyTask(type: FancyTask) {}

someTaskDefinition.gradle:
class FancyTask extends DefaultTask {}
ext.FancyTask = FancyTask


In build.gradle it looks like you're using a class literal, but it's a project property whose value is a class.

--
Luke Daley
Principal Engineer, Gradleware
http://gradleware.com


---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email





To start a new topic under gradle-dev, email [hidden email]
To unsubscribe from gradle-dev, click here.
NAML

Reply | Threaded
Open this post in threaded view
|

Re: declaring a class in a gradle file and using it through apply from

Xavier Ducrohet
In reply to this post by Luke Daley-2
I find groovy to a bit too flexible sometimes, and this seems like another case of it.

Why doesn't gradle require to write this (in build.gradle):
task fancyTask(type: ext.FancyTask) {}

I'm seeing quite a few users get bitten because Gradle is being too smart and sometimes hides what is really going on. Is this specific to Gradle or something about Groovy handling custom DSL. Would be possible to enable a more strict mode.

Two examples:

a developer wanted a flavor specific flavor and wrote

   productFlavors {
     pro {
       dependencies {
         compile project(':lib')
       }
     }
   }


Of course 'dependencies' is not a properties for the flavor object, but of the project and gradle accept this and silently does the right thing.

Another case was a developer writing something like this:

  def getVersionCode() {
  ...
  }

  android.defaultConfig {
     versionCode getVersionCode()
  }

In this case it looks right. Except that getVersionCode() is actually the getter of the versionCode prop on the defaultConfig object so it does nothing. While it's not really groovy being too flexible, it's another case of deal with the scope of execution for each closure. A "strict" mode where Groovy/Gradle complains that there's two conflicting resolution would be good.

Anyway, sorry for the rant and going off topic, I find there is a bit too much magic happening in Gradle files regarding scopes and visibility of different items in different cases and it's really difficult to keep track of them and, more importantly, to troubleshoot them when what is expected is not happening.

To resolve my original question, we managed to get a buildSrc folder in the right place and we're moving all our logic there, which makes things a lot nicer imo.

thanks!


On Wed, Jan 8, 2014 at 12:34 PM, Luke Daley <[hidden email]> wrote:

On 7 Jan 2014, at 6:37 pm, Xavier Ducrohet <[hidden email]> wrote:

> Hi,
>
> trying to refactor some internal code, I'm running into another issue with 'apply from'
>
> There's a foo.gradle file that only declares a new class extending DefaultTask, and we're trying to use it from another gradle file after doing 'apply from: foo.gradle' but it doesn't find the type.
>
> Is there a way to make this work?

Kind of.

Classes defined in script plugins are not visible to their “parents”. They are not on the compile classpath, because script plugin application happens at runtime. Moreover, class references in Groovy are not actually dynamic. So, you have to manually export the class literal across classloader boundaries, making a variable of type class available. This is usually done as a project extra property

build.gradle:
apply from: "someTaskDefinition.gradle"
task fancyTask(type: FancyTask) {}

someTaskDefinition.gradle:
class FancyTask extends DefaultTask {}
ext.FancyTask = FancyTask


In build.gradle it looks like you're using a class literal, but it's a project property whose value is a class.

--
Luke Daley
Principal Engineer, Gradleware
http://gradleware.com


---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email



Reply | Threaded
Open this post in threaded view
|

Re: declaring a class in a gradle file and using it through apply from

johnrengelman
You don't have to write ext.FancyTask because the Gradle code that is processing the script is checking the Extra properties to resolve property values (http://www.gradle.org/docs/current/dsl/org.gradle.api.plugins.ExtraPropertiesExtension.html)

-- 
John Engelman

On Wednesday, January 8, 2014 at 9:36 PM, Xavier Ducrohet [via Gradle] wrote:

I find groovy to a bit too flexible sometimes, and this seems like another case of it.

Why doesn't gradle require to write this (in build.gradle):
task fancyTask(type: ext.FancyTask) {}

I'm seeing quite a few users get bitten because Gradle is being too smart and sometimes hides what is really going on. Is this specific to Gradle or something about Groovy handling custom DSL. Would be possible to enable a more strict mode.

Two examples:

a developer wanted a flavor specific flavor and wrote

   productFlavors {
     pro {
       dependencies {
         compile project(':lib')
       }
     }
   }


Of course 'dependencies' is not a properties for the flavor object, but of the project and gradle accept this and silently does the right thing.

Another case was a developer writing something like this:

  def getVersionCode() {
  ...
  }

  android.defaultConfig {
     versionCode getVersionCode()
  }

In this case it looks right. Except that getVersionCode() is actually the getter of the versionCode prop on the defaultConfig object so it does nothing. While it's not really groovy being too flexible, it's another case of deal with the scope of execution for each closure. A "strict" mode where Groovy/Gradle complains that there's two conflicting resolution would be good.

Anyway, sorry for the rant and going off topic, I find there is a bit too much magic happening in Gradle files regarding scopes and visibility of different items in different cases and it's really difficult to keep track of them and, more importantly, to troubleshoot them when what is expected is not happening.

To resolve my original question, we managed to get a buildSrc folder in the right place and we're moving all our logic there, which makes things a lot nicer imo.

thanks!


On Wed, Jan 8, 2014 at 12:34 PM, Luke Daley <[hidden email]> wrote:

On 7 Jan 2014, at 6:37 pm, Xavier Ducrohet <[hidden email]> wrote:

> Hi,
>
> trying to refactor some internal code, I'm running into another issue with 'apply from'
>
> There's a foo.gradle file that only declares a new class extending DefaultTask, and we're trying to use it from another gradle file after doing 'apply from: foo.gradle' but it doesn't find the type.
>
> Is there a way to make this work?

Kind of.

Classes defined in script plugins are not visible to their “parents”. They are not on the compile classpath, because script plugin application happens at runtime. Moreover, class references in Groovy are not actually dynamic. So, you have to manually export the class literal across classloader boundaries, making a variable of type class available. This is usually done as a project extra property

build.gradle:
apply from: "someTaskDefinition.gradle"
task fancyTask(type: FancyTask) {}

someTaskDefinition.gradle:
class FancyTask extends DefaultTask {}
ext.FancyTask = FancyTask


In build.gradle it looks like you're using a class literal, but it's a project property whose value is a class.

--
Luke Daley
Principal Engineer, Gradleware
http://gradleware.com


---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email






To start a new topic under gradle-dev, email [hidden email]
To unsubscribe from gradle-dev, click here.
NAML