how does gradle resolve conflicting dependency versions - gradle

Say I have 3 modules with 3 different build.gradle property files.
Module A v1 has the following entries in build.gradle
ATLAS_VERSION = 1
Module B v1 has the following entries in build.gradle
ATLAS_VERSION = 2
MODULE_A_VERSION = 1
Module C v1 has the following entries in its build.gradle
ATLAS_VERSION = 3
MODULE_B_VERSION = 1
So my question is: what ATLAS version will be resolved during runtime?

According to this Gradle documentation Managing Transitive Dependencies, in case you don't specify any specific constraints for transitive dependencies resolution, the highest version of ATLAS modules should be selected:
When Gradle attempts to resolve a dependency to a module version, all dependency declarations with version, all transitive dependencies and all dependency constraints for that module are taken into consideration. The highest version that matches all conditions is selected.
You can quickly test this behavior with simple multi-project build below:
settings.gradle
rootProject.name = 'demo'
include "A", "B", "C"
build.gradle
subprojects{
apply plugin: "java"
repositories{
mavenCentral()
}
}
project(':A') {
dependencies{
implementation 'commons-io:commons-io:1.2'
}
}
project(':B') {
dependencies{
implementation project(":A")
implementation 'commons-io:commons-io:2.0'
}
}
project(':C') {
dependencies{
implementation project(":B")
implementation 'commons-io:commons-io:2.6'
}
}
You can then check which version of commons-io has been selected, which is 2.6 :
./gradlew C:dependencies
runtimeClasspath - Runtime classpath of source set 'main'.
+--- project :B
| +--- project :A
| | \--- commons-io:commons-io:1.2 -> 2.6
| \--- commons-io:commons-io:2.0 -> 2.6
\--- commons-io:commons-io:2.6

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

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

How to construct test dependency graph with gradle

I work on a large project (several hundred modules, each with tests) and would like to construct a test dependency graph using gradle dependencies.
For example, suppose I have the following modules and dependencies:
core <----- thing1 <----- thing1a
<----- thing2
If I run gradle thing1:dependencies it will tell me that thing1 dependsOn core. Instead, I would like to know what modules depend on thing1 so I can run the tests for thing1 and all dependant modules whenever I change thing1. In the example above, the dependent modules would be thing1 and thing1a
Hopefully there is a simple way to do this in gradle (constructing a test dependency graph seems like a pretty common thing to do), but I have not been able to find anything yet.
Using this gist (which I didn't write) as an inspiration, consider this in the root build.gradle:
subprojects { subproject ->
task dependencyReport {
doLast {
def target = subproject.name
println "-> ${target}"
rootProject.childProjects.each { item ->
def from = item.value
from.configurations
.compile
.dependencies
.matching { it in ProjectDependency }
.each { to ->
if (to.name == target) {
println "-> ${from.name}"
}
}
}
}
}
}
an example run using a project structure as you describe:
$ gradle thing1:dependencyReport
:thing1:dependencyReport
-> thing1
-> thing1a

How to collect jars with sources from projects in dependencies list?

I have a simple multi-project build:
root
|___ a
|___ b
|___ c
build.gradle in root project:
subprojects {
task jarSources(type: Jar, dependsOn: classes) {
classifier = 'source'
from sourceSets.main.java, sourceSets.main.resources
}
}
build.gradle in project a:
dependencies {
compile project(':b')
compile project(':c')
}
task archiveDependencySources(type: Zip) {
...
}
Task archiveDependencySources is intended to collect all jars with sources from projects on which project a depends. Is there a standard way to do this job?
So far I found the solution that looks a bit ugly:
def allJarSourcesTasks = []
for (def dep : configurations.compile.dependencies)
if (dep.hasProperty('dependencyProject'))
allJarSourcesTasks << dep.dependencyProject.tasks['jarSources']
archiveDependencySources.dependsOn allJarSourcesTasks
archiveDependencySources.from allJarSourcesTasks
This might work (not sure about the null argument):
allJarSourcesTasks = configurations.compile.getTaskDependencyFromProjectDependency(true, "jarSources").getDependencies(null)
For dependsOn, .getDependencies(null) could be omitted, but I believe it is needed for from.

Gradle with Eclipse - incomplete .classpath when multiple sourcesets

I have a gradle build script with a handful of source sets that all have various dependencies defined (some common, some not), and I'm trying to use the Eclipse plugin to let Gradle generate .project and .classpath files for Eclipse, but I can't figure out how to get all the dependency entries into .classpath; for some reason, quite few of the external dependencies are actually added to .classpath, and as a result the Eclipse build fails with 1400 errors (building with gradle works fine).
I've defined my source sets like so:
sourceSets {
setOne
setTwo {
compileClasspath += setOne.runtimeClasspath
}
test {
compileClasspath += setOne.runtimeClasspath
compileClasspath += setTwo.runtimeClasspath
}
}
dependencies {
setOne 'external:dependency:1.0'
setTwo 'other:dependency:2.0'
}
Since I'm not using the main source-set, I thought this might have something to do with it, so I added
sourceSets.each { ss ->
sourceSets.main {
compileClasspath += ss.runtimeClasspath
}
}
but that didn't help.
I haven't been able to figure out any common properties of the libraries that are included, or of those that are not, but I can't find anything that I'm sure of (although of course there has to be something). I have a feeling that all included libraries are dependencies of the test source-set, either directly or indirectly, but I haven't been able to verify that more than noting that all of test's dependencies are there.
How do I ensure that the dependencies of all source-sets are put in .classpath?
This was solved in a way that was closely related to a similar question I asked yesterday:
// Create a list of all the configuration names for my source sets
def ssConfigNames = sourceSets.findAll { ss -> ss.name != "main" }.collect { ss -> "${ss.name}Compile".toString() }
// Find configurations matching those of my source sets
configurations.findAll { conf -> "${conf.name}".toString() in ssConfigNames }.each { conf ->
// Add matching configurations to Eclipse classpath
eclipse.classpath {
plusConfigurations += conf
}
}
Update:
I also asked the same question in the Gradle forums, and got an even better solution:
eclipseClasspath.plusConfigurations = configurations.findAll { it.name.endsWith("Runtime") }
It is not as precise, in that it adds other stuff than just the things from my source sets, but it guarantees that it will work. And it's much easier on the eyes =)
I agree with Tomas Lycken, it is better to use second option, but might need small correction:
eclipse.classpath.plusConfigurations = configurations.findAll { it.name.endsWith("Runtime") }
This is what worked for me with Gradle 2.2.1:
eclipse.classpath.plusConfigurations = [configurations.compile]

Resources