Access project extra properties in buildscript closure - gradle

I am new to gradle and have some question about project properties.
I need to declare spring boot dependences at multiple locations in my build.gradle and I'd like to use a variable to define the version. What is the best way in gradle? (in Maven, I use properties)
My attempt is use extra properties, but it cannot access the property in the buildscript closure. I googled around and read many articles accessing properties in custom tasks. What did I miss?
ext {
springBootVersion = '1.1.9.RELEASE'
}
buildscript {
print project.springBootVersion //fails here
repositories {
mavenLocal()
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${project.springBootVersion}")
}
}
install {
repositories.mavenInstaller {
pom.project {
parent {
groupId 'org.springframework.boot'
artifactId 'spring-boot-starter-parent'
version "${project.springBootVersion}" //this one works
}
}
}
}

Moving the ext block inside the buildscript block solves the problem for me. Not sure if this is officially supported though, as it's effectively configuring project.ext from the (very special) buildscript block.

Because the buildscript block is evaluated first, before springBootVersion has been defined. Therefore, the variable definition must go in the buildscript block before any other definitions:
Source Here
buildscript {
ext {
springBootVersion = '1.1.9.RELEASE'
}
print project.springBootVersion //Will succeed
repositories {
mavenLocal()
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${project.springBootVersion}")
}
}

This will not work.
First of all buildscript block is evaluated at the very beginning, before any other part of groovy script. Hence, properties defined in ext block just does not exist at that time.
Secondly, I'm unsure about if exchanging properties between buildscript and other part of script is possible.

Related

Define global variable for AWS credentials in build.gradle? [duplicate]

I am new to gradle and have some question about project properties.
I need to declare spring boot dependences at multiple locations in my build.gradle and I'd like to use a variable to define the version. What is the best way in gradle? (in Maven, I use properties)
My attempt is use extra properties, but it cannot access the property in the buildscript closure. I googled around and read many articles accessing properties in custom tasks. What did I miss?
ext {
springBootVersion = '1.1.9.RELEASE'
}
buildscript {
print project.springBootVersion //fails here
repositories {
mavenLocal()
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${project.springBootVersion}")
}
}
install {
repositories.mavenInstaller {
pom.project {
parent {
groupId 'org.springframework.boot'
artifactId 'spring-boot-starter-parent'
version "${project.springBootVersion}" //this one works
}
}
}
}
Moving the ext block inside the buildscript block solves the problem for me. Not sure if this is officially supported though, as it's effectively configuring project.ext from the (very special) buildscript block.
Because the buildscript block is evaluated first, before springBootVersion has been defined. Therefore, the variable definition must go in the buildscript block before any other definitions:
Source Here
buildscript {
ext {
springBootVersion = '1.1.9.RELEASE'
}
print project.springBootVersion //Will succeed
repositories {
mavenLocal()
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${project.springBootVersion}")
}
}
This will not work.
First of all buildscript block is evaluated at the very beginning, before any other part of groovy script. Hence, properties defined in ext block just does not exist at that time.
Secondly, I'm unsure about if exchanging properties between buildscript and other part of script is possible.

Gradle: manage dependency/plugin versions in multi-project builds

I was working with Maven before Gradle and Maven has such things like dependencyManagement and pluginManagement what allows to keep all versions "DRY" in one place with help of "properties".
Gradle supports project properties, so I can declare versions like:
buildscript {
ext.kotlin_version = '1.1.61'
repositories {
mavenCentral()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
But this approach cannot be applied to plugins {} DSL. I cannot write something like this:
plugins {
id 'org.jetbrains.kotlin:kotlin-gradle-plugin' version $kotlin_version
}
As according to docs:
values must be literal (e.g. constant strings, not variables)
Is there a way to workaround this limitation?
The latest versions of Gradle allows you to define your versions in a property file, map that version in a pluginManagement block, and then omit the version from all downstream plugin blocks. The pluginManagement block does not have the only-constant restriction.
In fact, once you use this approach, it is a compile time error to even try to declare a version downstream.
After using this approach, there is a good chance you can completely omit your buildscript.
gradle.properties
kotlinVersion=1.3.50
settings.gradle
pluginManagement {
resolutionStrategy {
eachPlugin {
if (requested.id.id == "org.jetbrains.kotlin.jvm") {
useVersion(kotlinVersion)
}
}
}
}
build.gradle
plugins {
id("org.jetbrains.kotlin.jvm")
}
If you are into kotlinscript, get your version from a delegate:
settings.gradle.kts
val kotlinVersion: String by settings
pluginManagement {
resolutionStrategy {
eachPlugin {
if (requested.id.id == "org.jetbrains.kotlin.jvm") {
useVersion(kotlinVersion)
}
}
}
}
Of course, you do not need the properties file. You can just hard code the version in your gradle.settings. But by having the property, you can then declare dependencies to the stdlib using it.
I think you can put the ext closure in a separate properties.gradle, and then reference the properties twice in buildscript as well as project build (buildscript block is evaluated at the very beginning, before any other part of groovy script).
For example, in $projectRoot/gradle/properties.gradle as below:
ext {
kotlinVersion = '1.1.61' // NOTE, the naming convention is better with kotlinVersion instead of kotlin_version
}
And your $projectRoot/build.gradle would look like this:
buildscript {
apply from: "gradle/properties.gradle"
repositories {
jcenter()
}
dependencies {
println "In buildscript, kotlinVersion is $kotlinVersion"
}
}
apply plugin: 'java'
apply from: "gradle/properties.gradle"
repositories {
jcenter()
}
dependencies {
println "In project, kotlinVersion is $kotlinVersion"
}
When you run ./gradlew dependencies, it would show you the populated versions:
> Configure project :
In buildscript, kotlinVersion is 1.1.61
In project, kotlinVersion is 1.1.61

Why does this string replacement/concatenation not work in Gradle?

In this snippet of a build.gradle file, the first reference to ${appengineVersion} (line 11) causes an error. But the second reference (line 27) works fine. Why is that?
To get it working, I've had to explicitly include the version number on line 11...meaning that I'm going to forget to update it next time. How to fix that?
apply plugin: 'war'
apply plugin: 'appengine'
def appengineVersion = "1.9.48"
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath "com.google.appengine:gradle-appengine-plugin:${appengineVersion}"
}
}
war {
from 'src/main/webUI/app'
exclude('src/main/webUI/app/node_modules')
}
repositories {
mavenLocal()
mavenCentral()
}
dependencies {
appengineSdk "com.google.appengine:appengine-java-sdk:${appengineVersion}"
compile "javax.servlet:servlet-api:2.5"
...
Standard gradle practice is to declare user-defined properties in the ext namespace. See here
You should do:
ext.appengineVersion = "1.9.48"
Declaring vars on the top level of a project build file doesn’t make them visible to all Gradle blocks. buildscript {} is special, it gets evaluated before any other part of the script is. You can move declaration into the buildscript though, it should make it visible to other blocks too:
buildscript {
def appengineVersion = "1.9.48"
...
but you would need to use like
dependencies {
appengineSdk "com.google.appengine:appengine-java-sdk:" + appengineVersion
The solution was a combination of the answers from Oleg and RaGe:
Move the declaration of appengineVersion into the buildscript block AND define it in the ext namespace.
buildscript {
ext.appengineVersion = "1.9.48"
repositories {
mavenCentral()
}
dependencies {
classpath "com.google.appengine:gradle-appengine-plugin:${appengineVersion}"
}
}
This allowed it variable to be resolved both by the buildscript dependency and the project dependency:
dependencies {
appengineSdk "com.google.appengine:appengine-java-sdk:${appengineVersion}"
compile "javax.servlet:servlet-api:2.5"
compile "com.google.appengine:appengine-api-1.0-sdk:${appengineVersion}"
Both answers were a key part of the solution. But unfortunately, I can't accept 2 answers, so I'm answering it myself (and up-voting both answers).

LibGdx version variable in gradle classpath dependencies [duplicate]

I am new to gradle and have some question about project properties.
I need to declare spring boot dependences at multiple locations in my build.gradle and I'd like to use a variable to define the version. What is the best way in gradle? (in Maven, I use properties)
My attempt is use extra properties, but it cannot access the property in the buildscript closure. I googled around and read many articles accessing properties in custom tasks. What did I miss?
ext {
springBootVersion = '1.1.9.RELEASE'
}
buildscript {
print project.springBootVersion //fails here
repositories {
mavenLocal()
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${project.springBootVersion}")
}
}
install {
repositories.mavenInstaller {
pom.project {
parent {
groupId 'org.springframework.boot'
artifactId 'spring-boot-starter-parent'
version "${project.springBootVersion}" //this one works
}
}
}
}
Moving the ext block inside the buildscript block solves the problem for me. Not sure if this is officially supported though, as it's effectively configuring project.ext from the (very special) buildscript block.
Because the buildscript block is evaluated first, before springBootVersion has been defined. Therefore, the variable definition must go in the buildscript block before any other definitions:
Source Here
buildscript {
ext {
springBootVersion = '1.1.9.RELEASE'
}
print project.springBootVersion //Will succeed
repositories {
mavenLocal()
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${project.springBootVersion}")
}
}
This will not work.
First of all buildscript block is evaluated at the very beginning, before any other part of groovy script. Hence, properties defined in ext block just does not exist at that time.
Secondly, I'm unsure about if exchanging properties between buildscript and other part of script is possible.

Gradle Custom buildScriptRepository methods

I would like to make a custom buildScript repository method so I can easily reference our internal maven repo. Right now I'm required to declare a maven block everywhere we use our plugin.
Here is the current setup
buildscript {
repositories {
jcenter()
maven { url 'http://myNexus:8081/nexus/content/repositories/My-Release' }
}
dependencies {
classpath 'com.example.plugin:my-plugin:1+'
}
}
What I would like to do is something like this
buildscript {
repositories {
jcenter()
myReleaseRepo()
}
dependencies {
classpath 'com.example.plugin:my-plugin:1+'
}
}
How can I make a method available to create a repository anywhere we may use the plugin in the future?
Another solution is to add custom methods on RepositoryHandler using some Groovy goodness. Just chuck this in ~/.gradle/init.gradle
RepositoryHandler.metaClass.myReleaseRepo = {
delegate.maven {
name 'myReleaseRepo'
url 'http://myNexus:8081/nexus/content/repositories/My-Release'
}
}
After that, you can use it just as you described:
buildscript {
repositories {
myReleaseRepo()
}
}
Metaclasses in Groovy are just great. The delegate in this case is pretty much like the javascript this. This code is essentially using the RepositoryHandler instance (delegate keyword) and just calling repositoryHandlerInstance.maven(name, url).
It is possible to add a repo to an init script which would then apply to all gradle invocations that use the init script - without having to individually declare your maven repo in each build.gradle.
Solution 1:
Partial solution, does not do exactly what you're asking for. In init.gradle:
allprojects{
buildscript{
repositories{
maven{ url 'http://myNexus:8081/nexus/content/repositories/My-Release' }
}
}
}
Then your build.gradle can skip buildscript repo declaration entirely:
buildscript {
dependencies {
classpath 'com.example.plugin:my-plugin:1+'
}
}
Solution 2:
In fact, you can even move your buildscript classpath declaration to init and have the plugin apply to all projects that use the init script:
beefier init.gradle
allprojects{
buildscript{
repositories{
maven{ url 'http://myNexus:8081/nexus/content/repositories/My-Release' }
}
dependencies {
classpath 'com.example.plugin:my-plugin:1+'
}
}
}
gives you a lighter build.gradle
apply plugin: 'my-plugin'
I tried to, but apparently you cannot move the apply line to init.gradle as well. see this defect.
Solution 3:
I retract what I said in the comment above, I figured out how to do exactly what you're asking for. Apparently you can create extensions for the buildscript block using the initscript. However I still prefer solution2, because it gives you a cleaner build.gradle.
To create a buildscript extension, in your init.gradle:
class customRepos {
def buildscript
customRepos(buildscript) {
this.buildscript = buildscript
}
void addMyRepo() {
buildscript.repositories {
maven{ url 'http://myNexus:8081/nexus/content/repositories/My-Release' }
}
}
}
allprojects {
extensions.create('myRepo', customRepos, buildscript)
}
which then allows you to do this in your build.gradle
buildscript{
myRepo.addMyRepo()
dependencies {
classpath 'com.example.plugin:my-plugin:1+'
}
}
apply plugin: 'my-plugin'

Resources