Gradle: how does one modify a dynamically created task? - gradle

I am building an Android Library project using the Android Gradle plugin (version 0.9.2) and it appears to have a bug (reported) in that while a "provided" dependency is correctly handled (not included) in the generated aar artifact, that dependency is incorrectly included in the generated debug test apk file.
It strikes me that a reasonable workaround is to remove the dependency jar file that is added by the :preDexDebugTest task as the last step for that task. But this task is dynamically generated so getting a handle to it is eluding me at the moment, hence the question.

In your app's build.gradle file, add
afterEvaluate {
def preDexDebugTest = tasks['preDexDebugTest']
// Do something with preDexDebugTest ...
}
That way it should be possible to operate on the preDexDebugTest task.

Related

Setting dependency of a component to mantle-usl - custom Groovy class

I have a custom groovy class inside mantle-usl component. I would like to use the class in other component. Hence, I need to add a dependency so that the new component (or project) has the jar of mantle-usl ready for use.
Is there anyone who can help with this? I attempted to modify the build.gradle file of the project. And add a project dependency, but it returned an error.
project(':runtime/component/warehouse-items-masterenumerator') {
dependencies {
compile project(':runtime/component/mantle-usl')
}
}
As you would expect, this does not work. It seems that I do not have the project references set correctly.
The mantle-usl component doesn't have any compiled code in it so the build.gradle file does not build a jar file, it is only used for running the Spock tests.
I wouldn't recommend adding your own code to mantle-usl, it is easier and cleaner to put it in a separate component. For an example of a build.gradle file that does build a jar file look at the moqui/example component or most of the moqui tool components (such as moqui-elasticsearch).
You also don't need to modify the main build.gradle file from the moqui-framework repository, dependencies should be declared in the build.gradle file in each component (which are picked up automatically in the main build).

How to use Afterburner.fx with Gradle instaed of Maven 3, while leaving the original project structure of afterburner.fx

afterburner.fx for JavaFX 8 is a minimalistic (3 classes) JavaFX MVP framework based on Convention over Configuration and Dependency Injection created by Adam Bien.
afterburner.fx use Maven 3.
I would like to use it with Gradle.
How to use Afterburner.fx with Gradle instaed of Maven 3, while leaving the original project structure of afterburner.fx ?
In the build.gradle File add dependencies
dependencies {
compile group: 'com.airhacks', name:'afterburner.fx', version: afterburnerfxVersion
}
In the build.gradle File add the additional Resources (.fxml , .css , .properties)
sourceSets.main.resources.srcDirs("src/main/java").includes.addAll(["**/*.fxml", "**/*.css", "**/*.properties"])
and (re-)add all the standard Resources (in the resources folder)
sourceSets.main.resources.srcDirs("src/main/resources").includes.addAll(["**/*.*"])
Update for Gradle Version 6.8.1 : if you run gradlew with --warning-mode all there is a deprecated Message:
Copying or archiving duplicate paths with the default duplicates strategy has been deprecated. This is scheduled to be removed in Gradle 7.0.
Solution
add this line:
// from https://docs.gradle.org/6.8.1/userguide/upgrading_version_5.html#implicit_duplicate_strategy_for_copy_or_archive_tasks_has_been_deprecated
// and https://docs.gradle.org/current/userguide/java_plugin.html
// Java Plugin Task processResources(type: Copy)
processResources.duplicatesStrategy = DuplicatesStrategy.INCLUDE // allow duplicates
Thanks, this helped me a lot. I added the short form of it to dependencies:
compile 'com.airhacks:afterburner.fx:1.6.0'
Additionally I added a second line to include the files from the resources folder and not only from /java. I also added **/*.png to include png files because new Image("filename.png") wasn't working anymore.
sourceSets.main.resources.srcDirs("src/main/java").includes.addAll(["**/*.fxml", "**/*.css", "**/*.properties", "**/*.png"])
sourceSets.main.resources.srcDirs("src/main/resources").includes.addAll(["**/*.fxml", "**/*.css", "**/*.properties", "**/*.png"])
I don't know why the above two lines broke the default behavior - seems like I have to add every new file type to the above lines. :/ If anyone has a better solution please tell me.

"Pseudo" subproject without code and just dependencies fails when signing is required because of the missing jar

I'd like to create a subproject that acts as sole anchor for dependencies, ie. it includes no source code. Users can simply depend on the artifact created by the subproject in order to get all the required dependencies. So i've created foo-bar/build.gradle:
dependencies {
compile project(":foo-barz")
compile project(":foo-batz")
}
jar {
enabled = false
}
That seems to work as expected, until signing comes into the build process. I've then get an error message
:foo-bar:signArchives FAILED
What went wrong: Execution failed for task ':foo-bar:signArchives' >
java.io.FileNotFoundException:
/data/flo/code/foo/foo-bar/build/libs/foo-bar-4.0.1.jar (No such file
or directory)
How can I tell the signing plugin that it needs to sign just the pom file for this subproject?
I'd say either do not apply the java plugin, then you also don't need to disable the jar task, or also disable the signArchives task like you disabled the jar task.
I've came up with just creating an empty file with
foo-bar/src/main/java/org/foo/bar/FooBarDummy.java
so that all tasks are happy and an empty jar is created, signed and deployed. Thaks to Peter Niederwieser, Vampire and Daryl Teo for their input. I've found no elegant an easy solution to avoid that Dummy.java workaround.
This question was based on implementing smack-java7

Including a second jar file that's not a dependency into a fat onejar

I have a project that only builds the fat onejar file for testing purposes. Thus, there's a separate testing class that I don't want as a dependency to the main source, but I do want it included into the onejar. Odd scenario, I know.
I'm using the com.smokejumperit.gradle.OneJarPlugin plugin (source here), and clearly it gets the list of files to include in the onejar here:
project.task('oneJar', dependsOn:[project.tasks.jar, project.tasks.typedefOneJar]) {
...
inputs.files([jar.outputs.files, project.configurations.getByName("compile"), project.configurations.getByName("runtime")])
jar.output.files is used for publishing, so I don't want a this second jar file being published, and the two project.configurations would define dependencies for the main source jar, and I don't want this second jar to be a dependency of that either.
This second jar file is built with a task:
task integrationJar(type: Jar) {
from sourceSets.integrationTest.output
classifier = 'integration'
}
... so I can access the resulting FileCollection via integrationJar.outputs.files. If there was a clear way to add that to oneJar.input.files, I'd be golden, but I can't figure out how to do that. I've tried something like this:
oneJar {
dependsOn 'integrationJar'
println integrationJar.outputs.files.getAsPath()
inputs.files.add(integrationJar.outputs.files)
println inputs.files.getAsPath()
}
... but the result for the last print is still missing the integration jar file.
Ideas?
I'm not familiar with the implementation of that plugin, but I'd be surprised if inputs.files determined what gets included. (Usually, inputs is just consumed by Gradle's up-to-date check.) I recommend to try the gradle-one-jar plugin, which appears to be more flexible.

Gradle - can I include task's output in project dependencies

I have a task that generates java sources and a set of jars from these sources (say, project a). I would like to export these jars to dependent projects (say, project b). So here's roughly what I have right now:
//a.gradle
configurations{
generatedJars
}
task generateJars(type: JavaExec) {
//generate jars ...
outputs.files += //append generated jars here
}
dependencies{
generatedJars generateJars.outputs.files
}
//b.gradle
dependencies{
project(path: ':a', configuration: 'generatedJars')
}
It works OK, except that adding generateJars.outputs.files as a dependency does not tell gradle that it has to run generateJars task when there are no jars generated yet. I have tried adding the task itself as a dependency hoping that it would work in the same way as it does when you add a jar/zip task to an artifact configuration (e.g. artifacts{ myJarTask }), but it throws an error telling me that I cannot do that. Of course I can inject the generateJars task somewhere in the build process before :b starts evaluating, but that's clumsy and brittle, so I would like to avoid it.
I feel like I should be adding the generated jars to artifacts{ ... } of the project, but I am not sure how to make them then visible to dependent projects. Is there a better way of achieving this?
Dependent projects (project b) will need to do setup IntelliJ IDEA module classpath to point to project a's generated jars. Something rather like this (pseudo-code):
//b.gradle
idea{
module{
scopes.COMPILE.plus += project(path: ':a', configuration: 'generatedJars').files
}
}
So far I have tried simply adding a project dependecy on :a's generatedJars in :b, but Idea plugin simply adds module :a as a module-dependency and assumes that it exports its generated jars (which is probably a correct assumption), therefore not adding the generated jars to :b's classpath.
Any help would be greatly appreciated!
First, do you need a separate configuration? That is, do you have clients of a that should not see the generated Jars? If not, you can add the generated Jars to the archives configuration, which will simplify things.
Second, the correct way to add the generated Jars to the configuration is (instead of the dependencies block):
artifacts {
generatedJars generateJars
}
This should make sure that the generateJars task gets run automatically when needed.
Third, I'd omit the += after outputs.files, although it might not make a difference. You should also add the necessary inputs.
Fourth, why do you need a JavaExec task to generate the Jars? Can you instead add the generated sources to some source set and let Gradle build them?
Fifth, IDEA doesn't have a concept corresponding to Gradle's project configuration dependencies. Either an IDEA module fully depends on another module, or not at all. You have two options: either use a module dependency and make the generated sources a source folder of the depended-on module (preferably both in the Gradle and the IDEA build), or pass the generated Jars as external dependencies to IDEA. In either case, you should probably add a task dependency from ideaModule to the appropriate generation task. If this still doesn't lead to a satisfactory IDEA setup, you could think about moving the generation of the Jars into a separate subproject.
For my use case, I had a C++ project which generated some native libraries which my java project needed to load in order to run.
In the project ':native' build.gradle:
task compile(type: Exec, group: 'build') {
dependsOn ...
outputs.files(fileTree('/some/build/directory') {
include 'mylib/libmy.so'
})
...
}
In project java application build.gradle:
configurations {
nativeDep
}
// Add dependency on the task that produces the library
dependencies {
nativeDep files(project(':native').tasks.findByPath('compile'))
}
// Unfortunately, we also have to do this because gradle will only
// run the ':native:compile' task if we needed the tasks inputs for another
// task
tasks.withType(JavaCompile) {
dependsOn ':native:compile'
}
run {
doFirst {
// Use the configuration to add our library to java.library.path
def libDirs = files(configurations.nativeDep.files.collect {it.parentFile})
systemProperty "java.library.path", libDirs.asPath
}
}

Resources