[GRADLE-2580] Init script's classpath dependencies are not accessible in the build script Created: 30/Nov/12  Updated: 10/Feb/17  Resolved: 10/Feb/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: 0


 Description   

I'm trying to add an init script dependency containing some classes that must be visible by Gradle and all Projects, however it happens that those classes are only visible during the execution of the init script (and within the Gradle instance) but any attempt to import and load them from a Project fails:

//init.gradle

initscript {

repositories

{ mavenCentral() }

dependencies

{ classpath 'commons-collections:commons-collections:3.2' }

}

gradle.ext.myMap = new org.apache.commons.collections.map.MultiKeyMap()

//build.gradle

gradle.ext.myMap as org.apache.commons.collections.map.MultiKeyMap

Executing the above fails with `unable to resolve class org.apache.commons.collections.map.MultiKeyMap` (during compilation of the build.gradle file).
After struggling a bit (a lot) with this, I have found a workaround:

//init.gradle

gradle.projectsLoaded {

MutableURLClassLoader projectCl = rootProject.buildscript.classLoader as MutableURLClassLoader

projectCl.addURLs((initscript.getClassLoader() as URLClassLoader).getURLs() as List)

}

However this has the drawback that classes are actually loaded into two separate class loaders so if I start passing objects between them I get a ClassCastException:

//build.gradle

import org.apache.commons.collections.keyvalue.MultiKey

//fails with java.lang.ClassCastException: Key must be a MultiKey

gradle.ext.myMap.put(new MultiKey('key'), 'value')

So I wonder whether this problem could be considered a real issue or there are some reasons for it to be that way?

I'm using Gradle 1.3

P.S. I'm actually exploring this area in an attempt to [Configure different set of repositories based on project status]([1]http://forums.gradle.org/gradle/topic...).

Thanks,
Detelin
----------------------------------------------------------------------------------------
[1] http://forums.gradle.org/gradle/topics/configure_different_set_of_repositories_based_on_project_status



 Comments   
Comment by Gradle Forums [ 30/Nov/12 ]

This works as designed. (Not saying I'm entirely happy with the design.) To make a library available to build scripts, you can do something like this (in the init script):

rootProject {
buildscript {
dependencies {
classpath ...
}
}
}

For a complete example, see the `customDistribution` sample in the full Gradle distribution. This won't work for applied scripts though. I'm not aware of a way to make it work for applied scripts, other than declaring the dependencies in the applied script itself.

Comment by Gradle Forums [ 30/Nov/12 ]

Thanks, this seems a bit better than the class loader hacks I have been doing but one problem is that I would also need to configure the repositories that the init script uses for the build script as well.
I'm not interested in using these dependencies in applied build script (I saw the [other topic]([1]http://forums.gradle.org/gradle/topic...) about this), what I'm trying to do is to initialize some domain objects early before the projects are evaluated, then to set them as extra properties or an extension so that our build plugins can reuse them rather than having to re-create them.
I think what I'm trying to do exactly what the [basic usage of an init script]([2]http://gradle.org/docs/current/usergu...) mentions:
> - Set up enterprise-wide configuration, such as where to find custom plugins.
> - Set up properties based on the current environment, such as a developer's machine vs. a continuous integration server.

But with this limitation, I'm not able to do this kind of setup using custom classes, but must use only standard Gradle/Java types
----------------------------------------------------------------------------------------
[1] http://forums.gradle.org/gradle/topics/how_to_refer_to_classes_on_the_buildscript_classpath_in_an_applied_script
[2] http://gradle.org/docs/current/userguide/init_scripts.html

Comment by Gradle Forums [ 30/Nov/12 ]

I don't understand. What's the problem with the solution I posted? Did you have a look at the `customDistribution` sample?

Comment by Gradle Forums [ 30/Nov/12 ]

The problem is that I want to execute code before the projects are evaluated, so this code cannot be on the buildscript classpath, but has to be on the init script classpath. On the other hand, this code needs to create and store objects somewhere (Gradle/Project instance) where they can be later accessed by build plugins applied to the projects.

If this cannot be achieved by configuring the init script classpath, can I add this piece of code somewhere else so it becomes part of Gradle and:

*code and objects created by it are visible by init script

*code and objects created by it are visible by build scripts

Comment by Gradle Forums [ 30/Nov/12 ]

Unfortunately, I'm not aware of a way to do so.

Comment by Gradle Forums [ 30/Nov/12 ]

Ok, while there might be cases where inheriting init script dependencies in the build script classpath might be undesirable (I cannot think of such right now), I think that it is more common to assume that if something is declared as a dependency in the init script, it would be available for the build scripts as well.
Also, would not this also solve GRADLE-2407([1]http://issues.gradle.org/browse/GRADL...)?
----------------------------------------------------------------------------------------
[1] http://issues.gradle.org/browse/GRADLE-2407

Comment by Gradle Forums [ 30/Nov/12 ]

In larger builds, a global script class path can cause version conflict problems. Nevertheless I consider it necessary to have a way to globally share dependencies between all scripts in a build. I'll create an issue, let's see where it goes.

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 Benjamin Muschko [ 10/Feb/17 ]

Thanks again for reporting this issue. We haven't heard back from you after our inquiry from November 15th. We are closing this issue now. Please create an issue on GitHub if you still feel passionate about getting it resolved.

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