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 { ... }.
Related
I am using a gradle project to build a Jenkins shared library. I have a build.gradle with following content:
// Apply the groovy plugin to add support for groovy
apply plugin: 'groovy'
sourceSets {
main {
groovy {
srcDirs = ['src', 'vars']
}
}
test {
groovy {
srcDirs = ['test']
}
}
}
// In this section you declare where to find the dependencies of your project
repositories {
// Use 'jcenter' for resolving your dependencies.
jcenter()
// You can declare any Maven/Ivy/file repository here.
maven {
url "https://repo.jenkins-ci.org/releases/"
}
}
// In this section you declare the dependencies for your production and test code
dependencies {
compile 'org.codehaus.groovy:groovy-all:2.5.6'
compile 'org.apache.ivy:ivy:2.4.0'
testCompile 'junit:junit:4.12'
}
Inside my vars/ directory I have the following source code in it:
def call(Map params) {
2 pipeline {
3 agent none
4
5 stages {
6 stage('Build') {
7 agent { label 'maven'}
8 steps {
9 logError 'Hello world'
10 }
11 }
12 }
13 }
14 }
When I run ./gradlew build or ./gradlew compileGroovy the compilation goes through fine. It looks it is only doing syntax validation and does not care about linking the symbols such as pipeline or agent etc. Am I understanding it correctly?
Okay I think I figured it out. This is happening because groovyc (in this case gradlew compileGroovy is producing a byte code that does not translate high level language to its bytecode equivalent. Instead each line is replaced by a method dispatch. So line 2 in the code above will get replaced with
getMetaClass().invokeMethod(this, 'pipeline', closure)
This causes compile time check on pipeline symbol to be promoted to a runtime error.
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
I want to install some packages locally for all my projects, e.g. dependency-analyse. But I need to actually configure the plugin - also in the init script.
initscript {
repositories {
jcenter()
}
dependencies {
classpath "ca.cutterslade.gradle:gradle-dependency-analyze:1.3.0"
}
}
allprojects {
apply plugin: ca.cutterslade.gradle.analyze.AnalyzeDependenciesPlugin
}
This init script works fine and applies the plugin, but unfortunately, the default setting is that the plugin fails the build. I would like to just log a warning.
For that I need to add configs:
analyzeClassesDependencies {
justWarn = true
}
analyzeTestClassesDependencies {
justWarn = true
}
but when I try to add it in the init.gradle file:
initscript {
repositories {
jcenter()
}
dependencies {
classpath "ca.cutterslade.gradle:gradle-dependency-analyze:1.3.0"
}
}
allprojects {
apply plugin: ca.cutterslade.gradle.analyze.AnalyzeDependenciesPlugin
analyzeClassesDependencies {
justWarn = true
}
analyzeTestClassesDependencies {
justWarn = true
}
}
I get an error:
FAILURE: Build failed with an exception.
* Where:
Initialization script '/Users/<my-user>/.gradle/init.gradle' line: 13
* What went wrong:
Could not find method analyzeClassesDependencies() for arguments [init_2y9p9if69e8553k9fsvzz4a28$_run_closure1$_closure2#3e17c37a] on root project 'my-project' of type org.gradle.api.Project.
Anybody an idea of how I can apply plugin configuration?
I tried the gradle forum but didn't get any answer, so I hope to get some more help here :)
AnalyzeDependenciesPlugin will add different tasks depending on which plugin is applied to your project. For example analyzeClassesDependencies and analyzeTestClassesDependencies will be declared only when java plugin is applied (see how this plugin is implemented here : https://github.com/wfhartford/gradle-dependency-analyze/blob/master/src/main/groovy/ca/cutterslade/gradle/analyze/AnalyzeDependenciesPlugin.groovy )
So you just need to apply java plugin before you apply the AnalyzeDependenciesPlugin in your allprojects configuration closure:
allprojects {
apply plugin: "java" // <= apply Java plugin here
apply plugin: ca.cutterslade.gradle.analyze.AnalyzeDependenciesPlugin
analyzeClassesDependencies {
justWarn = true
}
analyzeTestClassesDependencies {
justWarn = true
}
}
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")
}
}
}
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')