How can I get the task associated with an Ant target to execute from within the build.gradle file?
The part in build.gradle which imports the build.xml file:
def targetSdk = android.defaultConfig.targetSdkVersion.getApiLevel()
ant.properties['android.version'] = "android-$targetSdk"
ant.properties['sdk-location'] = SDK_DIR
ant.importBuild(rootDir.absolutePath + "/bcproj/build.xml")
The ant target I want to execute is named compile-android. It successfully runs at the command line with:
./gradlew compile-android
But I'd like to include this in build.gradle so I can specify which ant target needs compiling for each buildType. In all my googling, all I could find references for is getting it to compile at the command line.
Update 1
I've tried adding the compile-android task as a dependency to another task that gets executed along with the build process. Though conceptually the two are really independent of each other. This still failed in getting compile-android to execute.
task copyShopMetadata(type: Exec, dependsOn: 'compile-android') {
workingDir rootDir
commandLine './copy_shop_metadata.sh'
}
copyShopMetadata.execute()
I've tried reversing the dependency, still doesn't work.
Task t = tasks.findByName('compile-android')
t.dependsOn(copyShopMetadata)
copyShopMetadata.execute()
Update 2
I should note that adding the dependency examples above does work when executing from the command line. However my end goal here is to be able to hit "sync project with gradle files" in Android Studio and have the the compile-android ant target compile. Perhaps this just isn't possible?
Assuming your task is not intended to be independent of all other processing, you're going to want your task to be depended on by some other task, which means that when you try to run that other task, your task will be executed first. That task might be "build" for instance, so you might do something like this:
project.build.dependsOn("compile-android")
(I'm not certain of the exact syntax for this.)
Ok, looks like the problem was a misunderstanding on my part for what the "Sync Project with Gradle" button was doing. It is not the equivalent of executing a build from the command line. It's not until I actually hit the run button in Android Studio does it perform the compile-android task. As hitting the run button is what's equivalent to the command line.
Related
Hi, I'm almost new at Gradle in Android.
So.. I'm leanring the Gradle but there are many things that I don't understand.
task clean(type: Delete) {
println "task clean~~"
delete rootProject.buildDir
}
In project A when I input "gradlew" in Android Studio Terminal,
I can see below result.
C:\Users\xxxx\AndroidStudioProjects\ProjectA>gradlew
> Configure project :
task clean~~
(..snip..)
I have questions:
Why is the task clean executed?
Is it default task?
I couldn't find something like below code in the project's gradle file.
defaultTasks 'clean', 'run' .
What is type in task? (I saw type "Copy" too) .
Well task clean is a default task of gradle. It runs every time you start your android studio. To know the working of gradle you should read this gradle documentation which will surely help you in your questions:
Gradle Docs
And for the second point according to gradle documentation:
A Task represents a single atomic piece of work for a build, such as compiling classes or generating javadoc.
So actually it's a task not type, type is a general term and to be specific task type belongs to central types which are used in Gradle scripts. If you go through the documentation you will also find the type:Copy too.
I am attempting to execute a python script from a Gradle task of type Exec. My main build task has a dependency on this task. Let's for this example call my build task assembleProjectDebug. Let's simplify the example also to this:
tasks.create(name: newFooTask, type: Exec) {
commandLine "python", "doSomething.py"
}
tasks[assembleProjectDebug].dependsOn(newFooTask)
If I run ./gradlew assembleProjectDebug from a terminal, my python script executes and all is well in the world. However if I attempt to build from Android Studio with Build -> Make Project, my python script will not execute.
I can confirm as well that my currently selected build variant is set to projectDebug, and can also confirm that when building from Android Studio, :app:assembleProjectDebug appears in the log leading me to believe that assembleProjectDebug task is or will be executed (I could be wrong there).
For the sake of brevity I have also left out where I assign an environment variable in my task which points my $PATH variable to the location of my python exec.
Is there any reason why, outside of me messing up the assignment of a proper $PATH variable for the subprocess, that a command line build will execute this task, yet a build from within Android Studio will not execute this task?
It's likely you'll need to set the workingDir on the Exec task
Eg:
tasks.create(name: newFooTask, type: Exec) {
commandLine "python", "doSomething.py"
workingDir = projectDir
}
I found a solution to my problem. Building from within Android Studio, my task dependency was not being executed as it was when building from the command line. This was due to having Configure on Demand selected in Android Preferences -> Build, Execution, Deployment -> Compiler. Android Studio applies this setting by default. You can read more about Configure on Demand here:
Configure on Demand in Gradle
I want to run a gradle task that fetches additional sources and sets them up before gradle tries to resolve dependencies.
In build.gradle there is a task that fetches a sub project's source code. The task needs to be run before Gradle tries to resolve dependencies, because the sub project is part of the dependencies. The task involves fetching sources from a remote repository and replacing a few build.gradle files to make the build possible.
What happens now is that:
I run the task.
Gradle tries to resolve dependencies before actually running the task.
It fails because one of the dependencies requires the sub project (the sources that my task is supposed to fetch).
Of course, resolving dependencies is part of the "Configuration" build phase, so it's pretty clear why the task is run after. The question is how to make it run before.
Of course I can make it work if I replace my gradle task with a separate bash script and run it manually before gradle does anything. However, that would mean that I duplicate some variables in the gradle and the bash scripts (like version names and git tag names). Those variables are used for other purposes in gradle, and having them in two places is bad. There are other reasons I want to avoid that, one of them being - using a bash script would mean that gradle fails at doing our build from start to finish...
Firstly you are incorrect that resolving dependencies is part of the "Configuration" phase. If you make use of the lazy evaluation of FileCollection then it will actually be resolved in the execution phase. A configuration will be resolved the first time that resolve() is invoked. Please see the javadoc for the methods which cause a Configuration to be resolved. AFAIK the core gradle code won't resolve a configuration in the "Configuration" phase but your custom code may cause this (I suggest you refactor if this is the case)
You can do something like this:
dependencies {
// this is lazy evaluated
compile fileTree(dir: "$buildDir/dynamicJars", include: "*.jar")
}
task getDynamicJars(type: Copy) {
from zipTree('path/to/somefile.zip')
into "$buildDir/dynamicJars"
}
compileJava.dependsOn getDynamicJars
I'm using Android Studio 1.3.2 on Mac.
Gradle version is listed as 2.2.1, Android Plugin version 1.3.1.
I have applied the FindBugs Gradle plugin, and I've created a task that successfully runs the analysis on the directory 'build/intermediates/classes'.
To trigger this task on Gradle Sync, I've added it as a dependency to the preBuild task, like this:
preBuild.dependsOn findBugs
The problem with this dependency is that, at time of preBuild, the generated class files are either non-existent (first sync) or stale (remaining from previous sync). Basically, I want my task to run immediately after the 'build/intermediates/classes' directory is created, or when the files there are refreshed as part of the 'Sync' operation.
Looking at the tasks available, I can see the 'clean' task has the following description:
clean - Deletes the build directory.
However, none of the other tasks I see describe the directory's creation. My first thought was "Well, it's got to be the build task, right?". Unfortunately, as usual, it's not that simple (pressing gradle 'sync' button, does not trigger my task when I've added it as a dependency to the 'build' task). Is no such task available? If so, which task would best suit what I'm trying to achieve?
You can see all tasks using ./gradlew tasks
The build task is the main one. It builds everything, generates APKs and runs all checks.
I recommend you adding the following to the build.gradle file:
check.dependsOn 'findbugs'
So when you run the check task, it will execute findbugs as well.
Then also set a dependency on findBugs for the compilation task:
task findbugs(type: FindBugs, dependsOn: 'compileDebugSources') {...}
This will compile the source in case you run findbugs without previously compiling it.
I've tried to get a gradle task to execute for a lib module 'lib1' in an Android Studio project. It should run with command 'gradlew assembleDebug' or 'gradlew assemble' but it never runs.
task copy(type: Copy, dependsOn: ':lib1:assembleDebug') << {
println "copying"
}
I tried a simpler task with no dependency and it never seems to run either.
task hello << {
println 'hello world'
}
This runs but it's only in the configuration phase.
task hello {
println 'hello world'
}
I need to get a copy to work in the execution phase after the library module assembled. Any clues what to do?
You need to add your task to the task dependency graph somehow. Typically, by making an existing task depend on it. In this case, copy depends on assembleDebug, which simply means, if you run the copy task, assembleDebug must run first. This does not mean that running assembleDebug will cause copy to run. Add this to your build.
assemble.dependsOn copy
Now running gradlew assemble will cause the copy task to execute.
Your second task is correctly defined but again, no other task depends on it so it will only execute if you run it explicitly via gradlew hello or by adding a dependency as mentioned above.
Your third task prints a line during the configuration phase because that closure is evaluated only during that phase. It is the << operator that adds a doLast action which is run at execution time.