I’ve got a gradle build with two projects. :foo
is an interactive application. :ship
has some custom tasks related to deployment. One task in particular from :ship
started to generate a warning in Gradle 5.1:
(file is in subproject :ship)
class FooTask extends DefaultTask {
FooTask() {
dependsOn(':foo:classes')
}
@TaskAction
void doAction() {
def cp = project.project(':foo').sourceSets.main.runtimeClasspath
project.javaexec({
classpath = cp
main = 'fooMain'
})
}
}
I am getting this warning:
The configuration :foo:runtimeClasspath was resolved without accessing the project in a safe manner. This may happen when
a configuration is resolved from a thread not managed by Gradle or from a different project. See https://docs.gradle.org/5.1/userguide/tro
ubleshooting_dependency_resolution.html#configuration_resolution_constraints for more details. This behaviour has been deprecated and is sch
eduled to be removed in Gradle 6.0.
at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration.resolveToStateOrLater(DefaultConfiguration.java:534)
at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration.access$2200(DefaultConfiguration.java:135)
at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration$ConfigurationFileCollection.getSelectedArtifacts(DefaultConfiguration.java:1158)
at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration$ConfigurationFileCollection.getFiles(DefaultConfiguration.java:1147)
at org.gradle.api.internal.file.AbstractFileCollection.iterator(AbstractFileCollection.java:72)
at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration.iterator(DefaultConfiguration.java:462)
at com.google.common.collect.ImmutableCollection$Builder.addAll(ImmutableCollection.java:384)
at com.google.common.collect.ImmutableCollection$ArrayBasedBuilder.addAll(ImmutableCollection.java:476)
at com.google.common.collect.ImmutableSet$Builder.addAll(ImmutableSet.java:518)
at org.gradle.api.internal.file.CompositeFileCollection.getFiles(CompositeFileCollection.java:80)
at org.gradle.api.internal.file.CompositeFileCollection.iterator(CompositeFileCollection.java:67)
at org.gradle.util.CollectionUtils.join(CollectionUtils.java:561)
at org.gradle.process.internal.JavaExecHandleBuilder.getAllJvmArgs(JavaExecHandleBuilder.java:59)
at org.gradle.process.internal.JavaExecHandleBuilder.getAllArguments(JavaExecHandleBuilder.java:225)
at org.gradle.process.internal.AbstractExecHandleBuilder.build(AbstractExecHandleBuilder.java:135)
at org.gradle.process.internal.JavaExecHandleBuilder.build(JavaExecHandleBuilder.java:242)
at org.gradle.process.internal.DefaultJavaExecAction.execute(DefaultJavaExecAction.java:34)
at org.gradle.api.internal.file.DefaultFileOperations.javaexec(DefaultFileOperations.java:227)
at org.gradle.api.internal.project.DefaultProject.javaexec(DefaultProject.java:1103)
at org.gradle.api.internal.project.DefaultProject.javaexec(DefaultProject.java:1098)
at org.gradle.api.Project$javaexec$2.call(Unknown Source)
...
The error message helpfully references the docs for Constraints on configuration resolution
which say:
Configurations need to be resolved safely when crossing project boundaries … Gradle can usually manage this safe access, but the configuration needs to be accessed in a way that enables Gradle to do so. There are a number of ways a configuration might be resolved unsafely … e.g. A task from one project directly resolves a configuration in another project.
The trouble is, the docs don’t say what makes a resolution safe. They list a couple unsafe examples (one of which I am clearly violating), but the docs:
- don’t recommend a solution
- don’t describe what proper operation is, so that I can find a solution myself
My first instinct is that there is now no way for one project to depend on the resolved configuration of another project. If so, fair enough, but let me describe my usecase for why I hope there is a way to resolve a peer project’s dependencies.
- subproject
:foo
is an interactive application - subproject
:ship
has tasks that headlessly automates:foo
for certain maintenance tasks, along with other generic maintenance tasks
Of course, some of the tasks in :ship
could move to :foo
if they have to. But the tasks are actually about completing tasks relating to shipping, and they’re coupled with other shipping tasks that don’t have anything to do with :foo
. Likewise, :foo
is an otherwise totally normal java project unrelated to shipping, and it would be a little messy if some random shipping logic has to get stuffed into its project.
Perhaps there can be a way to explicitly opt-in and say in my settings.gradle
that :ship
depends on :foo
, so it’s okay if :ship
uses configurations from :foo
? I’m shooting in the dark here, because the docs don’t explicitly say what is allowed, just a few examples of what isn’t…