Scope of the extra properties in Gradle?

10,718

Extra properties should be created via ext but referred via project instance without any instance at all so: project.dir or dir, so the first change to script will be:

ext {
  dir = null
}

task init << {
  build()
}

task buildAll(type: Exec){
  workingDir dir // ext.dir -> dir
  commandLine 'cmd', '/c', "echo %JAVA_HOME%"
}

def build(){
  ext.dir = "asdf"
  buildAll.execute()
}

Now, before any task or method is executed the script is read and parsed, sot the whole body of buildAll will be configured before any other part is run. Thus it will always fail, since dir property has no value. Proof:

ext {
  dir = null
}

task init << {
  build()
}

task buildAll(type: Exec){
  workingDir dir ? dir : project.rootDir 
  commandLine 'cmd', '/c', "echo %JAVA_HOME%"
}

def build(){
  ext.dir = "asdf"
  buildAll.execute()
}
Share:
10,718
zorglub76
Author by

zorglub76

Updated on July 08, 2022

Comments

  • zorglub76
    zorglub76 almost 2 years

    I have a Gradle script similar to this:

    ext {
      dir = null
    }
    
    task init << {
      build()
    }
    
    task buildAll(type: Exec){
      workingDir ext.dir
      commandLine 'cmd', '/c', "echo %JAVA_HOME%"
    }
    
    def build(){
      ext.dir = "asdf"
      buildAll.execute()
    }
    

    When I run the script, I get:

    groovy.lang.MissingPropertyException: Cannot get property 'dir' on extra properties extension as it does not exist
    

    Whatever I tried, I couldn't get a task to read a property from "ext". It can be seen from methods (like "build()" in my example), but not from any other task except the default one ("init" in my example).

    I understand that the "ext" properties should be accessible from anywhere inside the project, so what am I doing wrong?

    UPDATE: The workflow I'm trying to achieve (as asked by Opal):

    I have several environments I need to build with one script. Each of these environments is listed in a CSV file with a line: <environment>,<version>.

    Script then needs to do the following:

    • Delete existing directory
    • Checkout code from SVN into new directory (both directory and SVN url depend on environment and version)
    • Copy some settings files (paths depend on version)
    • Edit some of those settings files (values depend on environment and version)
    • Set some environment variables (JAVA_HOME, ANT_HOME...) (depends on version)
    • Run three build commands (${ANT_HOME}/bin/ant -f $checkedOutCodeDirectory/Build/build-all.xml target1, then target2 and target3)

    This needs to be executed for each environment

  • zorglub76
    zorglub76 almost 9 years
    That is exactly why I wonder how extra properties should be used. Basically, I want a global variable. How do I get a global variable in Gradle (deprecated solutions, used before extra properties were introduced, should not be considered)?
  • Opal
    Opal almost 9 years
    So define it in ext block and if there's a need to overwrite it pass it with -P command line switch.
  • zorglub76
    zorglub76 almost 9 years
    I already defined it in ext. In order to get the path to the directory ("dir" variable), I need two other variables that I pass using -P, and that is why I can't use "dir" as a parameter to the build script. Oh, well...
  • Opal
    Opal almost 9 years
    @zorglub76, could you please prepare a real world example? If I understand the problem I my help you better.
  • zorglub76
    zorglub76 almost 9 years
    Ok, I updated the original question with the workflow that I'm trying to automate. I'm new to Gradle, and wanted to make the script as Gradle-ly as possible, but at one point I found myself doing almost everything in Groovy, instead of using Gradle features, because of unexpected (seemingly) lack of Gradle features...
  • Opal
    Opal almost 9 years
    @zorglub76 It seems that what you need is not global properties but rather task rules: docs.gradle.org/current/userguide/more_about_tasks.html#N10F‌​07. One rule for single environment. Moreover, using ant from gradle is possible however in your case it seems to be overkill. What don't you switch to gradle fully?
  • zorglub76
    zorglub76 almost 9 years
    I've started working on this project 3 months ago, and the project itself is 20 years old. Build depends on bash, ant gradle and groovy scripts, so it's bit of a mess at the moment... Anyway, you mean that I should dynamically create all tasks and use rules to execute them?
  • Opal
    Opal almost 9 years
    Yes, for now it seems the best option. It would be nice to work on such project. I like tidying things up ;]
  • Opal
    Opal almost 9 years
    @zorglub76, if my answer helped you please accept or even upvote.