include not found copySpec / Sync task Gradle - gradle

I'm trying to sync specific files from a dir with Gradle. But I get a odd error that I can't seem to solve. If there is a better (working) way to filter files while syncing that would also be welcome.
Implementation 1
def updateAbstractsContentSpec = copySpec {
from('../../base') {
includes "../../base/shared/**/*_abstract.*"
}
}
task updateAbstracts(type: Sync) {
group 'build'
with updateAbstractsContentSpec
}
Error 1
Error:(24, 0) Could not find method includes() for arguments [../../base/shared/**/*_abstract.*] on object of type org.gradle.api.internal.file.copy.CopySpecWrapper_Decorated.
Implementation 2 (Preferable)
task updateAbstracts(type: Sync) {
group 'build'
from '../../base'
includes '../../base/shared/**/*_abstract.*'
}
Error 2
Error:(23, 0) Could not find method includes() for arguments [../../base/shared/**/*_abstract.*] on task ':apps:TestApp1:updateAbstracts' of type org.gradle.api.tasks.Sync.
I assume that its clear what I try to do. I hope that somebody can help me with this.

As of Gradle 3.0 CopySpec documentation, CopySpec does not contain includes method.
You should use include instead:
task updateAbstracts(type: Sync) {
group 'build'
from '../../base'
include '../../base/shared/**/*_abstract.*'
}

Related

Passing a gradle task arguments in command line

I'm trying to find the best way to pass a gradle task arguments from the command line.
I have this task. I want to unpack solutions from student exercises and copy them into the right place in the project to evaulate them. I call this task like this:
> gradle swapSolution -Pstudent=MyStudent -Pexercise=ex05
One Problem i have with this while doing this in IntelliJ while having the Gradle plugin enabled is that i get this error message when build the project. What could be a solution to this?
A problem occurred evaluating root project 'kprog-2020-ws'.
> Could not get unknown property 'student' for root project 'kprog-2020-ws' of type org.gradle.api.Project.
This is the gradle task:
task swapSolution(type: Copy) {
new File("${rootDir}/Abgaben").eachDir { file ->
if (file.name.toString().matches("(.*)" + project.property("student") + "(.*)")) {
def exDir = new File("/src/main/java/prog/" + project.property("exercise"))
if (!exDir.exists()) {
delete exDir
}
new File(file.path).eachFile { zipSolution ->
//def zipFile = new File("./Abgaben/" + file.name.toString() + "/" + project.property("exercise") + "Solution.zip")
from zipTree(zipSolution)
into "/src/main/java/"
}
}
}
}
Do you have any suggestions to optimize this process?
-P denotes the Gradle Project Property. If you need to use project properties you can specify it as a system property in gradle.properties file in project root directory.
If your task is of type JavaExec you can use --args switch and pass it in Arguments text field of the Gradle Task Run Configuration togenther with the task name like swapSolution -args="-student=MyStudent -exercise=ex05". See also
https://stackoverflow.com/a/48370451/2000323

How do I specify optional inputs on a Gradle task without an #Optional annotation?

I want to use an optional input if it exists and just move on if it does not exist.
When I run gradle -Dorg.gradle.warning.mode=all I got a deprecation warning for just specifying the input:
A problem was found with the configuration of task ':addWorkingCopyInfo'. Registering invalid inputs and outputs via TaskInputs and TaskOutputs methods has been deprecated and is scheduled to be removed in Gradle 5.0.
- File '/Users/robert/test/special-build-tag' specified for property '$1' does not exist.
This is the task in the build script:
task addWorkingCopyInfo(type: Exec) {
inputs.file file("tagFile") // deprecated if the file does not exist
outputs.file file("generated/taginfo")
executable "perl" args "..."
}
I've seen that I could add an #Optional annotation if I had a custom task class, but that's not the case here.
My best solution was to add a check for the file and only make it an input if it exists. This seems to work.
task addWorkingCopyInfo(type: Exec) {
def tagFile = new File("tagFile");
if (tagFile.exists()) {
inputs.file tagFile
}
outputs.file file("generated/taginfo")
executable "perl" args "..."
}
Is there a better / more Gradle-ish way to do this?
The method inputs.files(...) returns a TaskInputFilePropertyBuilder that provides the methods optional() and optional(boolean).
Just try:
inputs.files('my-file').optional()

What is the proper way to refer to resource directory path in one source set in gradle?

In my build.gradle file, I have defined a separate sourceSet for integration tests:
sourceSets {
integtest {
java.srcDir 'src/integtest/java/io/attil/integration'
resources.srcDir 'src/integtest/resources'
}
}
I would like to use the path to resources of the integration tests in one of my manually defined tasks (a task that prefills the data-base for integration tests; the sql script is located in the mentioned resource folder).
I have now the following solution:
task prefillDatabase {
// ... snip!
String sqlString = new File(sourceSets.integtest.resources.srcDirs.iterator().next().toString() + '/setup_integration_tests.sql').text
// ... snip!
}
While this works, it is quite cumbersome.
Is there a better, shorter way to achieve the same? (I'm looking for something like sourceSets.integtest.resources.srcDir.)
I'm not sure this is less verbose, but I'd argue it's more correct
File file = sourceSets.integtest.resources.matching {
include 'setup_integration_tests.sql'
}.singleFile
String sqlString = file.text
See FileTree.matching(Closure) and FileCollection.getSingleFile()
Also, this looks wrong to me
java.srcDir 'src/integtest/java/io/attil/integration'
I'd think it would be
java.srcDir 'src/integtest/java'
java.include 'io/attil/integration/**'

Calling the same task multiple times in a single build.gradle file

I have a custom Gradle plugin that will generate Java files from a template file. I have several such template files in different locations, and I need to "compile" all of them to generate the Java files I need. Once I have the files, I want to package them into a .jar.
One way I thought I could do this was to call the "compile template" task multiple times from within the same build file. I'd call it once in a task that compiles template files in location A, again from a task that compiles template files from location B... etc., until I have all the Java files I need.
Something like this:
task compileFromLocationA <<{
compileTemplate.execute(A)...
}
task compileFromLocationB
compileTemplate.execute(B)...
...
packageJar(depends: compileFromLocationA, compileFromLocationB, ...)
...
However, you can't programmatically call a task from within another task. I suppose I could break each compileFromLocation_ task into it's own build.gradle file, but that seems like overkill. What's the "best practice" in a case like this?
This code seems to work in build.gradle by using tasks.register() - e.g. to perform multiple source code generating steps - in my case I needed to load different pairs of files (XML schema and generation options) in two different steps:
plugins {
id 'java'
id "com.plugin" version "1.0"
}
sourceSets.main.java.srcDirs += file("${buildDir}/genSrc")
sourceSets.test.java.srcDirs += file("${buildDir}/testGenSrc")
tasks.compileJava {
dependsOn tasks.named("genMessage")
}
genMessage {
codesFile = "${projectDir}/src/main/resources/file.xml"
}
def testGenModel1 = tasks.register("testGenModel1", com.plugin.TestGenModelTask.class) {
schema = "${projectDir}/src/test/resources/file.xsd"
options = "${projectDir}/src/test/resources/file.xml"
}
def testGenModel2 = tasks.register("testGenModel2", com.plugin.TestGenModelTask.class) {
schema = "${projectDir}/src/test/resources/file2.xsd"
options = "${projectDir}/src/test/resources/file2.xml"
}
tasks.compileTestJava {
dependsOn tasks.named("testGenModel1"), tasks.named("testGenModel2")
}

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]
[]
[]
(...)

Resources