Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to set properties for a dependent gradle task

Tags:

gradle

I want to set up a "generic" task which will build app bundles for a number of platforms (it uses javafxpackager). The mechanics of the task apply to creating all platform bundles, but the difference is in the various property used by the task.

I had thought that I would create separate higher level tasks for each platform in which the platform specific properties would be set, and then call/execute/(substitute the correct gradle lingo here) the generic task. E.g.,

task buildMacBundle(dependsOn: ['macBundleConfig', 'buildAppBundle']) << {
  // set Mac-specific properties (project.ext properties?)
  // call/invoke/execute or whatever the mechanism is called, buildAppBundle task
    buildAppBundle.mustRunAfter macBundleConfig
    println "building a Mac app bundle"
}

task macBundleConfig << {
    println "executing macBundleConfig"
    ext {
        nativeType = "dmg"
        bundleAppName = 'My App'
    }
    delete ("${buildDir.name}/dist/${bundleAppName}.dmg")
}


task buildWindowsBundle << {
  // omitted for brevity, but just like buildMacBundle except for property values
}

task buildAppBundle << {

    println "nativeType: ${project.ext.nativeType}" // it stumbles here!

    def cmd = [
        "${javapackager}",
        "-deploy",
        "-native", "${project.ext.nativeType}",
        "-name",
        "${project.bundleAppName}",
        "-outdir",
        "${buildDir.name}${File.separator}dist",
        "-outfile",
        "MyApp",
        "-srcdir",
        "${buildDir.name}${File.separator}${libsDir.name}",
        "-appclass",
        "org.pf.app.MyApp"
    ]

    println cmd.join(" ")

    def javapackager = exec {
        workingDir "${project.projectDir.absolutePath}"
        commandLine cmd
    }
}

But when I run "buildMacBundle", I get

* What went wrong:
Execution failed for task ':buildAppBundle'.
> cannot get property 'nativeType' on extra properties extension as it does not exist

How do I define the properties in the specific task which then invokes the generic task?

like image 874
pfurbacher Avatar asked Jun 03 '14 18:06

pfurbacher


People also ask

How do you set a system property in Gradle task?

To define system properties for our Gradle build we can use the command line option --system-prop or -D . But we can also add the values for system properties in the gradle. properties file of our project. This file contains project properties we want to externalized, but if we prefix the property name with systemProp.

How do you pass properties in Gradle?

Using the -D command-line option, you can pass a system property to the JVM which runs Gradle. The -D option of the gradle command has the same effect as the -D option of the java command. You can also set system properties in gradle. properties files with the prefix systemProp.

How do I add a dependency in Gradle?

To add a dependency to your project, specify a dependency configuration such as implementation in the dependencies block of your module's build.gradle file.


4 Answers

You can try create GradleBuild Task and invoke desired task with given project properties.

task someTask(type: GradleBuild) {
    tasks = ['taskToParametrize']
    startParameter.projectProperties = ['parameterName': 'parameterValue']
}

Then you can query for property:

project.properties['parameterName']    

See Gradle build logic docs.

like image 196
Michal Borek Avatar answered Sep 22 '22 13:09

Michal Borek


I solved it with this:

gradle.taskGraph.whenReady {taskGraph ->
    if (taskGraph.hasTask(buildMacBundle)) {
        project.ext.nativeType = "dmg"
    } else if (taskGraph.hasTask(buildWindowsBundle)){
        project.ext.nativeType = "exe"
    }
}

To me, this is the simplest way, but far from intuitive. It took a great deal of googling to stumble on this in

the User Guide: 6.13. Configure by DAG (whatever DAG is?)

I suspect there's an easier way, but it's not in writing a plugin for sure. Were I to be creating something to be used in more than one build.gradle script, I'd consider a plugin to be the right way to go, but here, in just one build.gradle build script, it's overkill.

like image 35
pfurbacher Avatar answered Sep 21 '22 13:09

pfurbacher


I came across this solution:


task meta1 {
    doLast {
        user.property="variant1"
    }
}

task meta2 {
    doLast {
        user.property="variant2"
    }
}

meta1.finalizedBy buildTask
meta2.finalizedBy buildTask

Where buildTask is the task that does the work, and in this example user.property must be set before the task runs to configure the target configuration. There are two meta tasks, each of which sets the appropriate value for the property, then requires the build task to be run after it, via the finalizedBy command.

Gradle

like image 35
Clyde Avatar answered Sep 22 '22 13:09

Clyde


I faced a similar problem, and I found that if you switch

ext {
    nativeType = "dmg"
    bundleAppName = 'My App'
}

with

project.ext {
    nativeType = "dmg"
    bundleAppName = 'My App'
}

it should work. From what I gather, it's a scoping problem - in the first case you set the property for the Task, and in the second case, for the Project.


By the way, I think that buildAppBundle.mustRunAfter macBundleConfig will run too late for you, as it is part of the buildMacBundle task, so the order of running will be:

  1. macBundleConfig
  2. buildAppBundle
  3. buildMacBundle

and only during 3 will the configuration mustRunAfter of buildAppBundle will be changed.

like image 28
orirab Avatar answered Sep 23 '22 13:09

orirab