How to Get $project.version in Custom Gradle Plugi

2020-07-06 05:33发布

问题:

Within a custom gradle plugin the project.version seems to always be unspecified. Why and how to retrieve the project.version within a custom plugin (class)?

For Example:

apply plugin: 'java'
apply plugin: MyPlugin

version = "1.0.0"

println "In build file: $project.version" 

class MyPlugin implements Plugin<Project> {
  public void apply(Project project) {
    project.task('myTask') {
      println "In plugin: $project.version"
    }
  }
}

Prints out:

%> gradle -q myTask
  In plugin: unspecified
  In build file: 1.0.0

Besides the how I really would like to know the why?

回答1:

You set the property after you call apply

If you move

version = "1.0.0"

To before the line

apply plugin: MyPlugin

It should work

Edit

Following Peter's answer, you can see that this works also:

apply plugin: 'java'
apply plugin: MyPlugin

version = "1.0.0"

println "In build file: $project.version" 

class MyPlugin implements Plugin<Project> {
  public void apply(Project project) {
    project.task('myTask') {
      project.gradle.projectsEvaluated { 
        println "In plugin: $project.version"
      }
    }
  }
}

To delay the evaluation of $project.version until evaluation of the build is complete



回答2:

Dealing with evaluation order is the challenge when writing plugins, and it requires some knowledge and expertise to master.

Notice that in the build script, the plugin gets applied (and therefore executed!) before the version is set. This is the norm, and the plugin has to deal with it. Roughly speaking, whenever the plugin accesses a mutable property of the Gradle object model, it has to defer that access until the end of the configuration phase. (Until then, the value of the property can still change.)

Some of Gradle's APIs (lazy collections, methods accepting callbacks, etc.) provide special support for dealing with this problem. Other than that, you can wrap affected code in project.gradle.projectsEvaluated { ... }, or use the more sophisticated "convention mapping" technique.

The Gradle User Guide and http://forums.gradle.org provide more information on these topics.



回答3:

Check my answer here

You can place this block after the projectEvaluated closure or afterTask closure. I haven't tested just pure standalone, but it may work.

AppExtension android = (AppExtension) project.extensions.findByName("android")
String versionName = android.defaultConfig.versionName
String versionCode = android.defaultConfig.versionCode


标签: groovy gradle