The cd command in my Gradle task is not working. Using it to go to another folder.
task assembleTask(overwrite: true, type:Exec) {
commandLine "gradle", "assembleDev"
doLast {
commandLine "cd tests"
commandLine "ls"
}
}
The Exec task only runs once. You are setting the commandLine property 3 times.
once in the configuration phase, before the task runs
twice after the task has run (this will have no effect)
If you want one task to run another, you might do
task assembleTask {
dependsOn assembleDev
doLast {
file('tests').listFiles().each { File f ->
println f.name
}
}
}
Or perhaps you want a GradleBuild task, not sure
If you want to run multiple execs in a single task you might want to use project.exec() instead of Exec task. Eg:
task assembleTask {
doLast {
exec {
commandLine 'foo'
}
exec {
commandLine 'bar'
}
exec {
commandLine 'baz'
}
}
}
My Gradle task stopped showing the group and description in ./gradlew tasks, since I've added an exec {} in the root build.gradle.
What's going on, and how do I get it back?
task doSomething << {
group 'yourGroupName'
description 'Runs your bash script'
exec {
workingDir "$projectDir/../pathto/"
commandLine 'bash', '-c', './bashscript.sh'
}
}
Everything else works.
You cannot configure group and description in a doLast() closure
this code
task doSomething << {
exec {
workingDir "$projectDir/../pathto/"
commandLine 'bash', '-c', './bashscript.sh'
}
}
is the same than
task doSomething {
doLast {
exec {
workingDir "$projectDir/../pathto/"
commandLine 'bash', '-c', './bashscript.sh'
}
}
}
In the following group and description are not taking into account
task doSomething {
doLast {
group 'yourGroupName'
description 'Runs your bash script'
exec {
workingDir "$projectDir/../pathto/"
commandLine 'bash', '-c', './bashscript.sh'
}
}
}
But here it does :
task doSomething {
group 'yourGroupName'
description 'Runs your bash script'
doLast {
exec {
workingDir "$projectDir/../pathto/"
commandLine 'bash', '-c', './bashscript.sh'
}
}
}
I'm in the early stages of migrating an android project to gradle, using the experimental plugin 0.4.0
As part of the build process I have a number of scripts that should run prior to compiling my code / building the apk. The arguments or tasks themselves will be different for a debug or release build.
I'm struggling to find a straight forward way to achieve this.
I've stripped everything back to a simple hello world project while I figure this out.
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle-experimental:0.4.0'
}
}
apply plugin: 'com.android.model.application'
model {
android {
compileSdkVersion = 23
buildToolsVersion = "23.0.2"
}
android.buildTypes {
debug {
//
}
release {
//runProguard, sign etc.
}
}
android.productFlavors {
create("free")
{
applicationId = "com.example.app.free"
versionName = "1.0-free"
}
create("full")
{
applicationId = "com.example.app.full"
versionName = "1.0-full"
}
}
}
repositories {
jcenter()
}
dependencies {
compile 'joda-time:joda-time:2.7'
}
task runScript(type: Exec) {
executable "sh"
args "-c", "echo SomeScriptHere"
}
tasks.withType(JavaCompile) {
compileTask -> compileTask.dependsOn runScript
}
task wrapper(type: Wrapper) {
gradleVersion = '2.5'
}
Ideally I want to differentiate by buildType ( not productFlavor ) as the tasks required as based on the type of build not the variety of app produced.
Is it possible to specify that a task should only run on a release or debug build?
Alternatively is it possible to define different arguments to be used for my runScript task based on being a release or debug build?
Apologies if I'm missing something obvious, I'm pretty new to using gradle.
using onlyIf() would be one option gradle docs here but having to define properties seemed awkward especially as a project gets larger and more complicated.
ZXStudio has a good blog post / example here where instead of using properties or rules will iterate over the existing tasks and create a new task based on the buildType / flavor.
So for my original question the answer mean removing the runScript task above and replacing tasks.withType(JavaCompile) as follows;
Could also be extended to match build flavors and create tasks appropriately.
tasks.withType(JavaCompile) {
def newTaskName = "runScript_" + name;
def isDebug = false;
if( name.contains("Debug") )
{
isDebug = true;
}
//Create a new task
tasks.create( newTaskName, Exec ) {
if( isDebug )
{
executable "sh"
args "-c", "echo this is a DEBUG task"
}
else
{
executable "sh"
args "-c", "echo this is a RELEASE task"
}
}
dependsOn newTaskName
}
I found this gradle script built for android studio to allow the use of the NDK until the team can create an official (and more understandable) way of accomplishing this. I don't really understand how it works or how it ties in to a normal gradle script as I am still new to this IDE. Can anybody explain it to me?
The script is:
//////////////
// NDK Support
//////////////
// If using this, Android studio will fail run the following to set the environment
// variable for android studio:
// launchctl setenv ANDROID_NDK_HOME
// /Users/boos_patrick/Development/Android/android-ndk-r8e
// otherwise remove the dependsOn part and run ./gradlew buildNative from the
// command line
task copyNativeLibs(type: Copy, dependsOn: 'buildNative') {
dependsOn 'buildNative'
from(new File('libs')) { include '**/*.so' }
into new File(buildDir, 'native-libs')
}
tasks.withType(Compile) { compileTask -> compileTask.dependsOn copyNativeLibs }
clean.dependsOn 'cleanCopyNativeLibs'
tasks.withType(com.android.build.gradle.tasks.PackageApplication) { pkgTask ->
pkgTask.jniDir new File(buildDir, 'native-libs')
}
task buildNative(type: Exec) {
if (System.env.ANDROID_NDK_HOME != null) {
def ndkBuild = new File(System.env.ANDROID_NDK_HOME, 'ndk-build')
commandLine ndkBuild
} else {
doLast {
println '##################'
println 'Skipping NDK build'
println 'Reason: ANDROID_NDK_HOME not set.'
println '##################'
}
}
}
I'm wondering how to add dependency to specific productFlavor and buildType in gradle.
For example I have productFlavor free and build type release, how can I add a dependency on the assembleFreeRelease task?
I've tried many variants but neither works.
For example I tried:
task('release', dependsOn: assembleProductionRelease) {
}
// error: Could not find property 'assembleProductionRelease' on root project 'app'.
Or:
task('release', dependsOn: 'assembleProductionRelease') {
}
Here there is no error but the task is executed for every flavor and build type, very confusing.
There is built-in support for flavor and buildType dependencies.
dependencies {
flavor1Compile "..."
freeReleaseCompile "..."
}
http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Sourcesets-and-Dependencies
These task are generated dynamically based on your Android plugin configuration. At the time of configuration they are not available to you yet. You can defer the creation of your task in two ways:
Wait until the project is evaluated.
afterEvaluate {
task yourTask(dependsOn: assembleFreeRelease) {
println "Your task"
}
}
Lazily declaring the task dependency as String.
task yourTask(dependsOn: 'assembleFreeRelease') {
println "Your task"
}
Looks like now in version 1 of the android gradle plugin and gradle 2.2+, you can do this with a configuration:
configurations {
freeReleaseCompile
}
android {
...
productFlavors {
free {
...
}
}
}
dependencies {
freeReleaseCompile('myLib#aar')
}
Reference: https://groups.google.com/forum/#!msg/adt-dev/E2H_rNyO6-o/h-zFJso-ncoJ
Muschko's answer didn't work for me, so this is my solution, written and posted by me here
Define the task that should only be executed on a specific buildType/variant/flavor
task doSomethingOnWhenBuildProductionRelease << {
//code
}
It's important to use the "<<" syntax or else the task will automatically be called every time.
Dynamically set the dependency when the tasks are added by gradle
tasks.whenTaskAdded { task ->
if (task.name == 'assembleProductionRelease') {
task.dependsOn doSomethingOnWhenBuildProductionRelease
}
}
android {
ext.addDependency = {
task, flavor, dependency ->
def taskName = task.name.toLowerCase(Locale.US)
if (taskName.indexOf(flavor.toLowerCase(Locale.US)) >= 0) {
task.dependsOn dependency
}
}
productFlavors {
production {
}
other
}
task theProductionTask << {
println('only in production')
}
tasks.withType(JavaCompile) {
compileTask -> addDependency compileTask, "production", theProductionTask
}
}
To be frank, I don't which locale is used to generate names for compile taks so toLowerCase(Locale.US) may be counterproductive.
Here is another way that I used:
tasks.withType(JavaCompile) {
compileTask ->
def dependedTaskName = "dependedTask_";
if(compileTask.name.contains('Release') {
dependedTaskName += "Release";
}
createTask(dependedTaskName, Exec) {
........
}
compileTask.dependsOn ndkBuildTaskName
}
Another way:
tasks.whenTaskAdded { task ->
if (task.name == 'generateReleaseBuildTypeBuildConfig') {
task.dependsOn doSomethingForReleaseBuild
}
}
The 1st method is dynamic while the second one is simpler.
Update: This solution no longer works as of 12/8/2022
I now get the error message: No such property: productFlavors for class: org.gradle.api.internal.provider.DefaultProperty
All the above answers helped me, but I ended up needing to run a script before the compilation of each flavor's debug + release build. The first argument of the script takes the flavor name.
In order to have this trigger early on, but after the flavor specific task has been created, the key is binding the dependsOn to generateMyflavorDebugBuildConfig.
Here's the script I ended up with, which can be placed at the bottom of app/build.gradle
// When a task is active, loop through all app flavors, and see if the
// task.name matches the earliest task we can set up the dependsOn
// loop through all flavors, and create a task that does the work we want to do
// before anything else
android.productFlavors.all { flavor ->
task("${flavor.name}RunCommandBefore", type: Exec) {
workingDir "$projectDir/../.."
commandLine 'sh', 'scripts/run_thing.sh', "${flavor.name}"
}
}
// when tasks created, loop through and as early as we can, bind the
// RunCommandBefore task we created above
tasks.whenTaskAdded { task ->
def taskName = task.name
// loop through all flavors
android.productFlavors.all { flavor ->
def flavorName = flavor.name
// loop through release types so that this happens for debug and release
['debug', 'release'].each { releaseType ->
// generateMyflavorDebugBuildConfig is the earliest task we're able
// to set up the dependsOn to make sure that our script runs
if (taskName.toLowerCase() == "generate${flavorName.toLowerCase()}${releaseType}buildconfig") {
// now myflavorRunCommandBefore will run before
// generateMyflavorDebugBuildConfig
tasks."$taskName".dependsOn "${flavorName}RunCommandBefore"
}
}
}
}
Hope this helps someone! Amazing how difficult Android makes running a simple script first thing..