I have several unrelated Java projects built with gradle, some of which are assembled into a jar file, others, into a war.
I'd like the assemble task of all projects to depend on the clean task since we've had issues with various old classes getting into assembled jars/wars from the build folder cache. Is there a way of doing that without adding assemble.dependsOn clean to each and every build.gradle?
You can handle this with a global hook in your ./gradle/init.gradle script. Anything you put in there is executed on every build.
In order to avoid failures on projects that don't have an assemble task you need a filter as well, something like the following will work:
allprojects {
tasks.whenTaskAdded { theTask ->
if (theTask.name.equals('assemble')) {
theTask.dependsOn clean
}
}
}
What this is doing is applying a block to all projects defined (allproject). When each task is added this will run, and when a task with the name assemble is added a dependency will be added to clean.
From your top level build.gradle
submodules {
assemble.dependsOn clean
}
This will apply the dependsOn to each subproject
Related
I am used to specifying project dependencies in ant/Netbeans, where a project recompiles if its dependency (another, otherwise separate project) changes, "clean and build" cleans and rebuilds dependencies etc. There is also source code navigation, where Netbeans switches seamlessly between projects.
Now I want to learn Gradle, but I was told that I should use a repository for accessing dependencies, like Maven Central. Project dependency configuration in Netbeans UI, in case of a Gradle project, is gone. Thus the question: is the aforementioned possibility of a deep integration between a project and its dependencies possible in a Gradle project?
For your project's source, meaning the stuff under the typical src/main/java, Gradle will "cache" this out of the box for most built-in tasks.
In Gradle, this is known as Up-to-date checks (AKA Incremental Build):
Once your source files have been compiled, there should be no need to recompile them unless something has changed that affects the output, such as the modification of a source file or the removal of an output file.
If you have a custom build task defined or a task that requires to be incremental (cached), then you'll need to follow this to make your custom task incremental.
And for the following:
"clean and build" cleans and rebuilds dependencies etc.
Gradle does not "build" dependencies. It will retrieve dependencies from the configured repositories in the project and then cache them.
You can configure the build cache if needed to suite your needs: https://docs.gradle.org/current/userguide/build_cache.html#sec:build_cache_configure
I have following structure:
ProjectA -> depends on ProjectB
ProjectB -> depends on ProjectC
compiling projectB everything works:
ProjectB/build.gradle:
dependencies {
compile project(':ProjectC')
}
ProjectB/settings.gradle:
include ':ProjectC'
project(':ProjectC').projectDir = new File(settingsDir, '../ProjectC')
However, compiling ProjectA it says it can not find ProjectC
ProjectA/build.gradle:
dependencies {
compile project(':ProjectB')
}
ProjectA/settings.gradle:
include ':ProjectB'
project(':ProjectB').projectDir = new File(settingsDir, '../ProjectB')
This will show following error:
Where:
Build file ProjectB\build.gradle
What went wrong:
A problem occurred evaluating project ':ProjectB'.
Project with path ':ProjectC' could not be found in project ':ProjectB'.
I Could only make it work including ProjectC in ProjectA. But this is not what I want.
I also tried to exclude on ProjectA but didnt work
ProjectA/build.gradle:
dependencies {
compile (project (':ProjectB')) {
exclude module: ':ProjectC'
}
}
But shows same error.
How can I fix this?
Multi-Project builds are not cascadable. You can have either one or no settings.gradle file in a multi-project build, but not multiple.
Besides that it is not working as expected, it can even get more confusing if you call Gradle from different directories. Gradle looks up (and to the side into directories called master) to find the nearest settings.gradle if none is specified. Then it evaluates the settings.gradle and checks whether the project in which your working directory is, is part of the multi-project build defined in that settings.gradle file. If so, it is executed in the context of the multi-project build, if not, it is executed as standalone build.
This means, if you call Gradle from inside ProjectA, you have a completely different build that probably als is configured differently, than if you call Gradle from inside ProjectB.
If you want to compose multiple multi-project builds into one build, you should instead use GradleBuild tasks or composite builds. In both cases the sub-build is completely independent and can itself be a multi-project build. Which one to use depends on the exact use-case.
With gradle you should be using only a single settings.gradle file. See Multiple settings gradle files for multiple projects building
Also just follow gradle multiproject documentation.
I have a multi project build setup. If I execute the "jar" task of any subproject, gradle checks whether it needs to rebuild a certain dependent project or not by using the org.gradle.api.internal.tasks.execution.SkipUpToDateTaskExecuter.
Is there a way to access this information to like build a custom task or a task in a custom plugin which automatically copies the jars of theses projects to somewhere?
You should be able to use jar.didWork to determine whether the task jar actually did some work or not if I remember correctly: https://docs.gradle.org/current/javadoc/org/gradle/api/Task.html#getDidWork()
Or maybe more appropriate, use something like the following:
gradle.taskGraph.afterTask { task, state ->
// check anything on Task or TaskState, like didWork, executed, failure, noSource, skipMessage, skipped or upToDate
}
I have simple java (Gradle) project wich depends on several JARs, obtained automatically from Maven repositories.
Now I wish to call my jar with external application (Matlab). Unfortunately, application does not see any dependencies after I call build, jar and similar goals.
Me myself also don't know dependencies, since they are managed automatically with Gradle and may contain nested dependencies, not listed in build.gradle.
Is it possible to collect all required JARs in one place to run them freely?
You can write a custom task to collect your runtime dependencies into a jar
task copyToLib(type: Copy) {
into "$buildDir/libs"
from configurations.runtime
}
You could also look into the application and distribution gradle plugins, that provide similar packaging and distribution functionality
I've set up a Gradle task to auto generate one of the subprojects of my Gradle build on which another depends (reason for doing this: long story involving Apache Cordova!). So the root build.gradle contains this autogenerate task that creates a "CordovaLib" sub project. The build.gradle in the other sub project (that isn't autogenerated) depends on CordovaLib:
dependencies {
compile project(':CordovaLib')
}
Is there a way to execute the autogenerate task before the non-generated subproject's build.gradle is evaluated (specifically the above line)? I'm using Gradle 1.11 on JDK 1.7 and as it currently stands I can't even run gradle tasks without it failing due to the missing project.
It isn't possible to execute a task before build files have been evaluated, at least not without complications such as one build executing another build using a GradleBuild task. You are likely better off checking the generated project in to source control, or finding a solution that doesn't involve generating build scripts.
You can use init script to gradle to achieve this.
https://gradle.org/docs/current/userguide/init_scripts.html