How to specify configuration order among Gradle sub-projects? - gradle

settings.gradle is:
rootProject.name = 'snth'
include 'snth-proto-definition'
include 'snth-server'
include 'snth-client-guice'
snth-server/build.gradle has:
sourceSets {
main {
java {
srcDir "${project(':snth-proto-definition').protobuf.generatedFilesBaseDir}/server/java"
}
}
}
snth-client/build.gradle has:
sourceSets {
main {
java {
srcDir "${project(':snth-proto-definition').protobuf.generatedFilesBaseDir}/client/java"
}
}
}
But while snth-server-guice/build.gradle gets processed fine, snth-client-guice/build.gradle errors with:
FAILURE: Build failed with an exception.
* Where:
Build file 'snth/snth-client-guice/build.gradle' line: 14
* What went wrong:
A problem occurred evaluating project ':snth-client-guice'.
> Could not find property 'protobuf' on project ':snth-proto-definition'.
How can I ensure that project(':snth-proto-definition').protobuf is defined before it's used?

Configuration time dependencies indicates use of evaluationDependsOn would allow finer-grained control of the configuration order of sub-modules. For example:
evaluationDependsOn(':snth-proto-definition')

Related

Gradle protobuf task not picking up definitions from dependencies

I have a situation where I have two Gradle subprojects that are basically dumb protobuf containers. One sub project needs to import the definitions from the other, but I can't seem to figure out how to get the protobuf Gradle plugin to work correctly (I'm fairly new to Gradle).
Here's an example.
Directory layout:
build.gradle
settings.gradle
gradle.properties
dependency/
|
- build.gradle
- src/main/proto/dependency.proto
main/
|
- build.gradle
- src/main/proto/main.proto
build.gradle (top level)
plugins {
id "com.google.protobuf" version "0.8.12"
id "java"
}
configure (allprojects) {
apply plugin: 'java'
apply plugin: 'com.google.protobuf'
}
settings.gradle
rootProject.name = 'sample'
include 'main'
include 'dependency'
gradle.properties
group=sample
version=0.1.0
dependency/build.gradle
protobuf {
protoc {
artifact = "com.google.protobuf:protoc:3.11.0"
}
}
dependencies {
compile 'com.google.protobuf:protobuf-java:3.11.4'
compile 'com.google.protobuf:protobuf-java-util:3.11.4'
}
dependency/src/main/proto/dependency.proto
syntax = "proto3";
package dependency;
option java_package = "dependency";
message DependencyRequest {
string foo = 1;
}
message DependencyResponse {
string bar = 1;
}
main/build.gradle
protobuf {
protoc {
artifact = "com.google.protobuf:protoc:3.11.0"
}
plugins {
grpc {
artifact = 'io.grpc:protoc-gen-grpc-java:1.27.2'
}
}
generateProtoTasks {
all()*.plugins {
grpc {}
}
}
}
dependencies {
compile 'com.google.protobuf:protobuf-java:3.11.4'
compile 'com.google.protobuf:protobuf-java-util:3.11.4'
protobuf project(':dependency')
}
main/src/main/proto/main.proto
syntax = "proto3";
package main;
option java_package = "main";
import "dependency/dependency.proto";
service MainService {
rpc CallDependency(DependencyRequest) returns (DependencyResponse) {}
}
When I try to build, I get this error:
$ ./gradlew :main:compileJava
> Task :main:generateProto FAILED
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':main:generateProto'.
> protoc: stdout: . stderr: dependency/dependency.proto: File not found.
main.proto:7:1: Import "dependency/dependency.proto" was not found or had errors.
main.proto:11:24: "DependencyRequest" is not defined.
main.proto:11:52: "DependencyResponse" is not defined.
I read documentation for the plugin and this answer, but I haven't been able to get it to work. Any idea why the protobuf task isn't picking up dependency.proto?
Apparently the protobuf files were getting set up correctly, but there was a mismatch in the package names that cause the main.proto to not be able to find dependency.proto. I was able to get this working by removing the package names in the protobuf definitions.
If anyone runs into this problem in the future, check your package names and imports to make sure they're correct.

Use of Gradle Plugin in external .gradle file

Background:
I'm trying to use the gradle-dependency-graph-generator-plugin in a gradle build, and configure it with custom Generator configurations. When I place the configuration within the _root.gradle, our root gradle project:
buildscript {
repositories {
maven {
url artifactoryRepoURL + '/repo'
}
}
dependencies {
//...
classpath "com.vanniktech:gradle-dependency-graph-generator-plugin:0.5.0"
}
}
//...
allprojects {
//...
apply plugin: "com.vanniktech.dependency.graph.generator"
//...
}
...it works just fine. (Though, Intellij reports errors in the import, it builds and runs both on command line and in the IDE)
The Problem
I'd like to put this code in a separate gradle file, just so it's not cluttering up the root project. So I move the code to a dependencyGraph.gradle file, and include it with an
apply from: "$rootProject.projectDir/dependencyGraph.gradle"
However, I get compilation errors, class not found. So I add the buildScript and dependencies/classpath from the root project file, and try again. This time, it gives a class cast exception:
com.vanniktech.dependency.graph.generator.DependencyGraphGeneratorExtension$Generator cannot be cast to com.vanniktech.dependency.graph.generator.DependencyGraphGeneratorExtension$Generator
Its the same classname, so I assume this is some kind of classloader problem. So, how does one include a build script that references plugin classes into a project.gradle?
EDIT:
Per – #EugenMartynov 's comment, the file looks like:
buildscript {
repositories {
maven {
url artifactoryRepoURL + '/repo'
}
}
dependencies {
classpath "com.vanniktech:gradle-dependency-graph-generator-plugin:0.5.0"
}
}
import com.vanniktech.dependency.graph.generator.DependencyGraphGeneratorPlugin
import com.vanniktech.dependency.graph.generator.DependencyGraphGeneratorExtension.Generator
import guru.nidi.graphviz.attribute.Color
import guru.nidi.graphviz.attribute.Style
import guru.nidi.graphviz.attribute.Label
def updateNode(node, dependency) {
def group = dependency.getModuleGroup()
def colorCodeFor = { starts, color ->
if (group.startsWith(starts)) {
node.add(Style.FILLED, Color.rgb(color))
return color
}
return null
}
def color = colorCodeFor("commons", "#ff008c")
?: colorCodeFor("org.apache", "#ff008c")
?: colorCodeFor("org.springframework", "#6db33f")
?: colorCodeFor("javax", "#ff0000")
?: colorCodeFor("com.fasterxml", "#3a772e")
?: colorCodeFor("ch.qos.logback", "#ffd0a0")
?: colorCodeFor("", String.format("#%06x", Math.abs(group.hashCode()) % (255*255*255))) // base off the group
return node
}
def colorCodedGenerator = new Generator(
"ColorCoded", // Suffix for our Gradle task.
{ dependency -> true }, // filter
{ dependency -> true }, // Include transitive dependencies.
{ node, dependency -> updateNode(node, dependency) }, // Give them some color.
{ node, project ->node.add(Style.FILLED, Color.rgb("#2cc2e4")) }, // project nodes.
)
dependencyGraphGenerator {
generators = [ Generator.ALL, colorCodedGenerator ]
}
and is applied within the allprojects block:
allprojects {
...
apply plugin: "com.vanniktech.dependency.graph.generator"
apply from: "$rootProject.projectDir/dependencyGraph.gradle"
...
}
though I also tried only within the root project. As configured, I get:
FAILURE: Build failed with an exception.
...
* What went wrong:
A problem occurred configuring root project 'dar'.
> com.vanniktech.dependency.graph.generator.DependencyGraphGeneratorExtension$Generator cannot be cast to com.vanniktech.dependency.graph.generator.DependencyGraphGeneratorExtension$Generator
This is gradle 4.9, btw

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

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")
}
}
}

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")
}
}

Custom scala test path in gradle 1.2

I'm new to Gradle and it still seems a little magic to me.
In my project we do not use the default sourceDirs because we separate the different kinds of tests:
configure(subprojects) {
sourceSets {
test {
java.srcDir('src/test/unit/java')
resources.srcDir('src/test/unit/resources')
}
integrationTest {
java.srcDir('src/test/integration/java')
resources.srcDir('src/test/integration/resources')
}
concurrencyTest {
java.srcDir('src/test/concurrency/java')
resources.srcDir('src/test/concurrency/resources')
}
componentTest {
java.srcDir('src/test/component/java')
resources.srcDir('src/test/component/resources')
}
}
}
I'm trying to configure a scala test source directory. My attempt:
apply plugin: 'scala'
configure(subprojects) {
sourceSets {
test {
java.srcDir('src/test/unit/java')
scala.srcDir('src/test/unit/scala')
resources.srcDir('src/test/unit/resources')
}
...
The result:
FAILURE: Build failed with an exception.
* Where:
Build file 'C:\projects\...\build.gradle' line: 109
# note, this is the line "sourceSets {"
* What went wrong:
A problem occurred evaluating root project 'X'.
> Could not find method sourceSets() for arguments [build_5ft63n6d7svimaibmkfq56rbrk$_run_closure4_closure18#573ed6c3] on root project 'X'.
I've tried a few other variants but cannot get it to work. Can someone help please?
The sourceSets extension is added by language plugins like scala, but you didn't apply the scala plugin to the subprojects. Hence the error.
PS: Instead of configure(subprojects) { ... }, you can just use subprojects { ... }.

Resources