apply plugin in gradle - for-loop

I have a quick question on how to formulate my logic to apply custom parameters in my gradle build file.
I want to apply my plugin with the given parameters for each file in a specified directory location.
How might I accomplish this?
UPDATED
build.gradle:
apply plugin: 'quick.plugin'
task applyPluginXMLOne(type: com.nav.QuickFixTask){
quickfixPlugin.dictFile = file("${projectDir}/src/main/resources/custom.xml")
quickfixPlugin.decimal = true
quickfixPlugin.outputDirectory = file("${buildDir}/generated/")
quickfixPlugin.schemaDirectory = file("${projectDir}/src/main/resources/quickfix/generated")
}
task applyPluginXMLTwo(type: com.nav.QuickFixTask){
quickfixPlugin.dictFile = file("${projectDir}/src/main/resources/custom2.xml")
quickfixPlugin.decimal = true
quickfixPlugin.outputDirectory = file("${buildDir}/generated/")
quickfixPlugin.schemaDirectory = file("${projectDir}/src/main/resources/quickfix/codegen")
}
applyPluginXMLTwo.mustRunAfter applyPluginXMLOne
The result when I run $ gradle applyPluginXMLOne applyPluginXMLTwo
:
This is my output dictFile C:\dev\src\main\resources\custom2.xml
This is my output outputDirectory C:\dev\build\generated
This is my output orderedFields false
This is my output decimal true
:applyPluginXMLTwo
This is my output dictFile C:\dev\src\main\resources\custom2.xml
This is my output outputDirectory C:\dev\build\generated
This is my output orderedFields false
This is my output decimal true
BUILD SUCCESSFUL
Total time: 2.299 secs

In order to apply the plugin one after the other I needed to add a `build.finalizedBy(task1,task2) portion as shown below.
build.gradle:
apply plugin: 'quick.plugin'
task applyPluginXMLOne(type: com.nav.QuickFixTask){
quickfixPlugin.dictFile = file("${projectDir}/src/main/resources/custom.xml")
quickfixPlugin.decimal = true
quickfixPlugin.outputDirectory = file("${buildDir}/generated/")
quickfixPlugin.schemaDirectory = file("${projectDir}/src/main/resources/quickfix/generated")
}
task applyPluginXMLOne(type: com.nav.QuickFixTask){
quickfixPlugin.dictFile = file("${projectDir}/src/main/resources/custom2.xml")
quickfixPlugin.decimal = true
quickfixPlugin.outputDirectory = file("${buildDir}/generated/")
quickfixPlugin.schemaDirectory = file("${projectDir}/src/main/resources/quickfix/codegen")
}
build.finalizedBy(applyPluginXMLOne,applyPluginXMLOne)

Related

How to add multiple tasks of the same type in Gradle?

I need to generate FlatBuffers files from *.fbs file before the build.
So i'm using gradle.plugin.io.netifi:gradle-flatbuffers-plugin:1.0.7 to do it for me.
It works as expected for 1 task:
def generatedSourcePathJava = "$buildDir/generated/source/flatbuffers/java"
def generatedSourcePathCpp = "$buildDir/generated/source/flatbuffers/cpp"
...
task createFlatBuffersJava(type: io.netifi.flatbuffers.plugin.tasks.FlatBuffers) {
outputDir = file(generatedSourcePathJava)
language = "kotlin"
}
build.dependsOn createFlatBuffersJava
But if i add the 2nd one (to generate C++ files for JNI):
task createFlatBuffersJava(type: io.netifi.flatbuffers.plugin.tasks.FlatBuffers) {
outputDir = file(generatedSourcePathJava)
language = "kotlin"
}
task createFlatBuffersCpp(type: io.netifi.flatbuffers.plugin.tasks.FlatBuffers) {
outputDir = file(generatedSourcePathCpp)
language = "cpp"
}
assemble.dependsOn createFlatBuffersJava, createFlatBuffersCpp
Gradle build (../gradlew :engine-flatbuffers:clean :engine-flatbuffers:build) fails with the following:
What went wrong:
A problem occurred configuring project ':engine-flatbuffers'.
java.util.ConcurrentModificationException (no error message)
I think the question can be generalized to "How to add multiple tasks of the same type in Gradle?".
PS. "gradle-5.6-all"
That's a known plugin bug/feature reported at https://github.com/gregwhitaker/gradle-flatbuffers-plugin/issues/7.
It works in 1.0.5 but kotlin [argument] is sadly not supported there at that point. java works and it's compatible.

gradle: how to use result of task in configuration phase (plugin ospackage)

I have a gradle script in which I configure a plugin (in my case ospackage but I guess the same would apply to another plugin) using a variable as per:
ospackage {
...
version project.ext.my_version
...
}
This variable is first initialized and then is updated using a task that I call first in my build script:
ext {
...
my_version = "XXX"
...
}
task init{
group 'ho'
description 'get HO Version'
doLast {
...
project.ext.my_version = getParameter("VERSION")
...
}
}
the problem is that the plugin (in my case ospackage) always consider the initial value "XXX" and not the correct one that was set by executing the init task.
I know it has something to do with configuration and execution phase but still I cannot find a workaround to do what I want.
For info, I also tried to create a task like the one below but it also fail as it seems that buildDeb task does not overwrite ospackage version parameter
buildDeb {
doLast {
...
version project.ext.my_version
link('/usr/bin/aa', '/usr/bin/aa.sh')
...
}
}
I also tried to put at the end of my file something like:
ospackage.dependsOn("init")
but the problem is that ospackage is not recognized as a task
Thank you in advance for your help.
It looks to me like the essence of your question revolves around on-demand values. My understanding is that you would like to set a version number during the configuration phase and use that value during the execution phase to set a package version using the ospackage plugin.
The issue is that the ospackage documentation only provides examples (to date) that setup the package constants during the configuration phase. Obviously that won't work because it is the same time you are setting your version (something that must be able to be done in parallel). You have the right idea with doLast. I found that some things from the ospackage cannot go in "doLast" blocks like packageName (if you have more than one of the same package/task type), so I just put the things that require on-demand evaluation in that block (the version, because we need its evaluation delayed until the execution phase).
My solution was to create a variable that holds the function that resolves the version.
def versionForRpm = { -> project.version }
Create a configuration block
configurations.ext {
version = versionForRpm
...
}
This is an example of an on-demand value (aka lazily-evaluated value).
task someRpmBuild(type: Rpm) {
// all package configs that require evaluation during execution phase (lazy)
doLast {
version = configurations.ext.version
requires("someotherpackageinthisbuild", configurations.ext.version(), 0)
}
// all package configs that may be evaluated during the configuration phase
release = configurations.ext.release
packageGroup = configurations.ext.packageGroup
license = configurations.ext.license
packager = configurations.ext.packager
user = configurations.ext.user
distribution = configurations.ext.distribution
vendor = configurations.ext.vendor
url = configurations.ext.url
os = configurations.ext.os
buildHost = configurations.ext.buildHost
epoch = configurations.ext.epoch
arch = configurations.ext.arch
}
Note that configurations.ext.version will be "called" automatically in the execution phase. I needed to explicitly call it when used as an argument in requires, however.
according to the documentation, the task type is Deb:
task fooDeb(type: Deb) {
packageName // Default to project.name
packageDescription // Defaults to project.description
version // Version field, defaults to project.version
arch // Architecture, defaults to "all". E.g. "amd64", "all"
multiArch // Configure multi-arch behavior: NONE (default), SAME, FOREIGN, ALLOWED (see: https://wiki.ubuntu.com/MultiarchSpec )
release // DEB Release
epoch // Epoch, defaults to 0
user // Default user to permission files to
permissionGroup // Default group to permission files to, "group" is used by Gradle for the display of tasks
packageGroup
buildHost
license
packager
distribution
vendor
url
signingKeyId
signingKeyPassphrase
signingKeyRingFile
sourcePackage
provides
uid // Default uid of files
gid // Default gid of files
createDirectoryEntry // [Boolean]
maintainer // Defaults to packager
uploaders // Defaults to packager
priority
summary
conflicts
recommends
suggests
enhances
preDepends
breaks
replaces
}
where:
version Version field, defaults to project.version
might give the RPM plugin a try.
I was able to solve the issue i had, setting the destination for the ospackage copy destination to a calculated value by using
configurations.ext{
mydestdir = ""
rpmVersion = "1"
releaseNumber = "1"
}
task init{
group 'ho'
description 'get HO Version'
doLast {
...
configurations.ext.mydestdir = "/store/tmp/+getSubDir()"
configurations.ext.rpmVersion = "123"
configurations.ext.releaseNumber = "456"
...
}
}
task fooRpm(type: Rpm) {
dependsOn init
...
doLast(){
version = configurations.rpmVersion
release = configurations.releaseNumber
}
from(project.tempDir) {
into configurations.mydestdir
fileMode = 0644
user = "nobody"
permissionGroup = "nobody"
}
}
I think you'll have use type Deb, and make some changes, but this should speed up your build, and you can verify results by adding --scan before and after making these changes.

Antlr4 - generate grammar source for more language in gradle

In my project I have to generate the grammar sources for more than one language (Java, Javascript and Python) using gradle.
I'm using the antlr plugin, so I have the following rows in my build.gradle file:
apply plugin: 'antlr'
generateGrammarSource {
def languageFlag = project.hasProperty('Language') ?project.property('Language') : 'Python2'
arguments = ['-Dlanguage=' + languageFlag]
def pythonOutputDirectory = "python/engine_lib/kpi_attributes"
switch (languageFlag) {
case "Java":
outputDirectory = file("../../../../XSpotterGUI/sviluppo/src/com/xech/xspotter4/grammars/kpiattributes")
arguments += ['-package', 'com.xech.xspotter4.grammars.kpiattributes']
break
case "JavaScript":
outputDirectory = file("../../../../XSpotterGUI/sviluppo/WebContent/xspotter4/js/xech/grammars/kpiattributes")
break
case "Python2":
outputDirectory = file(pythonOutputDirectory)
break
}
description = 'Generates Java sources from Antlr4 grammars.'
maxHeapSize = "64m"
sourceSets.main.antlr.srcDirs = ['.']
includes = ['KpiAttributes.g4']
doLast {
if (languageFlag.equals("Python2")) {
File file = new File("$pythonOutputDirectory/__init__.py")
file.write ""
}
}
}
I omitted the rows regarding repositories, dependencies and so on.
In this way I'm able to call gradle three times:
./gradlew generateGrammarSource -PLanguage=Java
./gradlew generateGrammarSource -PLanguage=Python2
./gradlew generateGrammarSource -PLanguage=JavaScript
But I have not been able to create a task 'generateAllGrammarSources' in order to call gradlew only ONE time and generate all sources

Gradle configure task based on subproject property

I'm trying to configure a Zip task based on one of the property inside sub-projects, but the property is not yet accessible at the time of configuring the task. For instance, I want to exclude all my projects that has toexclude = true from my zip file. So, the build.gradle of the sub-projects that I want to exclude starts with this:
ext.toexclude = true;
...
And my main build.gradle has this task:
task zipContent (type: Zip){
def excludedProjects = allprojects.findAll{Project p -> p.toexclude == true}.collect{it.name}
println excludedProjects
destinationDir = "/some/path"
baseName = "myFile.zip"
exclude excludedProjects
from "/some/other/path"
}
The problem is that excludedProjects is always empty. Indeed, when I am executing the task, I can see []. I believe this is due to the fact that the property that I set in the subproject's build.gradle is not available at the moment the task is configured. As a proof, if I replace the first line of the task by this:
def excludedProjects = allprojects.collect{it.name}
The task prints out all of my project's name, and the zip contains nothing (which means the problem is in the p.toexclude == true).
Also, if I try this:
task zipContent (type: Zip){
def excludedProjects = []
doFirst{
excludedProjects = allprojects.findAll{Project p -> p.toexclude == true}.collect{it.name}
println "IN DOFIRST"
println excludedProjects
}
println "IN TASK CONFIG"
println excludedProjects
destinationDir = "/some/path"
baseName = "myFile.zip"
exclude excludedProjects
from "/some/other/path"
}
The task prints out IN TASK CONFIG followed by an empty array, then IN DOFIRST with the array containing only the subprojects that I set ext.toexclude == true.
So, is there a way to get the properties of the sub-projects at configuration time?
Well, the crucial question is: At which point of the build is all necessary information available?
Since we want to know each project in the build, where the extra property toexclude is set to true and it is possible (and by design) that the property is set via the build script, we need each build script to be evaluated.
Now, we have two options:
By default, subprojects are evaluated after the parent (root) project. To ensure the evaluation of each project, we need to wait for the point of the build, where all projects are evaluated. Gradle provides a listener for that point:
gradle.addListener(new BuildAdapter() {
#Override
void projectsEvaluated(Gradle gradle) {
tasks.getByPath('zipContent').with {
exclude allprojects.findAll { it.toexclude }.collect{ it.name }
}
}
})
Gradle provides the method evaluationDependsOnChildren(), to turn the evaluation order around. It may be possible to use your original approach by calling this method before querying the excluded projects. Since this method only applies on child projects, you may try to call evaluationDependsOn(String) for each project in the build to also apply for 'sibling' projects. Since this solution breaks Gradle default behavior, it may have undesired side effects.
Just define excludedProjects outside the task
def excludedProjects = allprojects.findAll{Project p -> p.toexclude == true}.collect{it.name}
task zipContent (type: Zip){
destinationDir = file("/some/path")
baseName = "myFile.zip"
exclude excludedProjects
from "/some/other/path"
}
You can call evaluationDependsOnChildren() in the root project so that child projects are evaluated before the root
Eg
evaluationDependsOnChildren()
task zipContent (type: Zip) { ... }
Another option is to use an afterEvaluate { ... } closure to delay evaluation
Eg:
afterEvaluate {
task zipContent (type: Zip) { ... }
}

How to call another projects build.gradle file with command line arguments

I went through the following link and successfully implemented a task which calls build.gradle file from another project. i.e. solution provided by #karl worked for me.
But I need something up on that.
Can somebody help me to know how I can pass command line arguments while calling another build.gradle? Command line argument should be the variable which I have generated from my current build.gradle file.
In my case, I am defining a buildNumber and doing something like this:
def buildNumber = '10.0.0.1'
def projectToBuild = 'projectName'
def projectPath = "Path_till_my_Project_Dir"
task executeSubProj << {
def tempTask = tasks.create(name: "execute_$projectToBuild", type: GradleBuild)
// ****** I need to pass buildNumber as command line argument in "$projectPath/$projectToBuild/build.gradle" ******
tempTask.tasks = ['build']
tempTask.buildFile = "$projectPath/$projectToBuild/build.gradle"
tempTask.execute()
}
You should never call execute directly on any gradle object. The fact it's feasible doesn't mean it should be done and it's highly discouraged since you intrude internal gradle's execution graph structure.
What you need is a task of type GradleBuild which has StartParameter field that can be used to carry build options.
So:
task buildP2(type: GradleBuild) {
buildFile = '../p2/build.gradle'
startParameter.projectProperties = [lol: 'lol']
}
Full demo can be found here, navigate to p1 directory and run gradle buildP2.
You should modify your script in the following way:
def buildNumber = '10.0.0.1'
def projectToBuild = 'projectName'
def projectPath = "Path_till_my_Project_Dir"
task executeSubProj(type: GradleBuild) {
buildFile = "$projectPath/$projectToBuild/build.gradle"
tasks = ['build']
startParameter.projectProperties = [buildNumber: '10.0.0.1']
}
In the project that is executed use project.findProperty('buildNumber') to get the required value.

Resources