Why my dependency is printed twice? - gradle

I have the following fairly simple build.gradle build script:
repositories {
mavenCentral()
}
configurations { libs }
dependencies {
libs 'org.hibernate:hibernate-core:4.3.5.Final'
}
configurations.libs.files { println it }
When I run it with gradlew build (I'm using Gradle 1.12, latest at the moment) I get the following:
DefaultExternalModuleDependency{group='org.hibernate', name='hibernate-core', version='4.3.5.Final', configuration='default'}
DefaultExternalModuleDependency{group='org.hibernate', name='hibernate-core', version='4.3.5.Final', configuration='default'}
These seem to be the same dependencies, but I don't get it why there are 2 of them when I have added just a single one.
Does anyone know why? Did I do something wrong? Or is there something I don't understand?

The Configuration#files method expects a predicate. (For API details, see Configuration in the Gradle Build Language Reference.) If you instead pass it a closure containing a println statement, (seemingly) strange things will happen. You probably want something like the following instead:
// configurations should only be resolved in
// the execution phase, so let's declare a task
task printLibs {
doLast {
configurations.libs.each { println it }
}
}

Related

Gradle - Protobuf module is rebuilt almost every time

I have a Gradle build with a module generating grpc code. The gradle.build.kts uses version 0.9.1 of the protobuf plugin and the file looks like this:
protobuf {
protoc {
artifact = "com.google.protobuf:protoc:$protobufVersion"
}
plugins {
id("grpc") {
artifact = "io.grpc:protoc-gen-grpc-java:$grpcVersion"
}
id("grpckt") {
artifact = "io.grpc:protoc-gen-grpc-kotlin:$grpcKotlinVersion:jdk8#jar"
}
}
generateProtoTasks {
ofSourceSet("main").forEach { task ->
task.plugins {
id("grpc")
id("grpckt")
}
task.builtins {
id("kotlin")
}
}
}
}
The code generation works well enough, but there is something causing Gradle to re-build that module even though nothing has changed causing the build to be a lot slower then it has to. Running the build with --scan I found this:
The task was not up-to-date because of the following reasons:
Output property 'destDir' file xxx/build/extracted-protos/main has been removed.
Seems like the build is "fighting" over that folder. Is there something wrong with my build configuration?

Configure plugin in separate file using Kotlin DSL

to differenciate diferent plugins configurations, I use separate files.
For example:
./build.gradle.kts
./detekt.gradle.kts
./settings.gradle.kts
./module1
./module2
...
In the root build.gradle.kts I have this:
plugins {
id("io.gitlab.arturbosch.detekt") version DependencyVersion.Detekt
}
buildscript {
dependencies {
classpath(io.gitlab.arturbosch.detekt:detekt-gradle-plugin:1.1.1)
}
}
And to configure it I go to the detekt.gradle.kts and put:
apply(plugin = "io.gitlab.arturbosch.detekt")
detekt {
// configure
}
But detekt lambda is not found. Also tried with:
apply(plugin = "io.gitlab.arturbosch.detekt")
configure<io.gitlab.arturbosch.detekt.Detekt> {
// configure
}
But it doesn't find .Detekt.
With JaCoCo I haven't got any problems using the second approach, but it doesn't work with Detekt or SonarQube.
How can I configure plugins in a separate file?
Thanks.
Try something like below. I have declared a plugin "sonarqube" in my main gradle. I then apply the file sonar.gradle.kts towards the end of the build.gradle.kts file.
build.gradle.kts:
plugins {
id("org.sonarqube") version "2.8" apply false
}
...
apply(from="$rootDir/gradle/includes/sonar.gradle.kts")
gradle/includes/sonar.gradle.kts:
apply(plugin="org.sonarqube")
Using a setup like above, I can then run "gradle sonarqube"
I faced a similar issue. Everything that you need to do is to call
configure<io.gitlab.arturbosch.detekt.extensions.DetektExtension> {
// configure
}
More info, you can find here: https://docs.gradle.org/current/userguide/migrating_from_groovy_to_kotlin_dsl.html#configuring-plugins

Is it possible to throw an error if no arguments are provided to Gradle?

My gradle setup accepts arguments during runtime which are checked in a shell script that Gradle Exec task calls. However, in order to reach that point, Gradle deals with dependencies and spends a good amount of time before the end script is executed, which would then throw an error if no arguments are passed.
Build task in gradle looks like below:
task buildAll(type: Exec) {
environment['PROJECT_ROOT'] = "${projectDir}"
workingDir rootProject.projectDir.path
executable rootProject.projectDir.path + "/script.ksh"
if (project.hasProperty('ARGS')) {
args(ARGS.split(','))
}
}
Gradle is called as follows:
./gradlew build -PARGS="-arg1,value1,-arg2,value2,-arg3,-arg4,value4"
I intend to check for -arg2 and if it is not provided, I would like the gradle build to fail with some sort of usage displayed. Is this possible?
You can add an if block at the very beginning of the script:
if (!project.hasProperty('lol')) {
throw new GradleException("'lol' property is required!")
}
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.google.guava:guava:18.0'
}
}
however it will not prevent gradle from resolving the dependencies of the script itself - buildscript block will be evaluated first.

Gradle copy build script dependency to folder

We are building one of our applications with gradle and part of the distribution I want to include an external jar which is not a run time dependency in a config folder. That jar is needed as part of the application install and it contains some custom ant tasks.
Our build script dependency looks like below:
buildscript {
...
dependencies {
classpath 'org.jfrog.buildinfo:build-info-extractor-gradle:3.1.1'
classpath 'my-group:custom-tasks:1.2.3'
}
}
How would I access and copy the custom-task-1.2.3.jar into a certain folder so I can include it in my distribution? Something like below:
task copyCustomTasks {
doLast {
copy {
// This below is a make up to express what I want
from buildscript.dependencies
include 'custom-tasks*.jar'
into "$buildDir/config"
}
}
}
If this is not the gradle way of doing things please let me know what alternatives I have.
Thank you in advance for your help.
UPDATE
I solved my problem in a different way by creating an extra configuration. However I would still be interested to find out how you can access build script dependencies at run time. Thanks again for your inputs.
configurations {
install {
description = "application install classpath"
transitive = true
}
}
...
dependencies {
...
install('my-group:custom-tasks:1.2.3')
...
}
...
task copyInstallDeps {
doLast {
copy {
from configurations.install
into "$buildDir/config"
}
}
}
You're quite close:
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.google.guava:guava:18.0'
}
}
task copyLibs(type: Copy) {
from buildscript.configurations.classpath
into 'lib'
}

Extract specific JARs from dependencies

I am new to gradle but learning quickly. I need to get some specific JARs from logback into a new directory in my release task. The dependencies are resolving OK, but I can't figure out how, in the release task, to extract just logback-core-1.0.6.jar and logback-access-1.0.6.jar into a directory called 'lib/ext'. Here are the relevant excerpts from my build.gradle.
dependencies {
...
compile 'org.slf4j:slf4j-api:1.6.4'
compile 'ch.qos.logback:logback-core:1.0.6'
compile 'ch.qos.logback:logback-classic:1.0.6'
runtime 'ch.qos.logback:logback-access:1.0.6'
...
}
...
task release(type: Tar, dependsOn: war) {
extension = "tar.gz"
classifier = project.classifier
compression = Compression.GZIP
into('lib') {
from configurations.release.files
from configurations.providedCompile.files
}
into('lib/ext') {
// TODO: Right here I want to extract just logback-core-1.0.6.jar and logback-access-1.0.6.jar
}
...
}
How do I iterated over the dependencies to locate those specific files and drop them in the lib/ext directory created by into('lib/ext')?
Configurations are just (lazy) collections. You can iterate over them, filter them, etc. Note that you typically only want to do this in the execution phase of the build, not in the configuration phase. The code below achieves this by using the lazy FileCollection.filter() method. Another approach would have been to pass a closure to the Tar.from() method.
task release(type: Tar, dependsOn: war) {
...
into('lib/ext') {
from findJar('logback-core')
from findJar('logback-access')
}
}
def findJar(prefix) {
configurations.runtime.filter { it.name.startsWith(prefix) }
}
It is worth nothing that the accepted answer filters the Configuration as a FileCollection so within the collection you can only access the attributes of a file. If you want to filter on the dependency itself (on group, name, or version) rather than its filename in the cache then you can use something like:
task copyToLib(type: Copy) {
from findJarsByGroup(configurations.compile, 'org.apache.avro')
into "$buildSrc/lib"
}
def findJarsByGroup(Configuration config, groupName) {
configurations.compile.files { it.group.equals(groupName) }
}
files takes a dependencySpecClosure which is just a filter function on a Dependency, see: https://gradle.org/docs/current/javadoc/org/gradle/api/artifacts/Dependency.html

Resources