gradle use variables in sub project that are defined in child - gradle

Root project build.gradle
subprojects{
task setUpEnvironmentDirs()<<{
file("${distDir}").mkdirs()
// FileTree tree = fileTree(dir:'../../../pngcommon/config-tokens', include:"*.properties")
project.tree.each {File currentFile ->
def fileName = "${currentFile.getName().split("\\.")[0]}"
def destinationFile = "${distDir}/${fileName}/"
file("${destinationFile}").mkdirs()
}
}
}
Sub project build.gradle
copyEnvironmentProperties{
FileTree tree = fileTree(dir:'../../../pngcommon/config-tokens', include:"*.properties")
}
setUpEnvironmentDirs{
FileTree tree = fileTree(dir:'../../../pngcommon/config-tokens', include:"*.properties")
}
The file tree that is commented out in the root project is the variable I am attempting to move to the sub project because the directory path will be different in each sub project. I saw a similar post and set mine up similarly, but I keep getting an error.
gradle use variables in parent task that are defined in child
Error:
What went wrong:
A problem occurred evaluating root project 'services'.
Could not find property 'tree' on project ':service'.

You just need to comment in the code that declares the local variable, and use tree.each instead of project.tree.each. The relative paths will be resolved correctly.

Related

Gradle: Set context root of web application

I have 2 Gradle projects, A is the root, and B is a subproject of A.
Project B generates a .war file, which is included in the .ear file, that project A generates.
I'd like to implement a general solution, where I can change the context root of project B.
Based on my research, I should call the ear.deploymentDescriptors.webModule(path, contextRoot) method, where path is the path of the artifact B in the ear.
How can I get the name of the artifact of B from project A, so that I have something to call the above mentioned method?
Is there a better way to set the context root?
Assume project A has a build.gradle and within ear, the below code can be solve this -
plugins {
id 'ear'
}
dependencies {
deploy project(path:':b', configuration: 'archives')
}
ear{
/* some basis configuration */
libDirName 'APP-INF/lib'
deploymentDescriptor {
/* Some basic attributes */
fileName = "application.xml"
version = "8"
def Set<Project> subProj = project.getSubprojects();
subProj.each{proj ->
if(proj.name.contains("B")){
webModule(proj.name + "-" + proj.version + ".war", "/"+ proj.name)
} //if close
}//each close
}//deploymentDescriptor close
}//ear close

Path to project on which Gradle task is executed

I have parent and child project. Parent's build.gradle is empty, settings.xml contains include 'child' and
in build.gradle of child I have a task
task('executionPath') << {
println projectDir
}
This task is supposed to print the path to project on which the build was started.
If I invoke it in root by ./gradlew executionPath I expect it to show path of the root project, e.g. C:\projects\parent.
If I invoke it in root by ./gradlew child:executionPath I expect it to show path of the child project, e.g. C:\projects\parent\child.
I've tried the following:
projectDir always path to child
new File('.') always path to parent
System.getProperty("user.dir") always path to parent
Answer Gradle: get folder from which "gradle" was executed is not helpful in my case. How can I achieve the above?
It's not very straightforward solution, but you can use start parameters to find out, whether the task was called for the root project or for the current. Something like this:
task('executionPath') << {
//find the argument representing current task
String calledTaskName = null;
for (String taskArgument : project.getGradle().startParameter.taskRequests.get(0).args) {
if (taskArgument.equals(name) || taskArgument.endsWith(':'+name)) {
calledTaskName = taskArgument;
}
}
if (calledTaskName == null) {
println 'Task was not called via arguments'
return;
}
//check, whether task was called on root project or for subproject only
if (calledTaskName.startsWith(project.getPath())) {
println projectDir
} else {
println System.getProperty("user.dir")
}
}
This task is looking within start parameters for the current task name. If it was called via start parameters, it checks, whether task name contains current project name as a prefix and according to it prints out current project path or root project path.
Unfortunately, I don't know any other solution for your case. Sure, you may need to modify it for your exact purposes.

Is it possible to override gradle from prompting error because ("." and "-") in the name of a variable? eg; name.dir (.dir not found) in task

The error message:
* What went wrong:
A problem occurred evaluating root project 'telescope-master'.
> Cannot get property 'dir' on null object
gradle.properties file
classes.dir = WebContent/WEB-INF/classes
webContent.dir = WebContent
template.dir = hdm/template
javascript.dir = hdm/function
javascript4.0.2.dir = hdm/function/4.0.2
datamodel.dir = hdm/datamodel
certificate.dir = certificate
build.gradle file
Properties extFile = new Properties()
extFile.load(new FileInputStream('gradle.properties'))
task FirmwareMatch(type: Zip) {
from ("${extFile.javascript.dir}")
include 'factoryResetOnFirmwareMatch.*'
archiveName 'factoryResetOnFirmwareMatch.zip'
destinationDir file('dist/hdm/function')
}
So basically if I remove the "." from .dir on both files it would work. But is there any way to over ride it?
Also how can I display actual date when using ${TODAY} in gradle.
So your problematic expression is:
extFile.javascript.dir
If we break that into how Groovy will interpret it:
extFile.getProperty('javascript').getProperty('dir')
You want Groovy to interpret it as:
extFile.getProperty('javascript.dir')
Besides directly calling getProperty, here are a couple Groovy options:
extFile.'javascript.dir'
extFile['javascript.dir']
Additionally, assuming your gradle.properties file is either in your project root (generally as a sibling to the build.gradle) or in your GRADLE_HOME directory (i.e. ~/.gradle/gradle.properties) it will be automatically loaded by Gradle and all properties available as project properties.
So you can remove all of your properties parsing code and just do the following:
project.getProperty('javascript.dir')
// or
project.'javascript.dir'
// or
project['javascript.dir']
If you want to protect against those properties not being set, and are on Gradle 2.13 or higher, you can use findProperty instead of getProperty which will return null instead of throwing an exception.

Reading includes from idl file in custom task

I want to make my gradle build inteligent when building my model.
To acquire this I was planning to read schema files, acquire what is included and then build firstly included models (if they are not present).
I'm pretty new to Groovy and Gradle, so please that into account.
What I have:
build.gradle file on root directory, including n subdirectories (subprojects added to settings.gradle). I have only one gradle build file, because I defined tasks like:
subprojects {
task init
task includeDependencies(type: checkDependencies)
task build
task dist
(...)
}
I will return to checkDependencies shortly.
Schema files located externally, which I can see.
Each of them have from 0 to 3 lines of code, that say about dependencies and looks like that:
#include "ModelDir/ModelName.idl"
In my build.gradle I created task that should open, and read those dependencies, preferably return them:
class parsingIDL extends DefaultTask{
String idlFileName="*def file name*"
def regex = ~/#include .*\/(\w*).idl/
#Task Action
def checkDependencies(){
File idlFile= new File(idlFileName)
if(!idlFile.exists()){
logger.error("File not found)
} else {
idlFile.eachLine{ line ->
def dep = []
def matcher = regex.matcher(line)
(...)*
}
}
}
}
What should I have in (...)* to find all dependencies and how should I define, that for example
subprojectA::build.dependsOn([subprojectB::dist, subprojectC::dist])?
All I could find on internet created dep, that outputted given:
[]
[]
[modelName]
[]
[]
(...)

copy tree with gradle and change structure?

Can gradle alter the structure of the tree while copying?
original
mod/a/src
mod/b/src
desired
dest/mod-a/source
dest/mod-b/source
dest/mod-c/source
I'm not sure where I should create a closure and override the copy tree logic
I'd like to do the gradle equivalent of ant's globmapper functionality
<property name="from.dir" location=".."/>
<property name="to.dir" location="dbutil"/>
<copy>
<fileset dir="${from.dir}" ... />
<globmapper from="${from.dir}/*/db" to="${to.dir}"/>
</copy>
Thanks
Peter
When changing file name, rename seems a good approach. When changing path you can override eachFile and modify the destination path.
This works pretty well.
copy {
from("${sourceDir}") {
include 'modules/**/**'
}
into(destDir)
eachFile {details ->
// Top Level Modules
def targetPath = rawPathToModulesPath(details.path)
details.path = targetPath
}
}
....
def rawPathToModulesPath(def path) {
// Standard case modules/name/src -> module-name/src
def modified=path.replaceAll('modules/([^/]+)/.*src/(java/)?(.*)', {"module-${it[1]}/src/${it[3]}"})
return modified
}
Please see sample below. Gradle 4.3 does not have rename/move methods, so we can do renaming on the fly.
What was happened:
Load file tree into the memory. I used zip file from dependencies in my example
Filter items, which are in the target folder
All result items will have the same prefix: if we filter files from directory "A/B/C/", then all files will be like "A/B/C/file.txt" or "A/B/C/D/file.txt". E.g. all of them will start with the same words
In the last statement eachFile we will change final name by cutting the directory prefix (e.g. we will cut "A/B/C").
Important: use type of task "Copy", which has optimizations for incremental compilation. Gradle will not do file copy if all of items below are true:
Input is the same (for my case - all dependencies of scope "nativeDependenciesScope") with previous build
Your function returned the same items with the previous build
Destination folder has the same file hashes, with the previous build
task copyNativeDependencies(type: Copy) {
includeEmptyDirs = false
def subfolderToUse = "win32Subfolder"
def nativePack = configurations.nativeDependenciesScope.singleFile // result - single dependency file
def nativeFiles = zipTree(nativePack).matching { include subfolderToUse + "/*" } // result - filtered file tree
from nativeFiles
into 'build/native_libs'
eachFile {
print(it.path)
// we filtered this folder above, e.g. all files will start from the same folder name
it.path = it.path.replaceFirst("$subfolderToUse/", "")
}
}
// and don't forget to link this task for something mandatory
test.dependsOn(copyNativeDependencies)
run.dependsOn(copyNativeDependencies)
The following works, but is there a more gradle-ish way to do this?
ant.copy(todir: destDir) {
fileset( dir: "${srcDir}/module", includes: '**/src/**')
regexpmapper(from: '^(.*)/src/(.*)$', to: /module-\1\/src\/\2/)
}

Resources