Gradle multi project build with applied compile project() dependency for all subprojects - gradle

I have a multi project gradle build and I would like to apply one of the subprojects as dependecy for all other subprojects.
That is, if I specify:
dependencies {
compile project(":my-shared-subproject")
}
in all relevant build.gradle files for each subproject, it works. I if instead do:
subprojects { project ->
dependencies {
if(project.name != 'my-shared-subproject') {
compile project(":my-shared-subproject")
}
}
}
Gradle gets angry and throws the followin error:
A problem occurred evaluating root project 'my-project'.
> Could not find method call() for arguments [:my-shared-subproject] on project ':my-other-subproject' of type org.gradle.api.Project.
Am I wrong in thinking this should be possible? If not - what am I doing wrong? :)

Remove the project parameter from subprojects
subprojects {
dependencies {
if(project.name != 'my-shared-subproject') {
compile project(":my-shared-subproject")
}
}
}

Related

gradle subproject dependencies as list of other subprojects

How can I get list of a subproject dependecies as list of Project object?
subproject.dependencies gives list of DependencyHandler objects. And I can't find how extract Project from DependencyHandler.
After a short have found solution myself :)
subprojects {
configurations.all {
allDependencies.each {
if (it instanceof ProjectDependency) {
println it.dependencyProject
}
}
}
}

Multiple Gradle Files in the same project using apply from

I'm trying to segregate the gradle tasks to respective gradle files.
build.gradle
plugins {
id 'org.openapi.generator' version '4.3.1'
}
apply from: "$projectDir/gradle/script/openapi.gradle"
openapi.gradle
task buildSampleClient(type: org.openapitools.generator.gradle.plugin.tasks.GenerateTask) {
generatorName = "spring"
inputSpec = "$rootDir/src/main/resources/sample.yaml".toString()
outputDir = "$buildDir/generated".toString()
modelPackage = "com.sample"
}
When gradle build is run, getting this error
A problem occurred evaluating script.
Could not get unknown property 'org' for root project 'sample' of type org.gradle.api.Project.
But If I move the content of openapi.gradle into build.gradle it works fine.
Not sure what is the issue, could anyone help here please?
You should add plugin dependencies before your task definition to your openapi.gradle:
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath "org.openapitools:openapi-generator-gradle-plugin:${openapiPluginDependencyVersion}"
}
}
apply plugin: "org.openapi.generator"
// your task goes here
task buildSampleClient(type: org.openapitools.generator.gradle.plugin.tasks.GenerateTask) {
...
}
gradle.properties:
openapiPluginDependencyVersion=4.3.0

Unable to resolve library using Gradle. Resolved using Grape

I'm fairly new to Groovy and I'm trying to wrap my head around Gradle. If I import the org.jvnet.hudson.plugins through Grapes it works perfectly and the dependency is resolved. But if I try to retrieve the dependency using Gradle the dependency is not resolved.
The package org.eclipse.hudson:hudson-core:3.2.1 works with both Gradle and Grape.
A dependency that is not resolved using Gradle
compile 'org.jvnet.hudson.plugins:checkstyle:3.42'
A dependency which is resolved using Grape
#Grab('org.jvnet.hudson.plugins:checkstyle:3.42')
A dependency which is resolved using Gradle
compile 'org.eclipse.hudson:hudson-core:3.2.1'
Error during Gradle build
line 3, column 1.
import hudson.plugins.checkstyle.CheckStyleResultAction;
^
The build.gradle
apply plugin: 'groovy'
repositories {
mavenCentral()
maven {
url "http://repo.jenkins-ci.org/releases/"
}
}
configurations {
ivy
}
sourceSets {
main {
groovy {
srcDirs = ['src/']
}
}
test {
groovy {
srcDirs = ['test/']
}
}
}
dependencies {
compile 'org.codehaus.groovy:groovy-all:2.4.11'
compile "org.apache.ivy:ivy:2.4.0"
ivy "org.apache.ivy:ivy:2.3.0"
// Works
compile 'org.eclipse.hudson:hudson-core:3.2.1'
// Does not work
compile 'org.jvnet.hudson.plugins:checkstyle:3.42'
}
tasks.withType(GroovyCompile) {
groovyClasspath += configurations.ivy
}
You're probably not actually downloading the jar you think you are. Looks like the default artifact that comes back from the org.jvnet.hudson.plugins:checkstyle:3.42 dependency is actually a file named checkstyle-3.42.hpi.
To get the jar which contains the classes instead, use:
compile group: 'org.jvnet.hudson.plugins', name: 'checkstyle', version:'3.42', ext: 'jar'
Then that class will be found on your classpath (and you'll be on to locating the next missing dependency).

How should I add a project dependency to a limited set of subprojects?

I would like to add a certain project dependency to various subproject starting with a specific name.
I tried this
subprojects.findAll { project -> project.name.startsWith("myproject-sample") }.each { project ->
dependencies {
//compile project(":myproject-core")
}
}
but it gives
A problem occurred evaluating root project 'myproject'.
> Could not find method call() for arguments [:myproject-core] on project ':myproject-sample-hello-world'.
When I do this
subprojects {
dependencies {
compile project(":myproject-core")
}
}
it seems to work. But it adds the dep to all subprojects.
How should I add a project dep to a limited set of subprojects?
A clean solution is:
def sampleProjects = subprojects.findAll { it.name.startsWith("sample") }
configure(sampleProjects) {
dependencies {
compile project(":myproject-core")
}
}
Or:
subprojects {
if (project.name.startsWith("sample")) {
dependencies {
compile project(":myproject-core")
}
}
}
Both snippets assume that the sample projects have already had the java plugin applied (otherwise add apply plugin: "java" before the dependencies block).
The subprojects method delegates to an instance of the Project interface for each subproject, which is why your second example works (Project has a method called dependencies()). The each method however is simply passed a Project object as an argument. You then need to call the dependencies() method on that object. This requires a simple syntactical change.
subprojects.findAll { project ->
project.name.startsWith("myproject-sample")
}.each { project ->
project.dependencies {
compile project(":myproject-core")
}
}

Can a Gradle plugin modify the list of subprojects in a multi-module project?

I've hacked together combination of build.gradle and settings.gradle below for creating an ad-hoc multi-module project out of several single-module projects (e.g., an application and all of its dependencies, or a shared library and everything that uses that library).
settings.gradle:
// find all subprojects and include them
rootDir.eachFileRecurse {
if (it.name == "build.gradle") {
def projDir = it.parentFile
if (projDir != rootDir) {
include projDir.name
project(":${projDir.name}").projectDir = projDir
}
}
}
build.gradle::
// Make sure we've parsed subproject dependencies
evaluationDependsOnChildren()
// Map of all projects by artifact group and name
def declarationToProject = subprojects.collectEntries { p -> [toDeclaration(p), p] }
// Replace artifact dependencies with subproject dependencies, if possible
subprojects.each { p ->
def changes = [] // defer so we don't get ConcurrentModificationExceptions
p.configurations.each { c ->
c.dependencies.each { d ->
def sub = declarationToProject[[group:d.group, name:d.name]]
if (sub != null) {
changes.add({
c.dependencies.remove(d)
p.dependencies.add(c.name, sub)
})
}
}
}
for (change in changes) {
change()
}
}
This works, but it's hard to share -- if somebody else wants to do something similar they have to copy my *.gradle files or cut and paste.
What I'd like to do is take this functionality and encapsulate it in a plugin. The build.gradle part looks easy enough to do in the plugin apply() method, but it seems like the list of subprojects is already set in stone before the plugin gets a chance at it. Is there any way to get in earlier in the build process, e.g. by applying to something other than Project? Or should I resign myself to giving my plugin a task for overwriting settings.gradle?
Solution: Per Peter Niederweiser's answer, I moved the code above into two plugins, one to be called from settings.gradle and the other to be called from build.gradle. In settings.gradle:
buildscript {
repositories { /* etc... */ }
dependencies { classpath 'my-group:my-plugin-project:1.0-SNAPSHOT' }
}
apply plugin: 'find-subprojects'
And in build.gradle:
buildscript {
repositories { /* etc... */ }
dependencies { classpath 'my-group:my-plugin-project:1.0-SNAPSHOT' }
}
evaluationDependsOnChildren()
apply plugin: 'local-dependencies'
Note that calling the plugin from settings.gradle doesn't work in Gradle 1.11 or 1.12 but does work in Gradle 2.0.
You'd need to apply a plugin in settings.gradle, which I believe is supported in recent versions.

Resources