How to extract plugins from a build.gradle file? - plugins

To simplify my build, I want to extract custom plugins from "build.gradle" and put them into separate gradle files.
Here's the simplest example I can contrive.
1. Defining a plugin inside build.gradle (WORKS)
The following "build.gradle":
apply plugin: GreetingPlugin
class GreetingPlugin implements Plugin<Project> {
void apply(Project project) {
project.task('hello') << {
println "Hello, World"
}
}
}
When you run:
gradle hello
Produces:
:hello
Hello, World
BUILD SUCCESSFUL
2. Extracting the plugin from build.gradle (DOESN'T WORK)
I want to move the plugin definition into another file "hello.gradle":
class GreetingPlugin implements Plugin<Project> {
void apply(Project project) {
project.task('hello') << {
println "Hello, World"
}
}
}
And change the "build.gradle" to be:
apply from: 'hello.gradle'
apply plugin: GreetingPlugin
Now when I run:
gradle hello
It produces:
FAILURE: Build failed with an exception.
* Where:
Build file 'build.gradle' line: 2
* What went wrong:
A problem occurred evaluating root project 'gradle-problem'.
> Could not find property 'GreetingPlugin' on root project 'gradle-problem'.
BUILD FAILED
Total time: 1.723 secs
I'm sure this must be possible, so how do you do it?

I've found two reasonable solutions:
1. Apply the plugin inside the external file
hello.gradle:
apply plugin: GreetingPlugin
class GreetingPlugin implements Plugin<Project> {
void apply(Project project) {
project.task('hello').doLast {
println "Hello, World"
}
}
}
build.gradle:
apply from: 'hello.gradle'
2. Export the plugin class by adding it to an ext property
hello.gradle:
class GreetingPlugin implements Plugin<Project> {
void apply(Project project) {
project.task('hello').doLast {
println "Hello, World"
}
}
}
ext.GreetingPlugin = GreetingPlugin
build.gradle:
apply from: 'hello.gradle'
apply plugin: GreetingPlugin

Related

Is it possible to define sub-project dependencies in main build.gradle file?

In eclipse gradle it is possible to add dependencies to all sub-projects like so:
def dependency_p = new org.gradle.plugins.ide.eclipse.model.ProjectDependency('/dependency-1')
dependency_p.exported = true
eclipse.classpath.file {
whenMerged { classpath ->
classpath.entries << dependency_p
}
}
My question: is it possible to add certain dependencies to certain sub-project from the main build.gradle file?
Something like:
subproject.eclipse.classpath.file {
whenMerged { classpath ->
classpath.entries << dependency_p
}
}

Replacement for ScalaCompile in gradle when switching to Kotlin

I convert a project that was originally written in Scala into kotlin. It is a typical backend - frontend-design with the backend written in Scala and the Frontend in Angular (the code was written by a former co-worker who is no longer working in this project)
During the gradle-build, the e2e-tests are evaluated. For this purpose the backend is compiled in the following way:
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.tasks.scala.ScalaCompile
class ScalaCompilerPlugin implements Plugin<Project> {
void apply(Project project) {
project.configurations {
scalaCompilerPlugin
}
project.afterEvaluate {
project.tasks.withType(ScalaCompile) {
options.encoding = 'UTF-8'
if (scalaCompileOptions.additionalParameters == null) {
scalaCompileOptions.additionalParameters = []
}
scalaCompileOptions.additionalParameters <<
"-Xplugin:" + project.configurations.scalaCompilerPlugin.asPath
}
}
}
}
The 'scalaCompilerPlugin'-plugin is then added to the build.gradle-file in the backend.
plugins {
id 'scala'
id 'com.github.psxpaul.execfork' version '0.1.12'
}
apply plugin: ScalaCompilerPlugin
// ...
Since now the project is converted to Kotlin/Ktor I plan to use something like a KotlinCompiler-plugin for the same purpose, but in gradle 6.0.1, there seems to be no such plugin, and not being that firm with gradle I don't know how to add org.jetbrains.kotlin.gradle.tasks.KotlinCompile.
How can I achieve the same and start the backend during the gradle-build to run the e2e-tests during the test-runs? I am also open to suggestions to change this design.

Gradle plugins in java

I want to write a custom plugin for gradle and move my gradle tasks to it. Now, I am using eclipse to write groovy code for my plugin and creating a jar as an output which is being used by my gradle project. I have been comfortable with writing tasks in android studio for gradle but I am not so comfortable with groovy in eclipse. I am sure there must be a slight difference in syntax but I am not aware. If some one can help. Ex, I have this task :
task example(type: Copy) {
delete('dist/')
from('build/intermediates/bundles/release')
into('dist/')
include('classes.jar')
def jarName = componentName + '-' + versionName + buildNumber + '.jar'
rename('classes.jar', jarName)
}
How to write the task in the Plugin in eclipse.
Here is a simple example of creating a custom plugin that adds a task to the task graph
class MySweetPlugin implements Plugin<Project> {
#Override
void apply(Project project) {
project.getTasks().create("mySweetTask", SomeTask)
}
}
class SomeTask extends DefaultTask {
#TaskAction
void thisIsMyTask() throws Exception {
// do task work
}
}
You task being type Copy might look more like this, depends on what you want to do and how separated you want your code.
class MySweetPlugin implements Plugin<Project> {
#Override
void apply(Project project) {
project.getTasks().create(type: Copy, "copyToLib") {
delete('dist/')
from('build/intermediates/bundles/release')
into('dist/')
include('classes.jar')
def jarName = componentName + '-' + versionName + buildNumber + '.jar'
rename('classes.jar', jarName)
}
}
}

Gradle plugin development error passing arguments

I am trying to create a custom gradle plugin following the example here: http://www.javacodegeeks.com/2012/08/gradle-custom-plugin.html. Everything works fine as long as I dont try to provide arguments to the task, however when I attempt to add arguments, I receive the following error:
Error:(26, 0) Task of type 'com.jwoolston.finalizer.gradle.FinalizerTask_Decorated' has been instantiated directly which is not supported. Tasks can only be created using the DSL.
I've googled it but I don't seem to be getting any results related to my situation (at least not that I understand.
The plugin short id is declared in the generated jar's manifest as: finalizer-plugin.
I have the following files:
FinalizerPlugin.groovy
class FinalizerArgumentExtension {
String path = ''
}
class FinalizerPlugin implements Plugin<Project> {
#Override
void apply(Project project) {
project.extensions.create('finalizeArgs', FinalizerArgumentExtension)
project.task('finalizeTask', type: FinalizerTask)
}
}
FinalizerTask.groovy
class FinalizerTask extends DefaultTask {
#TaskAction
def executeTask() {
println "------------executeTask-------------------"
println "Source Directory : ${project.finalizeArgs.path}"
}
}
Plugin related exerpt of build.gradle of the utilizing project:
apply plugin: 'java'
apply plugin: 'maven'
version = '1.0.0'
repositories {
mavenCentral()
}
dependencies {
testCompile group: 'junit', name: 'junit', version: '4.11'
}
buildscript {
repositories {
maven {
url uri("file://C:\\Users\\ideal\\.m2\\repository")
}
}
dependencies {
classpath group: 'com.jwoolston.finalizer',
name: 'gradle',
version: '1.0.1-SNAPSHOT'
}
}
apply plugin: 'finalizer-plugin'
finalizeArgs {
path = "src/main/java"
}
In short, I don't understand the error. Near as I can tell, everything matches the tutorial. I am trying to simply pass in a string argument to the plugin's task.
Plugin class needs to be fixed as follows:
class FinalizerPlugin implements Plugin<Project> {
#Override
void apply(Project project) { ... }
}
Groovy only supports String interpolation for double-quoted Strings:
println "Source Directory : ${project.finalizeArgs.path}"

Use Gradle Project Extension Properties In Configuration Phase

When writing a custom Gradle plugin, how is it possible to access the extension properties defined in the consuming build.gradle in the custom plugin’s configuration phase?
Please see the following MWE.
build.gradle
apply plugin: 'codechecks'
codechecks {
checkstyleConfig = '/home/user/checkstyle.xml'
}
CodechecksPlugin.groovy
class CodechecksPlugin implements Plugin<Project> {
void apply(Project project) {
project.extensions.create('codechecks', CodechecksPluginExtension)
project.apply( [ plugin: 'checkstyle' ] )
project.checkstyle {
configFile = project.codechecks.checkstyleConfig
}
}
}
CodechecksPluginExtension.groovy
class CodechecksPluginExtension {
def checkstyleConfig = 'config/checkstyle/checkstyle.xml'
}
Wanted behavior: The checkstyle plugin uses the configuration file defined in the build.gradle codechecks extension.
Actual behavior: The default value in the CodechecksPluginExtension is being used because the build.gradle codechecks extension is not yet evaluated.
I already tried putting all uses of the codechecks extension in the plugins into closures but they won’t expand correctly due to class casting issues at execution phase.
Thanks for your help!
project.afterEvaluate works for me.
Try:
project.afterEvaluate {
project.checkstyle {
configFile = project.codechecks.checkstyleConfig
}
}