How to add string replacement to plugins block [duplicate] - gradle

One of my build scripts imports that nebula plugin:
plugins {
id 'nebula.ospackage' version '3.5.0'
}
I've been moving all of my version info into a separate file that all projects have access to and am wondering what is the correct syntax to convert to something like:
plugins {
id 'nebula.ospackage' version "$versions.nebula_gradle_ospackage_plugin"
}
When I try running the above with "gradle clean build", I get the following error:
build file 'build.gradle': 2: argument list must be exactly 1 literal
non empty string
See
https://docs.gradle.org/2.7/userguide/plugins.html#sec:plugins_block
for information on the plugins {} block
# line 2, column 33.
id 'nebula.ospackage' version "$versions.nebula_gradle_ospackage_plugin"
The linked article shows how I could use the "buildscript" block, which works, but it seems like there must be a way to make this work in a single line?

As of Gradle 5.6, you can declare your plugin versions in the gradle.properties file, and reference these properties in plugins block.
For example, the gradle.properties file:
springBootVersion=2.2.0.RELEASE
the plugins block in build.gradle:
plugins {
id "org.springframework.boot" version "${springBootVersion}"
}
See: https://github.com/gradle/gradle/issues/1697#issuecomment-506910915.
See also:
https://docs.gradle.org/5.6/release-notes.html#central-management-of-plugin-versions-with-settings-script
https://docs.gradle.org/5.6/userguide/plugins.html#sec:plugin_management

You cannot use variable here:
Where «plugin version» and «plugin id» must be constant, literal,
strings. No other statements are allowed; their presence will cause a
compilation error.

This is an old post, but the bug is still open, and I found this post looking for workarounds.
It seems you were aware of this already, and actually have BoygeniusDexter's answer, but I think this may help others finding this post like I did. The following workaround is based on the Gradle docs and solved the problem for me:
buildscript {
ext {
springBootVersion = '2.0.4.RELEASE'
}
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
}
}
plugins {
id 'java'
// and other plugins
id 'io.spring.dependency-management' version '1.0.6.RELEASE'
}
// but the one with the variable version is applied the old way:
apply plugin: 'org.springframework.boot'
// We can use the variable in dependencies, too:
dependencies {
compile group: 'org.springframework.boot', name: 'spring-boot-starter-web', version: springBootVersion
// ...
}

In addition to #zhouji comment, you can not only specify the versions in gradle.properties, but you can also define it programmatically like:
buildscript {
ext {
kotlinVersion = "${JavaVersion.current().isCompatibleWith(JavaVersion.VERSION_16) ? '1.5.32' : '1.4.32'}"
}
}
plugins {
id 'org.jetbrains.kotlin.jvm' version "${kotlinVersion}"
}

Gradle 7
Gradle 7 introduced version catalogs for declaring dependencies and sharing them between projects/modules.
Plugins can be declared in the catalog:
// settings.gradle
dependencyResolutionManagement {
versionCatalogs {
libs {
version('android-plugins', '7.3.0')
plugin('android-application', 'com.android.application').versionRef('android-plugins')
// A library declaration using the same version.
library('some-library', 'com.group', 'artifact').versionRef('android-plugins')
}
}
}
The declaration can be referred to in the plugins block:
// build.gradle
plugins {
alias(libs.plugins.android.application) apply false
}
The version can also be referred to in the plugins block:
// build.gradle
plugins {
id 'com.android.application' version libs.versions.android.plugins apply false
}
See the version catalogs documentation for more information.
Note: In the declaration, - is used as separator in the dependency name. On the consuming side . is used instead, as - is the sign for the minus operator of the groovy language and can't be used in property names.
So the separators are different on the declaring and consuming side - which threw me off at first.

Summary
Omit the version from the plugin block
Move/specify the version in the buildscript.dependencies block, instead
Use a variable in that block that is a const variable
In short, plugin blocks require string literals or properties whereas dependency blocks permit varables. The original question asks for doing this in a "single line" and with this approach, your plugin block is shorter and all your dependencies live in one place for all modules. Depending on your goals, that might be better than doing everything in "one line."
Full Example
For Android, I was able to do this by omitting the version from the plugin block and then specifying it as a const in the buildscript dependencies, instead. That block allows variables, whereas the plugin block only allows string literals. From there, I use an object in buildSrc because that provides the most flexibility, while keeping all dependency info in one file for all modules. So my setup looks like this:
├── project/
│ ├── build.gradle
| └── app/
| └── build.gradle
| └── buildSrc/
| └── build.gradle.kts
| └── src/main/java/com/example/package/Deps.kt
From there, to specify any plugin version as a variable in one place, the app/build.gradle file omits the version (using kotlin as an example but the same approach works for any plugin):
app/build.gradle
plugins {
id 'kotlin-android' // omit version property here but provide it in buildscript dependencies
...
}
...
dependencies {
...
// Dagger
implementation Deps.Dagger.ANDROID_SUPPORT
kapt Deps.Dagger.ANDROID_PROCESSOR
kapt Deps.Dagger.COMPILER
}
Then the buildscript dependency section (usually in the parent build.gradle file but can also be in the same file) provides the version USING A VARIABLE!
project/build.gradle
import com.example.package.Deps // object in the buildSrc folder with all version info
buildscript {
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${Deps.kotlinVersion}"
}
}
Lastly, all the version information is managed in buildSrc, with an object in the Deps.kt file (there are many blog posts out there on using buildSrc with Android projects):
Deps.kt
object Deps {
// For use in the top-level buildscript dependency section which only works with a constant rather than `Deps.Kotlin.version`
const val kotlinVersion = "1.3.72"
object Kotlin : Version(kotlinVersion) {
val STDLIB = "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$version"
}
object Dagger : Version("2.25.2") {
val ANDROID_SUPPORT = "com.google.dagger:dagger-android-support:$version"
val ANDROID_PROCESSOR = "com.google.dagger:dagger-android-processor:$version"
val COMPILER = "com.google.dagger:dagger-compiler:$version"
}
}
open class Version(#JvmField val version: String)
Overall, I really like this setup. It's flexible, all dependency info is in one place, even across multiple modules and, best of all, it allows for code completion in the gradle files, when typing dependencies!

// gradle.properties
springBootVersion=2.6.7
// settings.gradle.kts
pluginManagement {
val springBootVersion: String by settings
plugins {
id("org.springframework.boot") version springBootVersion
}
}
// build.gradle.kts
plugins {
id("org.springframework.boot")
}

I hit this issue.
when I ran
gradle clean test build
instead of
./gradlew clean test build
and my "gradle" was at version 4.x
but my ./gradlew resolved to 6.9 or higher.
aka, "oops, I forgot my build.gradle files were coded to use later versions of gradle(w), but I snapfu-ed and executed the older 4.x version of regular "gradle"

Related

Gradle bundle import to module

I am trying to import base to a project, but I get an error.
settings.gradle
enableFeaturePreview('VERSION_CATALOGS')
dependencyResolutionManagement {
versionCatalogs {
libs {
// https://mvnrepository.com/artifact/org.springframework/spring-core
version('spring', '5.3.14')
// https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter
version('spring-boot', '2.6.2')
alias('spring-core').to('org.springframework', 'spring-core').versionRef('spring')
alias('spring-context').to('org.springframework', 'spring-context').versionRef('spring')
alias('spring-boot').to('org.springframework.boot', 'spring-boot-starter').versionRef('spring-boot')
bundle('base', ['spring-core', 'spring-context'])
}
}
}
module's build.gradle
dependencies {
implementation(libs.base)
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.7.0'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.7.0'
}
refreshing gradle will produce the following error
Could not get unknown property 'base' for extension 'libs' of type org.gradle.accessors.dm.LibrariesForLibs.
How to import libs.base correctly?
The correct way of referencing a bundle from a version catalog is
libs.bundles.base
Similarly for plugins use:
libs.plugins.yourplugin
It is also possible to reference versions, but this works slightly different. For example:
implementation group: "org.springframework.boot", name: "spring-boot-starter-web-services", version: libs.versions.spring.boot.get()
This assumes a version definition in your catalog which looks like:
version('spring-boot', '2.6.7')
Note that bundles, versions and plugins are all spelled as plural.
Also note that as of Gradle 7 version catalogs are no longer a feature preview. They are available by default. Also, the notation for libraries has changed slightly. You have to use library instead of alias.
See Gradle's support site for more information.

Gradle7 Version Catalog: How to use it with buildSrc?

I am very excited about the incubating Gradle's version catalogs and have been experimenting with it. I’ve found that the information in my gradle/libs.versions.toml is accessible in the build.gradle.kts scripts for my app and utility-lib projects.
However, I am unable to use the content of the toml file for buildSrc/build.gradle.kts or the convention files.
The only way that I could build was to hard-code the dependencies into those files, as I did before the version catalog feature.
In the buildSrc folder, I created a settings.gradle.kts file and inserted the dependencyResolutionManagement code for versionCatalogs, which is pointing to the same file as for my app and utility-lib projects.
Based on the Gradle7 docs, it seems that sharing a version catalog with buildSrc and modules is possible… I’d appreciate a nudge into getting it to work with buildSrc, if possible.
Here is a simple sample project, which I created via gradle init: my-version-catalog
Thank you for your time and help,
Mike
With Gradle 7.3.3, it is possible. Note version catalogs are GA since Gradle 7.4
The code snippet assumes Gradle is at least 7.4, but if you need them prior that version, insert enableFeaturePreview("VERSION_CATALOGS") at the beginning of each settings.gradle.kts.
Using buildSrc
buildSrc/settings.gradle.kts
dependencyResolutionManagement {
versionCatalogs {
create("libs") {
from(files("../gradle/libs.versions.toml"))
}
}
}
buildSrc/build.gradle.kts
dependencies {
implementation(libs.gradleplugin.intellij) // <- the lib reference
}
You can even use the version catalog for plugins
gradle/libs.versions.toml
...
[plugins]
kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
jetbrains-changelog = { id = "org.jetbrains.changelog", version.ref = "changelog-plugin" }
jetbrains-intellij = { id = "org.jetbrains.intellij", version.ref = "intellij-plugin" }
hierynomus-license = { id = "com.github.hierynomus.license", version.ref = "license-plugin" }
nebula-integtest = { id = "nebula.integtest", version.ref = "nebula-integtest-plugin" }
build.gradle.kts
plugins {
id("java")
alias(libs.plugins.kotlin.jvm)
alias(libs.plugins.nebula.integtest)
alias(libs.plugins.jetbrains.intellij)
alias(libs.plugins.jetbrains.changelog)
alias(libs.plugins.hierynomus.license)
}
Note for accessing the catalog within scripts, please refer to the below section, the trick is the same.
Using convention plugins and included build
In the main project include a the Gradle project that holds the convention plugins.
build.gradle.kts
includeBuild("convention-plugins") // here it's a subfolder
convention-plugins/settings.gradle.kts
dependencyResolutionManagement {
repositories {
gradlePluginPortal()
}
versionCatalogs {
create("libs") {
from(files("../gradle/libs.versions.toml"))
}
}
}
rootProject.name = "convention-plugins"
The trick to enable convention plugins to access the version catalog is split in two part, add an ugly implementation dependency that locate where the version catalog generated classes are located.
libs.javaClass.superclass.protectionDomain.codeSource.location
Then in the convention plugin refer to the libs extension via Project::the.
val libs = the<LibrariesForLibs>()
This is tracked by gradle/gradle#15383.
convention-plugins/build.gradle.kts
plugins {
`kotlin-dsl`
}
dependencies {
implementation(libs.gradleplugin.kotlin.jvm)
// https://github.com/gradle/gradle/issues/15383
implementation(files(libs.javaClass.superclass.protectionDomain.codeSource.location))
}
And in the actual convention plugin
import org.gradle.accessors.dm.LibrariesForLibs
plugins {
id("org.jetbrains.kotlin.jvm")
}
// https://github.com/gradle/gradle/issues/15383
val libs = the<LibrariesForLibs>()
dependencies {
detektPlugins(libs.bundles.kotlinStuff) // access catalog entries
}
The org.gradle.accessors.dm.LibrariesForLibs class is generated by gradle is somewhere in local gradle folder ./gradle/<version>/dependency-accessors/<hash>/classes
Quick note that older IntelliJ IDEA currently (2022.3) reports alias(libs.gradleplugin.thePlugin) as an error in the editor,
although the dependencies are correctly resolved.
This tracked by KTIJ-19369, the ticket indicates this is actually a bug in Gradle Kotlin DSL gradle/gradle#22797, and someone made a simple IntelliJ IDEA plugin to hide this error until resolved.
Brice, it looks like a can of worms to go down that path, particularly for my situation, where I'm trying to use a libs.version.toml file from an android project, but the custom plugin is of course from a java/kotlin project. I tried creating the libs file by hardwiring the path to the toml file in the custom plugin. It might work if both were java projects, but I never tried that since that's not what I'm after. The ideal solution would be for the plugin to use the libs file from the project it is applied to, but it looks like the version catalog needs to be created in the settings file, before you even have access to "Project", so that's why you would have to hardwire the path.
Short answer. No, but there are other techniques for a custom plugin to get project version data from the project it is applied to.

Gradle cannot find plugin declared in buildscript

I'm trying to factor out common Gradle tasks in a reusable file. Here is an excerpt of a build-root.gradle file:
buildscript {
// Repository declaration
ext {
isSnapshot = version.endsWith("-SNAPSHOT")
repos = {
def mavenRepo = { repoName, repoUrl ->
maven {
credentials {
username System.env.<some env var>
password System.env.<some env var>
}
name repoName
url repoUrl
}
}
mavenLocal()
mavenRepo('repo1', 'https://repo1.url')
mavenRepo('repo2', 'https://repo2.url')
mavenRepo('repo3', 'https://repo3.url')
}
}
// Versions and libraries declaration
ext {
versions = [
... some stuff
// Gradle
gradleRelease : '2.8.1',
... more stuff
]
libs = [
... some stuff
// Gradle
gradleRelease : "net.researchgate:gradle-release:$versions.gradleRelease",
... more stuff
]
}
repositories repos
dependencies {
classpath libs.gradleRelease
}
apply plugin: 'net.researchgate.release'
}
... more common stuff
The idea is for subprojects to apply from that file and get all the goodies from it.
On the "apply plugin" line I get the following error - > Plugin with id 'net.researchgate.release' not found.
I printed the libs.gradleRelease string, it looks fine: net.researchgate:gradle-release:2.8.1
We are currently using Gradle 5.2.1, but I also tried 6.0.1 - same error. Any ideas why it can't find the plugin? BTW, this is not exclusive to this particular plugin, I tried others and still get the same error.
After pulling whatever was left of my hair and banging my head against the wall, I came across this => https://discuss.gradle.org/t/how-do-i-include-buildscript-block-from-external-gradle-script/7016
Relevant comment from #Peter_Niederwieser:
"Secondly, externalizing a build script block into a script plugin isn’t supported. (It’s a tough problem, and can’t think of a good way to implement this.) You may have to live with some duplication, at least for the time being. Remember that dependencies specified in a project’s ‘buildscript’ block are visible to all subprojects. Hence, as long as you don’t need dependencies to be available in a script plugin, you just need to declare them in the root project’s build script."
Which is exactly what I was trying to do. I'm not going to curse here...

In gradle, how to use a variable for a plugin version?

One of my build scripts imports that nebula plugin:
plugins {
id 'nebula.ospackage' version '3.5.0'
}
I've been moving all of my version info into a separate file that all projects have access to and am wondering what is the correct syntax to convert to something like:
plugins {
id 'nebula.ospackage' version "$versions.nebula_gradle_ospackage_plugin"
}
When I try running the above with "gradle clean build", I get the following error:
build file 'build.gradle': 2: argument list must be exactly 1 literal
non empty string
See
https://docs.gradle.org/2.7/userguide/plugins.html#sec:plugins_block
for information on the plugins {} block
# line 2, column 33.
id 'nebula.ospackage' version "$versions.nebula_gradle_ospackage_plugin"
The linked article shows how I could use the "buildscript" block, which works, but it seems like there must be a way to make this work in a single line?
As of Gradle 5.6, you can declare your plugin versions in the gradle.properties file, and reference these properties in plugins block.
For example, the gradle.properties file:
springBootVersion=2.2.0.RELEASE
the plugins block in build.gradle:
plugins {
id "org.springframework.boot" version "${springBootVersion}"
}
See: https://github.com/gradle/gradle/issues/1697#issuecomment-506910915.
See also:
https://docs.gradle.org/5.6/release-notes.html#central-management-of-plugin-versions-with-settings-script
https://docs.gradle.org/5.6/userguide/plugins.html#sec:plugin_management
You cannot use variable here:
Where «plugin version» and «plugin id» must be constant, literal,
strings. No other statements are allowed; their presence will cause a
compilation error.
This is an old post, but the bug is still open, and I found this post looking for workarounds.
It seems you were aware of this already, and actually have BoygeniusDexter's answer, but I think this may help others finding this post like I did. The following workaround is based on the Gradle docs and solved the problem for me:
buildscript {
ext {
springBootVersion = '2.0.4.RELEASE'
}
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
}
}
plugins {
id 'java'
// and other plugins
id 'io.spring.dependency-management' version '1.0.6.RELEASE'
}
// but the one with the variable version is applied the old way:
apply plugin: 'org.springframework.boot'
// We can use the variable in dependencies, too:
dependencies {
compile group: 'org.springframework.boot', name: 'spring-boot-starter-web', version: springBootVersion
// ...
}
In addition to #zhouji comment, you can not only specify the versions in gradle.properties, but you can also define it programmatically like:
buildscript {
ext {
kotlinVersion = "${JavaVersion.current().isCompatibleWith(JavaVersion.VERSION_16) ? '1.5.32' : '1.4.32'}"
}
}
plugins {
id 'org.jetbrains.kotlin.jvm' version "${kotlinVersion}"
}
Gradle 7
Gradle 7 introduced version catalogs for declaring dependencies and sharing them between projects/modules.
Plugins can be declared in the catalog:
// settings.gradle
dependencyResolutionManagement {
versionCatalogs {
libs {
version('android-plugins', '7.3.0')
plugin('android-application', 'com.android.application').versionRef('android-plugins')
// A library declaration using the same version.
library('some-library', 'com.group', 'artifact').versionRef('android-plugins')
}
}
}
The declaration can be referred to in the plugins block:
// build.gradle
plugins {
alias(libs.plugins.android.application) apply false
}
The version can also be referred to in the plugins block:
// build.gradle
plugins {
id 'com.android.application' version libs.versions.android.plugins apply false
}
See the version catalogs documentation for more information.
Note: In the declaration, - is used as separator in the dependency name. On the consuming side . is used instead, as - is the sign for the minus operator of the groovy language and can't be used in property names.
So the separators are different on the declaring and consuming side - which threw me off at first.
Summary
Omit the version from the plugin block
Move/specify the version in the buildscript.dependencies block, instead
Use a variable in that block that is a const variable
In short, plugin blocks require string literals or properties whereas dependency blocks permit varables. The original question asks for doing this in a "single line" and with this approach, your plugin block is shorter and all your dependencies live in one place for all modules. Depending on your goals, that might be better than doing everything in "one line."
Full Example
For Android, I was able to do this by omitting the version from the plugin block and then specifying it as a const in the buildscript dependencies, instead. That block allows variables, whereas the plugin block only allows string literals. From there, I use an object in buildSrc because that provides the most flexibility, while keeping all dependency info in one file for all modules. So my setup looks like this:
├── project/
│ ├── build.gradle
| └── app/
| └── build.gradle
| └── buildSrc/
| └── build.gradle.kts
| └── src/main/java/com/example/package/Deps.kt
From there, to specify any plugin version as a variable in one place, the app/build.gradle file omits the version (using kotlin as an example but the same approach works for any plugin):
app/build.gradle
plugins {
id 'kotlin-android' // omit version property here but provide it in buildscript dependencies
...
}
...
dependencies {
...
// Dagger
implementation Deps.Dagger.ANDROID_SUPPORT
kapt Deps.Dagger.ANDROID_PROCESSOR
kapt Deps.Dagger.COMPILER
}
Then the buildscript dependency section (usually in the parent build.gradle file but can also be in the same file) provides the version USING A VARIABLE!
project/build.gradle
import com.example.package.Deps // object in the buildSrc folder with all version info
buildscript {
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${Deps.kotlinVersion}"
}
}
Lastly, all the version information is managed in buildSrc, with an object in the Deps.kt file (there are many blog posts out there on using buildSrc with Android projects):
Deps.kt
object Deps {
// For use in the top-level buildscript dependency section which only works with a constant rather than `Deps.Kotlin.version`
const val kotlinVersion = "1.3.72"
object Kotlin : Version(kotlinVersion) {
val STDLIB = "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$version"
}
object Dagger : Version("2.25.2") {
val ANDROID_SUPPORT = "com.google.dagger:dagger-android-support:$version"
val ANDROID_PROCESSOR = "com.google.dagger:dagger-android-processor:$version"
val COMPILER = "com.google.dagger:dagger-compiler:$version"
}
}
open class Version(#JvmField val version: String)
Overall, I really like this setup. It's flexible, all dependency info is in one place, even across multiple modules and, best of all, it allows for code completion in the gradle files, when typing dependencies!
// gradle.properties
springBootVersion=2.6.7
// settings.gradle.kts
pluginManagement {
val springBootVersion: String by settings
plugins {
id("org.springframework.boot") version springBootVersion
}
}
// build.gradle.kts
plugins {
id("org.springframework.boot")
}
I hit this issue.
when I ran
gradle clean test build
instead of
./gradlew clean test build
and my "gradle" was at version 4.x
but my ./gradlew resolved to 6.9 or higher.
aka, "oops, I forgot my build.gradle files were coded to use later versions of gradle(w), but I snapfu-ed and executed the older 4.x version of regular "gradle"

How can I make Gradle extensions lazily evaluate properties that are set dynamically by tasks?

I'm pretty new to working with Gradle and I'm trying to develop a plugin that helps manage version numbering. This plugin defines a task that sets the project.version property of the project it's applied to.
What I'm trying to do is make it so that this property is set at the start of every Gradle build. Using Peter's answer to another Gradle question, I've managed to get my task to execute before any other by adding gradle.startParameter.taskNames = [":setProjectVersionNumber"] + gradle.startParameter.taskNames within my plugin's apply method.
However, other plugins (notably 'Maven-publish') rely on the version being specified during the configuration phase:
publishing {
publications {
somePublication(MavenPublication) {
version = project.version
}
}
}
What I'd like to know is if there's a way that I can make the evaluation of properties like version within these extensions as lazy as possible - such that they're not evaluated until a task that depends upon them is called, which in this case might be :publishToMavenLocal.
Below is an SSCCE that demonstrates what I'm hoping to achieve:
// This would be included within the plugin
class SetProjectVersionNumber extends DefaultTask {
#TaskAction
void start() {
// This will set project.version during execution phase
project.version = "1.2.3"
logger.info "Set project version number: $project.version"
}
}
task setProjectVersionNumber(type: SetProjectVersionNumber)
// Imagine this block being replaced by a maven 'publishing' block (or something similar)
ext {
version = project.version
// This will print 'unspecified', as it's evaluated during configuration phase
println "In extension, setting version=$project.version"
}
If you can provide a way to make ext.version equal 1.2.3 in the example above, I believe you've resolved my issue.
If this is asking too much, it may be possible for me to make my plugin generate the version string at configuration-time rather than execution-time. It would be nice to know if I could do it this way, though.
EDIT
In an experimental branch, I tried moving all the version string assignment logic to the configuration-phase (by making it all happen during plugin application rather than during task execution), but I don't believe this will work as the plugin extension has not yet been processed and trying to refer to properties defined in it fail.
EDIT 2
Wrapping the version string assignment logic in a project.afterEvaluate closure seems to have worked:
#Override
public void apply(Project project) {
logger = project.logger
project.extensions.create(EXTENSION_NAME, SemVerPluginExtension)
project.afterEvaluate {
setVersionProjectNumber(project)
addTasks(project)
}
}
In a mock project, I implement build.gradle as follows:
apply plugin: 'semver'
apply plugin: 'maven-publish'
group = 'temp'
buildscript {
repositories {
mavenLocal()
jcenter()
}
dependencies {
classpath 'com.github.tagc:semver-plugin:0.2.2'
}
}
semver {
versionFilePath = 'version.properties'
}
publishing {
publications {
testPublication(MavenPublication) {
version = project.version
assert version
println "Set publication version to $version"
}
}
}
For some reason, this seems to work. Although the version string assignment logic is wrapped in an 'afterEvaluate' closure and the test publication version assignment isn't, the former still occurs before the latter:
Compiling build file '/Users/davidfallah/Documents/semver/TestSemver2/build.gradle' using StatementExtractingScriptTransformer.
Compiling build file '/Users/davidfallah/Documents/semver/TestSemver2/build.gradle' using BuildScriptTransformer.
VERSION FILE PATH=version.properties
Current Git branch: develop
Set project version to 0.2.1-SNAPSHOT
Set publication version to 0.2.1-SNAPSHOT
All projects evaluated.
I'm leaving this question open and unresolved since I'd still like to know if it's possible to do it the way I originally intended. Additionally, I'd appreciate any explanation about why the publication version is assigned after the project version is set, and whether I can depend on that always being the case or whether that's just happening now by accident.
You can use lazy instantiation of GStrings to evaluate properties at run time:
project.tasks.create("example_task", Exec.class, {
commandLine 'echo', "${-> project.someproperty}"
})
Note that you have to use quotation marks and not apostrophes - "${...}" works, but '${...}' does not.

Resources