How to get values provided by Groovy DSL from Kotlin in Gradle - gradle

Suppose following configuration:
build.dependencies.gradle:
ext {
libraries = [:]
}
libraries += [
library : [group: 'com.example', name: 'library', version: '1.1.1']
]
build.gradle.kts:
apply(from = "build.dependencies.gradle")
dependencies {
implementation(libraries["library"]) // does not work
}
Is there a way to get values provided by Groovy script in build.gradle.kts?

It doesn’t work because Kotlin is statically/strongly typed language unlike Groovy. libraries is not defined on any object from Gradle’s API.
You can access it like so:
dependencies {
implementation((project.extra["libraries"] as LinkedHashMap<*, *>)["library"]!!)
}
println(project.extra["libraries"])
project.extra[“libraries”] returns an Object so we need to cast it correctly in order to get the next value. It is also marked as #Nullable so hence the !! operator.
—
A better way to manage dependency versions is to leverage Java Platform plugin.

Related

Lazy evaluation of computed project.version

I'm trying to use the Jgitver Gradle Plugin together with the BuildConfig Gradle Plugin but I'm not getting the version in the generated BuildConfig class. Instead I get Unspecified.
This is because of ordering and so far I wasn't able to get the ordering right. Jgitver doesn't use a task and sets the project version in the afterEvaluate phase, as can be seen here.
The way to go seems to be lazy evaluation as described here. I couldn't figure out how to do this with the Kotlin DSL though.
Code example
plugins {
java
id("de.fuerstenau.buildconfig") version "1.1.8"
id("fr.brouillard.oss.gradle.jgitver") version "0.9.1"
}
configure<BuildConfigExtension> {
afterEvaluate { /* type mismatch for provider { project.version } if I remove this block
version = provider { project.version }
clsName = "BuildConfig" /* The name of the class that contains the build config */
packageName = "com.somegroup"
charset = "UTF-8"
}
}
I also tried another approach val lazyVersion: Provider<String> = providers.provider { () -> project.version } and then use lazyVersion but that doesn't compile: Type mismatch: inferred type is Any! but String was expected.
Another thing I tried is to add afterEvaluate to the configure closure as described in this Jgitver issue, but it doesn't work for me. Probably because the order in which afterEvaluate closures are executed is undefined.
Question
What's the recommended way to get the value of project.version after it was set by Jgitver in afterEvaluate? And what would be the correct syntax?

How to configure gradle rule base model plugin in gradle kotlin DSL?

I'm using play-application plugin, which in turn use gradle rule based model configuration. build.gradle.kts looks like this:
plugins {
`play-application`
}
/* the snippet does not work
model {
components {
play {
platform play: playVersion, scala: scalaVersion, java: javaVersion
injectedRoutesGenerator = true
}
}
}
*/
// this works instead
apply(from = "play_setup.gradle")
val setup: groovy.lang.Closure<Any?> by extra
setup(project, jVersion, scalaVersion, playVersion)
where play_setup.gradle is:
ext.setup = { project, javaVersion, scalaVersion, playVersion ->
model {
components {
play {
platform play: playVersion, scala: scalaVersion, java: javaVersion
injectedRoutesGenerator = true
}
}
}
}
Is there a way to stop using groovy for plugins made with rule based model and configure them directly via kotlin-DSL?
Not according to the limitations listed in the Gradle Kotlin DSL Primer.
The Kotlin DSL will not support the model {} block, which is part of
the discontinued Gradle Software Model. However, you can apply model
rules from scripts — see the model rules sample for more information
The link to the model rules sample is broken in the documentation, but I fixed it above.

Gradle : How to declare transitive dependency

I am beginner in Gradle, using Crashlytics library in my app. My Dependencies.Gradle is declared like following:
ext {
crashlyticsVersion = '2.5.5#aar'
presentationDependencies =
[
crashlytics:"com.crashlytics.sdk.android:crashlytics:${crashlyticsVersion}"
]
}
In my Presentation.Gradle
dependencies {
def presentationDependencies = rootProject.ext.presentationDependencies
compile presentationDependencies.crashlytics
}
According to Crashlytics doc this dependency has to be declared with Transtive = true. Not sure how to do this. My code follows clean architecture and design of gradle files come from there.
You need to use the following:
compile('com.crashlytics.sdk.android:crashlytics:2.5.5#aar') {
transitive = true
}
I don't see a reason why to over-complicate dependency declaration by using extension container and defining variables.

How do I compile against local file in gradle?

For each sub-project in our build, we have a structure like this:
apply from: '../dependencies.gradle'
dependencies {
... omitting other dependencies ...
compile libraries.poi
}
These libraries are defined in dependencies.gradle, which looks like this:
ext.libraries = [
... omitting other libraries ...
poi: [
'poi:poi:3.9.custom.1',
'poi:poi-ooxml:3.9.custom.1',
'poi:poi-ooxml-schemas:3.9.custom.0',
'poi:poi-scratchpad:3.9.custom.0',
],
... omitting other libraries ...
]
A few days ago I wanted to try something against a nightly build of POI. Nightly builds don't go into their repository, so I'm forced to try and get it to work with local files.
Looking in the docs, you're supposed to use files(...) for this, so I tried this:
poi: [
files('/path/to/poi-3.14-beta1/poi-3.14-beta1-20151027.jar'),
files('/path/to/poi-3.14-beta1/poi-3.14-ooxml-20151027.jar'),
files('/path/to/poi-3.14-beta1/poi-3.14-ooxml-schemas-20151027.jar'),
files('/path/to/poi-3.14-beta1/poi-3.14-scratchpad-20151027.jar'),
],
When I run this, I get an error:
* What went wrong:
A problem occurred evaluating root project 'product'.
> Cannot convert the provided notation to an object of type ModuleVersionSelector: file collection.
The following types/formats are supported:
- Instances of ModuleVersionSelector.
- String or CharSequence values, for example 'org.gradle:gradle-core:1.0'.
- Maps, for example [group: 'org.gradle', name:'gradle-core', version: '1.0'].
- Collections or arrays of any other supported format. Nested collections/arrays will be flattened.
So really it seems like files() does not actually work, as it doesn't return one of the things listed here.
What is the correct way to do it? (Assuming it's even possible!)
Edit: More information
Now that I updated to Gradle 2.8, I get a line number pointing at the problem. It points at some custom build code which we put in to work around Gradle sucking at dependency resolution:
resolutionStrategy {
libraries.each {
libraryName, libraryList ->
libraryList.each {
library -> force library // 👈 this line
}
}
failOnVersionConflict()
}
So I take it the problem is that force doesn't support all the same things that other methods support?
My crap workaround for a workaround is to filter out elements of type FileCollection:
resolutionStrategy {
libraries.each { libraryName, libraryList ->
[libraryList].flatten()
.findAll { library ->
!(library instanceof FileCollection)
}
.each { library -> force library }
}
failOnVersionConflict()
}
Maybe there is a better way.

Gradle plugin for XML Beans

I am trying to write a Gradle plugin for XML Beans. I have started with one of the 'Hello from Gradle' plugin examples, and also a plugin published by R. Artavia here. That plugin went straight to jar - I am trying to only generate source. The generated source must then be compiled with other project source and included in a single jar. Other goals include
- full plugin - all I should need is "apply plugin: 'xmlbean'"
- I can configure source/code gen location and some features if I want to
- It detects whether it needs to be rebuilt. (well, eventually!!!)
I am off to a pretty good start, but am blocked defining a new sourceSet. I am getting an error "No such property 'srcDirs'" (or 'srcDir'). It seems there is something I have to define someplace to make a new sourceSet work but I cannot find it. I have tried several different syntaxes (with/without equal sign, brackets, srcDir/srcDirs, etc. - nothing is working...
What do I need to do inside a plugin to make a new sourceSet entry be properly recognized?
Thank you!
JKE
File: xmlbean.gradle (includes greeting plugin for the moment for debugging)
apply plugin: xmlbean
apply plugin: 'java'
xmlbean {
message = 'Hi'
greeter = 'Gradle'
}
class xmlbean implements Plugin<Project> {
void apply(Project project) {
project.extensions.create("xmlbean", xmlbeanExtension)
Task xmlbeanTask = project.task('xmlbean')
xmlbeanTask << {
project.configurations {
xmlbeans
}
project.dependencies {
xmlbeans 'org.apache.xmlbeans:xmlbeans:2.5.0'
}
project.sourceSets {
main {
java {
srcDirs += '$project.buildDir/generated-source/xmlbeans'
}
}
xmlbeans {
srcDirs = ['src/main/xsd']
}
}
ant.taskdef(name: 'xmlbean',
classname: 'org.apache.xmlbeans.impl.tool.XMLBean',
classpath: project.configurations.xmlbeans.asPath)
ant.xmlbean(schema: project.sourceSets.xmlbean.srcDir,
srconly: true,
srcgendir: "$project.buildDir/generated-sources/xmlbeans",
classpath: project.configurations.xmlbeans.asPath)
println "${project.xmlbean.message} from ${project.xmlbean.greeter}"
}
project.compileJava.dependsOn(xmlbeanTask)
}
}
class xmlbeanExtension {
String message
String greeter
}
File: build.gradle
apply from: '../gradle/xmlbeans.gradle'
dependencies {
compile "xalan:xalan:$ver_xalan",
":viz-common:0.0.1",
":uform-repository:0.1.0"
}
Console: Error message:
:idk:xmlbean FAILED
FAILURE: Build failed with an exception.
* Where:
Script 'C:\jdev\cpc-maven\try.g2\comotion\gradle\xmlbeans.gradle' line: 32
* What went wrong:
Execution failed for task ':idk:xmlbean'.
> No such property: srcDirs for class: org.gradle.api.internal.tasks.DefaultSourceSet_Decorated
...
BUILD FAILED
Gradle info: version 2.5 / groovy 2.3.10 / JVM 7u55 on Windows 7 AMD64
You should try to become familiar with the Gradle DSL reference guide, because it's a huge help in situations like this. For example, if you click on the sourceSets { } link in the left navigation bar, you're taken to this section on source sets.
From there, you'll discover that the sourceSets {} block is backed by a class, SourceSetContainer. The next level of configuration nested inside is backed by a SourceSet object, and then within that you have one or more SourceDirectorySet configurations. When you follow the link to SourceDirectorySet, you'll see that there are getSrcDirs() and setSrcDirs() methods.
So how does this help? If you look closely at the exception, you'll see that Gradle is saying it can't find a srcDirs property on DefaultSourceSet_Decorated, which you can hopefully infer is an instance of SourceSet. That interface does not have an srcDirs property. That's because your xmlbeans {} block is configuring a SourceSet, not a SourceDirectorySet. You need to add another nested configuration to gain access to srcDirs.
At this point, I'm wondering whether a new source set is the appropriate solution. Unfortunately it's not clear to me exactly what the plugin should be doing, so I can't offer any alternatives at this point.

Resources