gradle
gradle copied to clipboard
Use a project dependency for test->main dependency in Java plugin
Instead of doing sourceSets.test.compileClasspath += sourceSets.main.output
, the Java plugin should use dependencies { testImplementation thisProject }
and Gradle will automatically wire in the main variant of the project.
While this change should work, it has some unwanted consequences due to the fact that our variant model for JVM components isn't fully fleshed out:
- With the
java
plugin applied, this results intestCompile
depending onjar
(instead of justclasses
) - With the
java-library
plugin applied,testCompile
correctly depends onclasses
(and doesn't require the main jar to be built). However thetestRuntimeClasspath
ends up requiring thejar
for the project.
I'm sure we can solve these problems by more correctly modelling the variants when either the java
or java-library
plugin is installed. Currently, we don't model any classes
variants for the java
plugin, and only the api-classes
variant with the java-library
plugin.
I'm not sure if this is worth rushing into 5.0.
After a little bit more experimentation, here's what I think is required:
- A new outgoing variant
Usage.RUNTIME_CLASSES_AND_RESOURCES
onruntimeElements
that has both the classes and resources directories as artifacts. - Appropriate compatibility and disambiguation rules to choose this variant for a self-referencing project dependency when resolving the
testRuntimeClasspath
configuration. - As stated in the main comment, change the
testImplementation
configuration to have a project dependency on self.
However, this has another implication: cross-project dependencies would be resolved the same way, so the test runtime classpath would now contain classes
and resources
directories for all dependent project, rather than jar
files. This might be better, but would be a breaking change.
I think we'll want to do this in a less disruptive way, perhaps by adding rules that choose the new variant only for self-project dependencies, and not for cross-project dependencies.
@oehme Given my previous comments, do you still want to target this for 5.0?
I think using the JAR is actually better, as it is much faster to load on Windows than classes folders. For the same reason I'm also in favor of creating API JARs instead of classes folders for compilation, but that's another issue.
I don't think we need different behavior for local and downstream consumption. The price is small on Linux and on Windows it's actually faster to compile against a JAR.
I'm fine with doing this in another release, I just added it to 5.0 as it may break some hidden assumptions that some plugins might have.
But changing tests to have a local jar
input instead of classes
and resources
would be a breaking change, and should probably be changed over a deprecation cycle: WDYT?
You mean by adding an opt-in and then nagging users to use it? That seems reasonable.
Note that this is the root cause for #10872
We should make this configurable. And then we can change the default in a major (e.g. 8.0).
This should be considered when we pick https://github.com/gradle/gradle/issues/12912 back up.
We already modify our test compile classpath to swap the main classes out for the jar, purely for the performance benefits. Not having to do that in our own scripts would be nice. :)
Also if you wanted a real performance boost, you could even skip generating the classes to the filesystem in the first place, and write them directly into the jar along with the resources. ;)
@jvandort let's split this so we can put compileElements into 8.0