Override plugin convention property with project property - gradle

I am trying to understand how to set a plugin convention property from a project property.
Here is the customPluginWithConvention example from the gradle distribution (gradle-0.9.2\samples\userguide\organizeBuildLogic\customPluginWithConvention\build.gradle)
apply plugin: GreetingPlugin
greeting = 'Hi from Gradle'
class GreetingPlugin implements Plugin<Project> {
def void apply(Project project) {
project.convention.plugins.greet = new GreetingPluginConvention()
project.task('hello') << {
println project.convention.plugins.greet.greeting
}
}
}
class GreetingPluginConvention {
def String greeting = 'Hello from GreetingPlugin'
}
Running this script with no project property:
>gradle hello
:hello
Hi from Gradle
BUILD SUCCESSFUL
And now trying to set a custom message via setting a project property:
>gradle -Pgreeting=goodbye hello
:hello
Hello from GreetingPlugin
Instead of the expected "goodbye" the default greeting of the convention is shown. Is it possible to override the message?

Is it possible to override the message?
Not yet, but we should try to make it possible. Please create an issue at http://jira.codehaus.org/browse/GRADLE.

Related

How to execute method in class using Gradle task?

I want to execute Hello method in class using gradle task(at springboot). The sample is like below.
class MyClass
{
public void Hello()
{
System.out.println("Hello World");
}
}
Is there any way to execute Hello function in gradle task?
I had added below and tried but below task cannot parse MyClass token.
task myTest{
doLast {
println "Executing MyClass method"
def v = new MyClass();
v.Hello();
}
}

Gradle error: Could not find method jar() for arguments

I'm writing a custom plugin which adds some data to manifest of Java project.
It looks something like this:
package com.example.gradle
import org.gradle.api.Plugin
import org.gradle.api.Project
public class ExamplePlugin implements Plugin<Project> {
def apply(Project project) {
project.jar() {
manifest {
attributes 'buildServer': checkIfIsBuildServer()
attributes 'personalBuild': checkIfIsPersonalBuild()
}
}
}
def checkIfIsBuildServer() {
return 'some result'
}
def checkIfIsPersonalBuild() {
return 'some result'
}
}
When I'm trying to apply it to some project, I get an error:
Could not find method jar() for arguments [com.example.gradle.ExamplePlugin$_apply_closure1#411e4f5e] on project ':SomeProject' of type org.gradle.api.Project.
I am reasonably sure this is some missing import. I don't have any idea how to determine what import it should be.
jar() isn’t a method on Project.
If I’m understanding your code correctly, what you are trying to do is configure the jar task that is created from the Java Plugin.
So you need to:
Get the task
Configure the task
Something like:
import org.gradle.api.plugins.JavaPlugin
import org.gradle.api.tasks.bundling.Jar
public class ExamplePlugin implements Plugin<Project> {
def apply(Project project) {
project.afterEvaluate {
project.tasks.named(JavaPlugin.JAR_TASK_NAME, Jar) {
it.manifest {
attributes 'buildServer': checkIfIsBuildServer()
attributes 'personalBuild': checkIfIsPersonalBuild()
}
}
}
}
def checkIfIsBuildServer() {
'some result'
}
def checkIfIsPersonalBuild() {
'some result'
}
}
I highly recommend switch to Kotlin or Java for your plugin. It will make errors like this trivial to resolve and you will fully understand where things are coming from compared to Groovy’s dynamic nature.

Can a groovy build script class acces the Gradle project directly?

Can a groovy class (located in buildSrc/src/main/groovy) access the project directly, or does the project have to be passed in explicitly?
I am able to access the project by explicitly passing it in as a method parameter, but I do not want to have to pass it in. For an example, I would like to be able to get access to the project via a static method call. Is this type of implicit access possible?
Explicit Access
import org.gradle.api.Project
class MyClazz {
static void foo(Project project) {
println project.version
}
}
Task in build.gradle
task foo() << {
MyClazz.foo(project)
}
Implicit Access via Static Method Call (this is the desired access pattern)
import org.gradle.api.Project
class MyClazz {
static void foo() {
println Project.getProject().version
}
}
Task in build.gradle
task foo() << {
MyClazz.foo()
}
You can use Groovy extension methods to do this.
here's a self-contained example, but should work with Gradle too:
class Project {
// we add this method dynamically
//static getProject() { [ version: 2.3 ] }
}
class MyClazz {
static void foo() {
println Project.getProject().version
}
}
class Gradle {
static def main(args) {
Project.metaClass.static.getProject = { [ version: 4.2 ] }
MyClazz.foo()
}
}

gradle custom task execution phase

This question is for gradle (>= 2.4). I would like to write a custom task like the following:
https://docs.gradle.org/current/userguide/custom_tasks.html
class GreetingTask extends DefaultTask {
#TaskAction
def greet() {
println 'hello from GreetingTask'
}
}
task hello(type: GreetingTask)
how can I make this task run during execution phase? Is passing an empty closure with
<< {
}
the only solution?
Edit
the task is supposed to be used in a multiproject build with several tasks as dependencies.
I'd like that the command gradle build would build all the projects by saying something like
`build.dependsOn(hello)`
but seems that the task hello is called during configuration phase of the build.
Add the following to a build.gradle file:
class GreetingTask extends DefaultTask {
#TaskAction
def greet() {
println 'hello from GreetingTask'
}
}
task hello(type: GreetingTask) {
println "This is the configuration phase"
doFirst {
println "This is the execution phase"
}
}
Now execute gradle hello. The output you will see is
This is the configuration phase
:hello
This is the execution phase
hello from GreetingTask
BUILD SUCCESSFUL
As you can see, the output from the task occurs after the doFirst(), which definitely happens during the execution phase.

Gradle custom plugin : add dependency from extension object

I'm trying to write a plugin which adds dependencies to project.dependencies according to informations gathered in the plugin extension object. But it seems to be impossible.
Indeed, the data from extension object is only available in a new task or in project.afterEvaluate closure, but dependencies added in those places are ignored.
The following code tries to add the dependency in afterEvaluate but the dependency is ignored :
apply plugin: MyPlugin
myplugin {
version '1.0'
}
class MyPlugin implements Plugin<Project> {
void apply(Project project) {
project.extensions.create('myplugin', MyPluginExtension)
project.afterEvaluate {
def version = project.myplugin.version
project.dependencies.add("compile", "org.foo:bar:$version") // --> ignored
}
}
}
class MyPluginExtension {
def version
}
In the following code the dependency injection works but I don't have access to the extension object :
apply plugin: MyPlugin
myplugin {
version '1.0'
}
class MyPlugin implements Plugin<Project> {
void apply(Project project) {
project.extensions.create('myplugin', MyPluginExtension)
def version = project.myplugin.version // == null
project.dependencies.add("compile", "org.foo:bar:$version") // --> fail because $version is null
}
}
class MyPluginExtension {
def version
}
Is there a solution ?
Update: I managed to figure this out since my original answer. The way do this is to add a DependencyResolutionListener in which you add the dependencies and then remove the listener so it doesn't try to add them on later resolution steps.
compileDeps = project.getConfigurations().getByName("compile").getDependencies()
project.getGradle().addListener(new DependencyResolutionListener() {
#Override
void beforeResolve(ResolvableDependencies resolvableDependencies) {
compileDeps.add(project.getDependencies().create("org.foo:bar:$version"))
project.getGradle().removeListener(this)
}
#Override
void afterResolve(ResolvableDependencies resolvableDependencies) {}
})
I have a working example of a plugin that uses this here
Original Answer:
This is also late but for anyone dropping in. With the latest gradle (2.6 at the time of writing), you can add a DependencyResolutionListener and add any dependencies before dependencies are resolved.
project.getGradle().addListener(new DependencyResolutionListener() {
#Override
void beforeResolve(ResolvableDependencies resolvableDependencies) {
depsToAdd.each { dep ->
compileConfig.getDependencies()
.add(project.getDependencies().create(dep))
}
}
#Override
void afterResolve(ResolvableDependencies resolvableDependencies) {
}
})
However, as of this writing I was having some issues getting this to work with Android Studio IDE. The problem is tracked in my question here
I originally implemented this solution using the DependencyResolutionListener approach by Saad. However, the listener itself is called only when something iterates over the configuration associated with the dependency. For example, if you want to dynamically add a dependency to compile, you have to make sure that something later on does something like:
project.configurations.compile.each {
...
}
But this is something that happens as a matter of course, since compile is a known configuration for any project that uses the java plugin. However, if you are using a custom configuration (as I was), then the listener approach won't work unless you explicitly iterate over your custom configuration.
I was able to find a better way to do this, and within afterEvaluate as the OP originally wanted. I'm using a custom configuration here, but I don't see a reason why it wouldn't work for compile either:
project.afterEvaluate {
def version = project.myPlugin.version
project.configurations.myConfig.dependencies.add(
project.dependencies.add("myConfig", "org.foo:bar:$version")
)
}
Of course, at some point something still has to iterate over the dependencies for them to actually get resolved.
The easiest way to do this:
project.dependencies {
delegate.compile("com.android.support:appcompat-v7:25.0.1")
}
Don't know if that's still relevant, but you can workaround this by explicitly adding your compile configuration to Java classpath in doFirst:
variant.javaCompile.doFirst {
variant.javaCompile.classpath += project.configurations.myconfiguration
}

Resources