Where can i set a property that will be available both from buildSrc’s build.gradle and my projects build.gradle’s?
project level gradle.properties not available from buildSrc
Goal: I want to share some props, like repo url’s
Where can i set a property that will be available both from buildSrc’s build.gradle and my projects build.gradle’s?
project level gradle.properties not available from buildSrc
Goal: I want to share some props, like repo url’s
The buildSrc project is looking for properties in a gradle.properties file in the buildSrc directory. A simple thing would just be to create a symbolic link there to the gradle.properties file in the root project.
├── buildSrc
│ ├── build.gradle
│ └── gradle.properties -> ../gradle.properties
└── gradle.properties
Alternatively if you want a more cross-platform way of doing this you could put properties in a .gradle file and then just apply to both projects.
properties.gradle
ext {
repoUrl = 'http://repo.mycompany.org'
}
build.gradle
apply from: 'properties.gradle'
buildSrc/build.gradle
apply from: "${rootDir.parentFile}/properties.gradle"
This is what I was looking for, however I do have a follow up question.
I found this answer: How to share variable between Gradle buildSrc and rest of project? - Stack Overflow
So based on using java.lang.Properties
as an alternative solution, how do you tell code in buildSrc where the root or base directory is.
It appears that the relative path from the perspective of code in buildSrc is always where you execute the build from.
So if I wanted to do something like this:
Properties projectProperties = new java.util.Properties()
FileInputStream fis = new FileInputStream(“gradle.properties”)
projectProperties.load(fis)
If you’re not in the root directory when you execute the build then it won’t find the file.
Can you do this:
Properties projectProperties = new java.util.Properties()
FileInputStream fis = new FileInputStream(“$rootDir/gradle.properties”)
projectProperties.load(fis)
This is with a situation where you don’t have a buildSrc/build.gradle
file.
@robleach It’s not clear to me where this code you are showing will live? Is this in a build script or in a Java source file that lives in the buildSrc
project?
Sorry, it is Groovy code under buildSrc/src/main/groovy/UCD.groovy
.
I think what I would do is restructure your code to take the file location as some kind of argument. The working directory is not going to be predictable and project.rootDir
is only available from within a build script.
Okay at least that answers my follow up question. Thanks.
Here’s a copy-paste snippet for anyone else who comes along and wants gradle.properties
in their root dir to be visible to buildSrc
.
/*** file: gradle/loadProps.gradle ***/
Properties properties = new Properties()
FileInputStream input = new FileInputStream(file('../gradle.properties'))
properties.load(input)
input.close()
for (String key : properties.stringPropertyNames()) {
ext.set(key, properties.getProperty(key))
}
/*** file: buildSrc/build.gradle ***/
apply from: '../gradle/loadProps.gradle'
How about properties visible from buildSrc/settings.gradle
?
Sorry to bump an old topic, but since the problem still exists, I hope my comment will be helpful to anyone coming across this topic from a Google search, just like I did.
Using Gradle 8.14, and Kotlin DSL.
buildSrc/build.gradle.kts
projectDir.parentFile
.resolve("gradle.properties")
.readLines()
.filter { it.contains("Version") } // I only wanted the versions
.forEach { line ->
val pieces = line.split("=").map { it.trim() }
project.extra[pieces.first()] = pieces.last()
}
You could also load a Java Properties
file, but given it’s pathetic API (you create an empty Properties
, then load
it ), I decided not to.
buildSrc/src/main/kotlin/java-conventions.gradle.kts
val junit5Version: String by project
submodule/build.gradle.kts
plugins {
id("java-conventions")
}
Better use a version catalog for centrally declaring versions and coordinates though.
buildSrc
plugins can’t access versions catalogs without bending over backwards, and falling over.
That’s not true.
Kotlin DSL precompiled script plugins cannot use the type-safe accessors without my hack-around, that is true.
But for example Groovy DSL precompiled script plugins can do.
And any build-logic code can use the VersionCatalogsExtension
and still benefit from the advantages of version catalogs like when doing the<VersionCatalogsExtension>().named("libs").findVersion("junit5")
in a Kotlin DSL precompiled script plugin.
Kotlin DSL precompiled script plugins cannot use the type-safe accessors without my hack-around, that is true.
That’s what I said.
the<VersionCatalogsExtension>().named("libs").findVersion("junit5")
Using string keys wouldn’t be type safe. Besides, this is just version, finding plugins is even messier.
the<VersionCatalogsExtension>().named("libs").findVersion("junit5")
is just as type-safe as
val junit5Version: String by project
with the added value that you benefit from the version catalog advantages.
Besides, this is just version, finding plugins is even messier.
Not really.
Plugins you anyway apply only by ID in a convention plugin and have it as dependency in the buildscript of the build logic project.
And there you can use the libs....
accessors if you just reference the TOML file in its settings script.
Well, if you insist that this monstrosity is equally type-safe and developer-friendly as val junit5Version: String by project
, then it’s a matter of your personal opinion, which I’d refrain from delving into.
What is a fact is that there are many developers who tried to use gradle.properties
or libs.versions.toml
in a similar manner in buildSrc
as they would do in a regular module, and found to their surprise that they couldn’t. It’s just bad design that no amount of insistence will change.
Well, if you insist that this monstrosity
It’s only a “monstrosity” because it is written as one-liner.
Typically you would get multiple things so for example have a variable called libs
.
is equally type-safe
That’s just a fact.
val junit5Version: String by project
is not more than syntactic sugar over val junit5Version = project.getProperty("junit5Version")
which just the same uses a string to lookup the version,
so is equally typesafe as val junit5Version = libs.findVersion("junit5")
.
and developer-friendly
I did not say it is as developer-friendly.
But the big points are, that
refreshVersions
Gradle plugin, dependency updater bots, … can easily understand the format and work with it, …But hey, it is just a recommendation after all.
You are free to use whatever works for you, you have to live with the consequences, I just share my expertise with you, what you do with the information is up to you.
It’s just bad design that no amount of insistence will change.
No, it’s not.
The point is, that buildSrc
or an included build with build logic is a completely separate standalone build, that runs before your build and produces plugins that you then apply to your project.
Version catalogs are not baked-in, they are defined by the consumer of your plugin, so you cannot easily provide types-safe accessors for the entries, because type-safe accessors are only generated for the things that Gradle knows will be there when used. But when compiling the plugin, Gradle simply cannot know what version catalogs or version catalog entries will be there in the project that is going to apply the plugin, unless you tell it, for example using my hack-around for which an essential part is, that you apply the exact same verison catalog to your main build and the build-logic build. Because my hack-around has the exact same pre-requisite as using the VersionCatalogsExtension
, namely that the consuming project has to define a version catalog with the expected entries, just like with your solution where you require that the consuming project has the expected entries in the properties file. So design-wise it is just the same as your solution.
But hey, if you don’t like the design, feel free to suggest to the Gradle folks to change it in an GitHub issue, I’m just a user like you.