How to deal with relative paths in Gradle composite builds? - gradle

I have a Gradle composite build with the following directory structure:
compositebuildroot/
build.gradle
settings.gradle
componentbuild/
build.gradle
settings.gradle
testfile.txt
with compositebuildroot/build.gradle containing
task runComponentBuildSampleTask {
dependsOn gradle.includedBuild('componentbuild').task(':sampleTask')
}
, compositebuildroot/settings.gradle containing
rootProject.name = 'compositebuildroot'
includeBuild 'componentbuild'
, compositebuildroot/componentbuild/build.gradle containing
task sampleTask {
doLast {
println "System.getProperty(\"user.dir\"): " + System.getProperty("user.dir")
println new File("testfile.txt").text
}
}
, and compositebuildroot/componentbuild/settings.gradle containing
rootProject.name = 'componentbuild'
.
When I execute gradle sampleTask from the componentbuild directory, I get the absolute path of the componentbuild directory printed out, followed by the contents of testfile.txt (which is what I want/expect). However, when I execute gradle runComponentBuildSampleTask from the compositebuildroot directory, I get the absolute path of the compositebuildroot directory followed by a java.io.FileNotFoundException for the testfile.txt file.
How can I make gradle runComponentBuildSampleTask from compositebuildroot produce whatever output gradle sampleTask from componentbuild does? Is there some way to tell gradle to run component build tasks as if the current directory is that of the component build's settings.gradle file?

Never use new File(...)
Always use file(...)
See Project.file(Object)

Related

processResources task in gradle doesn't copy a file

While processing resources in a gradle build, is it possible to copy certain special resources to a target directory?
processResources {
println "Project Dir : $projectDir"
copy {
from ('${projectDir}/../../../project-abc/src/main/resources/SkipColumns.properties')
into ('${projectDir}/target/classes/META-INF/project-abc')
}
}
gradle processResources
When I run above command, the build is successful. But it doesn't copy SkipColumns file.
Removing parentheses worked.
copy {
from ("$projectDir/../../../project-abc/src/main/resources/SkipColumns.properties")
into ("$projectDir/target/classes/META-INF/project-abc")
}

Gradle, copy and rename file

I'm trying to in my gradle script, after creating the bootJar for a spring app, copy and rename the jar that was created to a new name (which will be used in a Dockerfile). I'm missing how to rename the file (I don't want to have the version in docker version of the output file).
bootJar {
baseName = 'kcentral-app'
version = version
}
task buildForDocker(type: Copy){
from bootJar
into 'build/libs/docker'
}
You could directly generate the jar with your expected name, instead of renaming it after it has been generated, using archiveName property from bootJar extension:
bootJar {
archiveName "kcentral-app.jar" // <- this overrides the generated jar filename
baseName = 'kcentral-app'
version = version
}
EDIT
If you need to keep the origin jar filename (containing version), then you can update your buildForDocker task definition as follows:
task buildForDocker(type: Copy){
from bootJar
into 'build/libs/docker'
rename { String fileName ->
// a simple way is to remove the "-$version" from the jar filename
// but you can customize the filename replacement rule as you wish.
fileName.replace("-$project.version", "")
}
}
For more information, see Gradle Copy Task DSL
You can also do something like this:
task copyLogConfDebug(type: Copy){
group = 'local'
description = 'copy logging conf at level debug to WEB-INF/classes'
from "www/WEB-INF/conf/log4j2.debug.xml"
into "www/WEB-INF/classes/"
rename ('log4j2.debug.xml','log4j2.xml')

Using a default value between two different build gradle files

I have the following scenario in my Android project:
Project1 --> Build.gradle (1)
Project2--> Build.gradle (2)
Example: Define the following variable:
//first Gradle file
def getProductFlavor() {
//Logic here
Gradle gradle = getGradle()
String requestingTask = gradle.getStartParameter().getTaskRequests().toString()
return requestingTask
}
Instead of defining getCurrentTime() in the second Gradle file,
I call the getCurrentTime() from the first Gradle file.
Maybe my example is wrong and the default value needs to be implementing in another gradle file like the script gradle or somewhere else, but the intent of the example was to clarify what I'm trying to achieve.
The two projects are independents but both belong to the same android project. I want to use ONE def value in both of these gradle files.
I'm a gradle newbie by the way. Never mind if I'm asking this question the wrong way.
Feels like a scenario for external script:
main-project
....| sub-project1
........| src
........| build.gradle
....| sub-project2
........| src
........| build.gradle
....| common.gradle
build.gradle
apply from: '../common.gradle'
def flavor = getProductFlavor()
common.gradle
def getProductFlavor() {
Gradle gradle = getGradle()
String requestingTask = gradle.getStartParameter().getTaskRequests().toString()
return requestingTask
}
ext {
getProductFlavor = this.&getProductFlavor
}

Understanding gradle multi project build.gradle execution order

I'm doing some experiments on below gradle multi project structure
I have added println in all the build.gradle & settings.gradle files to see in what order they execute. I'm seeing that projectA -> build.gradle file is executing after its subproject pA1->build.gradle as seen in the output below
I'm not understanding why projectA->build.gradle is executing after its sub projects ? Should it not execute before its subproject, just like the build.gradle file on root.
location on project Multi project sample
First off, putting a naked println line in your build.gradle files does not give you execution order. The println will be invoked in the configuration phase, so if anything you're looking at the configuration order.
If you want to investigate execution order add a task with the same name to all your build.gradle files, maybe something like this:
task action << {
println("In project: ${project.name}")
}
and then run gradle action from the root folder.

gradle: avoid same custom task in multiple project

I have following folder structure...
project/
project/library
project/app1
project/app2
Now I have build one custom task publish (copy my android apks to a server folder). This task is in /app1/build.gradle and /app2/build.gradle.
My task is in both app same, except I have set project.ext variables. How can I put this task in /build.gradle(in root), because I don't want to change every single build.gradle in every app. The problem is, that /library should not have this task.
Any ideas?
Have a look at this document section: 14.3. Configuring the project using an external build script
UPDATE
Structure
p1
build.gradle - empty file
p2
build.gradle
build.gradle - empty file
settings.gradle
custom.gradle
custom.gradle:
task hello << {
println "hello!"
println project.sample_prop
}
settings.gradle:
include 'p1', 'p2'
p2/build.gradle
apply from: '../custom.gradle'
project.ext.sample_prop = '1'

Resources