Can't define task dependencies between multiple projects using gradle - gradle

I need to build 2 projects using Gradle.
I have the 2 gradle files for each project and a parent gradle file.
In the settings.gradle I define the projects:
include 'loadRemote'
include 'load'
rootProject.name = 'EquipLoad'
project(':loadRemote').buildFileName = 'buildRemote.gradle'
project(':load').buildFileName = 'buildLoad.gradle'
Each of the subprojects has their own defined compile and stage tasks.
I need the loadRemote project to run first then the load project.
How to I create this dependency?
I tried adding the dependency to the build.gradle file like this:
tasks.getByPath(":load:cleanCompileStage").dependsOn(":loadRemote:cleanCompileStage")
But the load project compiles first.
I found these syntax:
project(':load') {
dependencies {
compile project (':remoteLoad')
}
}
But need to replace the Gradle compile task with the one that I created in the subproject. I am not sure if it is allowed.
Does anyone have any ideas how to define the dependencies of tasks between 2 subprojects?

You can modify your script like this:
project(':load') {
war.dependsOn project(":loadRemote").tasks.compileJava
}

The above answer did not work for me. I'm sure it is unique to my project. I have to create 2 ear files using 1 code base.
What I did was create a parent gradle file, build.gradle, and add tasks in there that used both projects like this:
//This task builds load and loadRemote ear using 1 command, buildAll
gradle.projectsEvaluated {
task compileAll (dependsOn: [project(':loadRemote').remoteLoadCleanCompileStage]) {
compileAll.finalizedBy project(':load').loadCleanCompileStage
}
task packageAll (dependsOn: [project(':loadRemote').remoteLoadPackage]) {
packageAll.finalizedBy project(':load').loadPackage
}
task buildAll (dependsOn: [compileAll]) {
buildAll.finalizedBy packageAll
}
}

Related

Use build.finalizedBy on each subproject with Gradle kotlin

I want to run a specific task after EVERY build of my subprojects. I can go into each of my subprojects build.gradle.kts file and add the following
tasks.build {
finalizedBy("afterbuildtask")
}
However, this should be possible to do in my root project build.gradle.kts file right? I tried it by doing the following:
subprojects {
this.tasks.findByName("build")?.dependsOn("afterbuildtask")
}
But nothing happens. How can I achieve this?
You can't programatically execute tasks from other tasks in newer versions of Gradle.
Instead, you are supposed to declare task dependencies and Gradle will ensure they get executed in the correct order. But I think it's not what you want
Alternatively, you could move your logic into the doLast block in the build task. eg:
build {
doLast {
println("Copying...")
copy {
from 'source'
into 'target'
include '*.war'
}
println("completed!")
}
}
good coding! ¯_(ツ)_/¯

Gradle- Copy Dependencies of Sub Projects into respective folder of Sub Projects

From root, I am basically trying to fetch the dependencies of each sub project and copy into a directory named dependency within each subproject
I have a root Project and in that build.gradle file i have a task like below:
task copyDependencies(type:Copy) {
nonTestProjects.each {
delete rootProject.project(it).file('dependencies')
from rootProject.project(it).configurations.runtime
intorootProject.project(it).file('dependencies/')
}
}
Inside the Sub Projects build.gradle, i have dependencies as below:
dependencies
{
implementation "com.google.protobuf:protobuf-java:$protobufVersion"
implementation "io.netty:netty:$nettyVersion"
implementation "xmlpull:xmlpull:$xmlPullVersion"
}
On running the task copydependencies from root, i am getting error as below:
Could not get unknown property 'runtime' for configuration container of type org.gradle.api.internal.artifacts.configurations.DefaultConfig
urationContainer.
You get the error Could not get unknown property 'runtime' for configuration container because when gradle configures your root project and tries to create the task copyDependencies, the subprojects have not yet been evaluated, so Gradle doesn't know about "runtime" configuration at this stage ( java plugin has not yet been applied to subprojects).
So one solution would be to wrap this task creation into a gradle.projectsEvaluated lifecycle hook:
gradle.projectsEvaluated {
task copyDependencies(type:Copy) {
// task definition ...
}
}
But then you will have other issues because you want to copy different sources to different destination directories (see How to copy to multiple destinations with Gradle copy task? for possible solution to this issue)
I think a better way would be to create different copyDependencies tasks, one per subproject , and create an "aggregator" task in root project which will depend on these subprojects's tasks:
// aggregator task at root project level
task copyDependencies
// create copydependencies task for each (non-test) subproject
gradle.projectsEvaluated {
nonTestProjects.each {
Project proj = project(it)
Task task = proj.task('copyDependencies', type: Copy) {
from proj.configurations.runtimeClasspath
into proj.file("dependencies")
doFirst {
file('dependencies').deleteDir()
}
}
copyDependencies.dependsOn task
}
}

Gradle: 'dependsOn' to task in other subproject

I have a hierarchical gradle 3.1 project, which looks like this:
root
- build.gradle
- settings.gradle
- server (Java + WAR plugin)
- build.gradle
- client (Node plugin)
- build.gradle
The settings.gradle therefore looks like this:
include ':server', ':client'
What I would like to do now is to bundle the output of the :client:build task in the *.war file produced by the :server:war task. To do so, I need a dependency from :server:war to :client:build in order to ensure that the output files of :client:build are always present when I need to copy them in the :server:war task.
The question is: how does this work?
What I want to achieve here: whenever :server:war is executed, :client:build gets executed first.
Things I tried so far (none of them worked):
// in server/build.gradle
task war {
dependsOn ':client:build'
}
I also tried:
// in server/build.gradle
war.dependsOn = ':client:build'
... and also:
// in server/build.gradle
task war(dependsOn: ':client:build') {
}
None of the attempts above works. Any idea what I am doing wrong?
Please try just:
war.dependsOn ':client:build'
and:
task war {
dependsOn ':client:build'
}
defines a new task called war
and:
war.dependsOn = ':client:build'
theoretically calls this method but the argument has wrong type
and:
task war(dependsOn: ':client:build') {
}
here you define a new task as well.

Execute Gradle task after subprojects are configured

I have a multi-project Gradle build where subprojects are assigned version numbers independent of the root project. I'd like to inject this version number into a few resource files in each subproject. Normally, I'd do this by configuring the processResources task for each subproject in the root build. However, the problem is that Gradle appears to be executing the processResources task before loading the subprojects' build files and is injecting "unspecified" as the version.
Currently, my project looks like this:
/settings.gradle
include 'childA' // ... and many others
/build.gradle
subprojects {
apply plugin: 'java'
apply plugin: 'com.example.exampleplugin'
}
subprojects {
// This has to be configured before processResources
customPlugin {
baseDir = "../common"
}
processResources {
// PROBLEM: version is "unspecified" here
inputs.property "version", project.version
// Inject the version:
from(sourceSets.main.resources.srcDirs) {
include 'res1.txt', 'res2.txt', 'res3.txt'
expand 'version':project.version
}
// ...
}
}
/childA/build.gradle
version = "0.5.424"
I looked into adding evaluationDependsOnChildren() at the beginning of root's build.gradle, but that causes an error because childA/build.gradle runs before customPlugin { ... }. I've tried using dependsOn, mustRunAfter, and other techniques, but none seem have the desired effect. (Perhaps I don't fully understand the lifecycle, but it seems like the root project is configured and executed before the subprojects. Shouldn't it configure root, then configure subprojects, and then execute?)
How can I get inject the version of each subproject into the appropriate resource files without a lot of copy/paste or boilerplate?
You could try using this method, with a hook:
gradle.projectsEvaluated({
// your code
})
I got this figured out for myself. I'm using a init.gradle file to apply something to the rootProject, but I need data from a subproject.
First option was to evaluate each subproject before I modified it:
rootProject {
project.subprojects { sub ->
sub.evaluate()
//Put your code here
But I wasn't sure what side effects forcing the sub project to evaluate would have so I did the following:
allprojects {
afterEvaluate { project ->
//Put your code here
Try doing it like this:
subprojects { project ->
// your code
}
Otherwise project will refer to your root project where no version has been specified.

Gradle - Make existing android project a child of other project and run "gradlew tasks"

Part 1.
I have an existing Android project which is built with gradle.
settings.gradle looks like this:
include ':android', ':androidTest', ':androidTestApp'
build.gradle looks like this:
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.2.3'
}
}
task wrapper(type: Wrapper) {
gradleVersion = '2.4'
}
task customClean(dependsOn: [':android:clean', ':androidTest:clean', ':androidTestApp:clean']) {
}
allprojects {
repositories {
mavenCentral()
mavenLocal()
}
}
What I need to do is a create a project that is a parent of this android project and runs this android project tasks. I add to settings.gradle of new root project only include 'android-sdk:android'which is all I need for now. And everything works fine, I can run tasks of android project like this gradlew androidBuild:
task androidBuild(dependsOn: 'android-sdk:android:assemble') << {
group unitySdkGroupName
}
Problems arise when I run gradlew tasks on the new root projects. I get
Caused by: org.gradle.api.UnknownTaskException: Task with path ':android:clean' not found in project ':android-sdk'.
I know I can fix this by removing colons like this, but I want to somehow make tasks command work without changing android project if possible.
task customClean(dependsOn: ['android:clean', 'androidTest:clean', 'androidTestApp:clean']) {
}
Part 2.
When I add to settings.gradle of root project other nested projects
include 'android-sdk:androidTest'
include 'android-sdk:androidTestApp'
I get errors here in dependencies sections of child projects that are dependent on android module (this is androidTest module):
dependencies {
compile project(path: ":android")
compile 'com.google.android.gms:play-services:7.3.0'
}
and getting this when I refresh projects (again seems like relative paths issue):
Error:(30, 0) Project with path ':android' could not be found in project ':android-sdk:androidTest'.
So the question is - can I make gradlew tasks command work properly without modifying the underlying android project and how can it be done the most elegant way?
Unfortunately: no. Nested multiproject builds are not possible. I should add yet, but although intention to support them has been shown, there is absolutely no indication of when this feature can be expected.
See https://discuss.gradle.org/t/nested-multimodule-builds-with-a-flat-directory-layout/7509/13
I could not even find a feature request at https://discuss.gradle.org/c/bugs

Resources