I was searching in the Internet but I have not found answer for my question regarding to build.gradle.kts syntax.
I haven't found any syntax regarding to below application plugin adding:
plugins {
// Apply the Kotlin JVM plugin to add support for Kotlin on the JVM.
id("org.jetbrains.kotlin.jvm") version("1.3.21")
// Apply the application plugin to add support for building a CLI application.
application
//id("kotlin-android")
I mean, what kind of syntax stay behind application?
It only looks like a class member name. Maybe is it a function call? but it has no brackets.
I don't catch this kotlin syntax sugar.
Additional, I have not found plugins (and others blocks) implementation in gradle repository. Someone know where it is located? I am just curious how it works.
If you go to the implementation of application it should bring you to the source:
/**
* The builtin Gradle plugin implemented by [org.gradle.api.plugins.ApplicationPlugin].
*
* Visit the [plugin user guide](https://docs.gradle.org/current/userguide/application_plugin.html) for additional information.
*
* #see org.gradle.api.plugins.ApplicationPlugin
*/
inline val org.gradle.plugin.use.PluginDependenciesSpec.`application`: org.gradle.plugin.use.PluginDependencySpec
get() = id("org.gradle.application")
So application is just an extension function on PluginDependenciesSpec or plugins { }
Related
I am trying to convert build.gradle to kotlin dsl. Using gradle 7.4.1.What the right way to declare custom configuration. For custom configuration like
configurations { grafana }
sourceSets { grafana }
and within dependencies block
grafanaImplementation "org.slf4j:slf4j-simple:1.7.36"
grafanaImplementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
grafanaRuntimeOnly "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
While I am in kotlin-dsl I am doing
val grafana by configurations.creating
val grafanaSourceSet = sourceSets.create("grafana")
and within dependency block
grafana("org.slf4j:slf4j-simple:1.7.36")
grafana("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
When I try to put grafanaImplementation/ grafanaRuntimeOnly within kotlin dsl, it fails.
What is the equivalent of grafanaImplementation/ grafanaRuntimeOnly within kotlin dsl
Quick fix
When you do
val grafanaSourceSet = sourceSets.create("grafana")
behind the scenes Gradle will create the required configurations, grafanaImplementation, grafanaRuntimeOnly, etc, so you can use them without error like this:
val grafanaSourceSet = sourceSets.create("grafana")
dependencies {
"grafanaImplementation"("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
"grafanaRuntimeOnly"("org.slf4j:slf4j-simple:1.7.36")
}
This approach is more like how Groovy works - it basically disables type-checking and the strings will be evaluated during Gradle execution.
Generated DSL accessors
However, string-typing is not why we like Kotlin! We want type-safety and auto completion hints. That's exactly what we see with the implementation() and runtimeOnly(). So how do we get them for grafanaImplementation() and grafanaRuntimeOnly()?
Basically, Gradle will scan the registered config and when it sees that a plugin creates an implementation configuration, it generates Kotlin DSL accessors. However, it can't generate accessors for the build.gradle.kts that contains the definition for the accessors... that's too late. So we need to define the config earlier. We can do that with a buildSrc plugin.
buildSrc Grafana convention plugin
Set up a buildSrc project (this is covered more in the Gradle docs or other StackOverflow answers)
Create a pre-compiled script plugin for Grafana config
// $projectRoot/buildSrc/src/main/kotlin/grafana.convention.gradle.kts
plugins {
// using 'sourceSets' requires the Java plugin, so we must apply it
java
}
val grafanaSourceSet = sourceSets.create("grafana")
Note that this convention plugin is quite opinionated as it applies the Java plugin. In more complex setups you might want to instead react to the Java plugin, rather than always applying it.
Now apply the convention plugin, and Gradle will generate the Kotlin DSL accessors!
// $projectRoot/build.gradle.kts
plugins {
id("grafana.convention")
}
dependencies {
// no string-typing needed!
grafanaImplementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
grafanaRuntimeOnly("org.slf4j:slf4j-simple:1.7.36")
}
In gradle 7.3, I found the following source code:
package org.gradle.util;
import com.google.common.base.Objects;
import com.google.common.collect.Ordering;
import javax.annotation.Nullable;
/**
* This class is only here to maintain binary compatibility with existing plugins.
*
* #deprecated Will be removed in Gradle 8.0.
*/
#Deprecated
public class VersionNumber implements Comparable<VersionNumber> {
...
So is this feature dropped or moved? What's the new way of using VersionNumber related functionality?
That class and many others in the util package were not intended to be used in plugins or anything outside of Gradle's codebase.
In #16745, the Gradle team formally deprecated many of the utility classes and moved/copied them into an internal utility package. Some utility classes have replacements as noted in their respective Javadoc, but some such as VersionNumber have no public replacement provided by Gradle. As such, this should be considered a private API and you should not use it anywhere in your project's build or plugins.
As an alternative, you can use a semver library of your choosing as a replacement.
As can be seen from the top of documentation of class org.gradle.api.tasks.testing.Test, test tasks can be configured using the following piece of code:
test {
// configuration here. For example:
useJUnitPlatform()
}
From usage of method useJUnitPlatform we can assume that method test is called with a Closure which has an instance of aforementioned class Test as delegate.
In Gradle, there are other similar methods which take a Closure. For example, afterEvaluate. Documentation of method afterEvaluate is readily available in documentation of class Project. This is also mentioned in the user guide:
This example uses method Project.afterEvaluate() to add a closure which is executed after the project is evaluated.
Where is the documentation of method test? I could not find it. Or maybe this isn't a method in a class, but inserted via reflection into class Project at runtime or some similar DSL magic?
test in this context is not a method per se, but rather a task named test. To figure out what exactly is going on here requires diving into the internals of Gradle itself which is not part of any public documentation because well, it's not part of the public API.
The only way to figure exactly out what is going on is to debug Gradle during its execution. The easiest way to do that is to generate a plugin project via gradle init. Write a simple Gradle build file such as (build.gradle; I am assuming you are using the Groovy DSL):
plugins {
id("java")
}
test {
useJUnitPlatform()
}
Then write a basic functional test and start debugging. I was curious myself what is going and did just that.
In the following screenshot, you can see the stack trace in the bottom left corner. As you can see, there is a lot of methods called.
There is a mixture of Groovy specific methods and Gradle specific methods. Digging further in, you will come to:
You can see here bottom right that the list of objects is:
Project (root project)
Extra properties
Extensions
Tasks
This aligns with what I mentioned earlier: Gradle will go out of its way to match to what is being asked for. This is also explained in the "A Groovy Build Script Primer" in official documentation (starting from "If the name is unqualified [...]").
Eventually, you will land in some of the public API methods:
getByName is part of NamedDomainObjectContainer which is documented. However, what actually implements that interface is not as you can see from the Javadoc here. The implementation, from debugging, is DefaultTaskContainer.
The rest I will leave to you as an exercise. Hopefully this gives you an idea as to what is going on behind the scenes.
Indeed, test { ... } in this case is not calling a method with name test. This block is a feature of the Gradle API called "Groovy dynamic task configuration block". Per Gradle documentation version 6.1:
// Configure task using Groovy dynamic task configuration block
myCopy {
from 'resources'
into 'target'
}
myCopy.include('**/*.txt', '**/*.xml', '**/*.properties')
This works for any task. Task access is just a shortcut for the tasks.named() (Kotlin) or tasks.getByName() (Groovy) method. It is important to note that blocks used here are for configuring the task and are not evaluated when the task executes.
As such, per this shortcut convention, test { ... } block is used for configuring a task registered in the project – task with name test in this case.
Although nowadays I'd recommend using Gradle's Configuration Avoidance API to configure a task lazily instead of eagerly:
project.tasks.named('test', Test).configure {
it.useJunitPlatform()
}
See getByName replacement in the table "Existing vs New API overview".
I have a Gradle 5.3 build script using Kotlin DSL, similar to this:
plugins {
`kotlin-dsl`
`java-library`
}
group = "my.company"
version = "1.2.3"
Here, version= resolves to org.gradle.api.Project.setVersion.
Now, farther down, I'd like to do this (porting from a Groovy DSL build file):
tasks.named<Jar>("jar") {
manifest {
attributes(
"Product-Version" to version
)
}
}
Here, version resolves to AbstractArchiveTask.getVersion -- not what I want (and also deprecated)!
Figuring I could use Kotlin's qualified this, I tried to use
"${this#Project.version}"
instead (NB: the extra string wrapping gets rid of an additional type error), but I get Unresolved reference: #Project now.
How can I access the project version from within a Kotlin DSL expression?
The Gradle script doesn't seem to be nested inside Project but instead delegates accessors to its relevant properties. In fact, the top-level this is of type Build_gradle.
When those accessors are shadowed, variable project can be used; that is,
project.version
solves the issue at hand. As an alternative,
this#Build_gradle.version
is also valid but less readable.
I'm loading a Maven project as described here. I'm trying to figure out how I can retrieve the source roots so I can figure out the Java classes I have so my Mojo can use them.
I tried a couple of the methods in there, like getResources or getScriptSources without luck. Any idea?
Thanks in advance!
Edit:
I was asked to elaborate a little bit in what I'm attempting to do, so here it is:
The plugin I'm developing will take the sources in the project and create test cases from those. Unless configured, I want to generate tests for all the classes, and for that, I need to somehow figure out where are my sources so I can configure properly.
Hope that helps.
Here's the repository. I planned on publishing it later but I provided source as requested.
Have you read the plugin developers documentation?
That page will link to Plugins Cookbook which links to Mojo Developer Cookbook which has The maven project, or the effective pom. and gives you access to org.apache.maven.project.MavenProject object via
/** #parameter default-value="${project}" */
private org.apache.maven.project.MavenProject mavenProject;
Alternatively via Java 5 annotations
#Component
MavenProject project;
You can call getCompileSourceRoots() to get a list of the directories that will be used for compilation.
You will also need to do more reading about how to setup inclusion/exclusions. You can use other plugins as examples of how to do this, e.g. maven-compiler-plugin
If you want to use annotations, it is very important to make sure your pom is configured as per using annotations and that you use annotations at the class level as well. Mixing javadoc annotations might not work.
I think the simplest solution would be to define a mojo parameter:
/**
* #parameter default-value="${project.build.sourceDirectory}"
* #required
*/
private File sourceDirectory;
or with new annotation based definition:
#Parameter(required = true, defaultValue="${project.build.sourceDirectory}"}
private File sourceDirectory;
which should give your wished result.