-
Notifications
You must be signed in to change notification settings - Fork 5k
Allow compilation of build scripts against a different Gradle API version #20373
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow compilation of build scripts against a different Gradle API version #20373
Conversation
1cb5d97
to
aa9a6be
Compare
aa9a6be
to
600bab3
Compare
subprojects/core-api/src/main/java/org/gradle/api/artifacts/dsl/DependencyHandler.java
Outdated
Show resolved
Hide resolved
/** | ||
* Creates a dependency on the API of the current version of Gradle. | ||
* | ||
* @return The dependency. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be good to add some Javadoc on the expected format of the parameter. Are snapshots accepted?
I think we need to mention that only older versions are accepted, right? What happens if I give it a newer or non-existent version?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, probably. Though I wouldn't go into polishing the Javadoc for this spike.
return new GroovyScriptClasspathProvider( | ||
classLoaderScopeRegistry.getCoreAndPluginsScope(), | ||
() -> { | ||
String version = System.getProperty("org.gradle.api.version"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should qualify what API version this is. I'd go with org.gradle.api.target-version
or something.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I think we should qualify the property name. It feels like target
doesn't really capture it. For me, target
sounds more about the target runtime. How about org.gradle.api.source-version
, since this is the version of the Gradle API we use for sources.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Renamed.
private void applyDependencies(Project project) { | ||
DependencyHandler dependencies = project.getDependencies(); | ||
dependencies.add(API_CONFIGURATION, dependencies.gradleApi()); | ||
String apiVersion = System.getProperty("org.gradle.api.version"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We query this property in six different places by name. Instead it would be good to have a shared mechanism to expose this as an Optional<VersionNumber>
instead. An @Inject
-able service would be nice.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I extracted the common logic to a single class. I didn't make it a service, yet, since I am not sure what scope this would need to go.
repository.setUrl(repositoryUrl); | ||
}); | ||
dependencies.add(API_CONFIGURATION, dependencies.gradleApi(apiVersion)); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it would be good if the user could declare the API version they want to use via a gradleApi("6.9")
call in the build script of the plugin. The above mechanism does not allow that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, this can be improved. Note that with this solution you can already specify a different version of the gradle API by adding a constraint to the configuration, since the gradleApi(version)
is a regular dependency and participates in dependency resolution. For the final solution, I am not sure what the right thing from dependency management is. defaultDependencies
sounds it may be something in the right direction.
repository.setUrl(repositoryUrl); | ||
}); | ||
dependencies.add(JavaPlugin.API_CONFIGURATION_NAME, dependencies.gradleApi(apiVersion)); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This code is repeated, and should be abstracted/shared.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I extracted the common code.
? gradleApisFromCurrentGradle(dependencyFactory) | ||
: gradleApisFromRepository(resolutionServices, dependencyFactory, version); | ||
}, | ||
() -> ((SelfResolvingDependency) dependencyFactory.createDependency(DependencyFactory.ClassPathNotation.LOCAL_GROOVY)).resolve()); |
This PRs explores what would be necessary to compile build scripts against a different Gradle API. It allows passing the Gradle API version via
-Dorg.gradle.api.version=6.9
to the Gradle installation. Note that you also need a repository which contains an artifact for the Gradle API of this version with the coordinatesorg.gradle:gradle-api:<version>
. You can specify the URL of the repository via-Dgradle.api.repository.url=...
.Currently this works for Kotlin and Groovy build scripts. It also should work for Kotlin pre-compiled scripts and Kotlin and Groovy build logic. Though it doesn't work for Groovy pre-compiled build scripts. I suppose we should be able to make this work with Groovy pre-compiled build scripts as well, though I did run into some classloader problems there.
You can also declare a dependency in your build script on the Gradle API with a version by using
gradleApi(<version>)
instead ofgradleApi()
.Exploration doc: https://docs.google.com/document/d/1JB75X_Lt5BlubszqD0l10rHPqL89B2yd-yD39qizyDA/edit