I need to apply a gradle plugin, in this case errorprone from a custom Gradle plugin.
My Plugin has a build.gradle that looks like this:
gradlePlugin {
plugins {
myErrorprone {
id = 'my-errorprone'
implementationClass = 'com.my.MyErrorpronePlugin'
}
}
}
And the plugin code is:
public class MyErrorpronePlugin implements Plugin<Project> {
List<String> compilerArgs =
Arrays.asList(
"-XepExcludedPaths:.*/proto/.*|.*/protoGeneratedSrc/.*",
"-XepDisableWarningsInGeneratedCode");
#Override
public void apply(Project project) {
project.getPluginManager().apply("net.ltgt.errorprone:");
for (JavaCompile task : project.getTasks().withType(JavaCompile.class)) {
task.getOptions().setCompilerArgs(compilerArgs);
}
}
}
Then, when in another project I apply this plugin (after getting the dependencies in the buildscript)
like this:
apply plugin: 'my-errorprone'
A problem occurred evaluating root project 'my-project.
Failed to apply plugin [id 'my-errorprone']
Plugin with id 'net.ltgt.errorprone' not found.
And it only resolved if i add to buildscript classpath
classpath "net.ltgt.gradle:gradle-errorprone-plugin:0.0.16"
How can I make my plugin work in such way that the project that consumes my plugin will not have to add this direct dependency in the classpath in "net.ltgt.gradle:gradle-errorprone-plugin:0.0.16" ?
In order to solve it, one should apply the plugin by class rather than by ID. This will force you to include error prone dependency in your plugin’s dependency list as it won’t compile until you add the dependency.
import net.ltgt.gradle.errorprone.ErrorPronePlugin.class;
public class MyPlugin implements Plugin<Project> {
public void apply(Project project) {
project.getPluginManager().apply(ErrorPronePlugin.class);
// custom logic here
}
}
and in the build.gradle file:
repositories {
maven {
url "https://plugins.gradle.org/m2/"
}
}
dependencies {
api "net.ltgt.gradle:gradle-errorprone-plugin:1.1.1"
}
I found the answer in Gradle's forum under this topic:
https://discuss.gradle.org/t/apply-a-gradle-plugin-errorprone-from-a-custom-gradle-java-plugin/34645/4
Related
In a regular build script you can easily use extensions on Project like Project.sourceSets, for example build.gradle.kts:
sourceSets {
main {
...
}
}
But when I am developing a Gradle plugin in my buildSrc module, I cannot access these. For example:
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.kotlin.dsl.*
class ExamplePlugin : Plugin<Project> {
override fun apply(target: Project) {
target.sourceSets { // error because `sourceSets` can't be resolved.
}
}
}
This is happening despite including the kotlin-gradle-plugin module in my buildSrc dependencies:
plugins {
`kotlin-dsl`
}
repositories {
mavenCentral()
}
dependencies {
implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.31")
}
So, how can I access these extensions from within my Gradle plugin?
class ExamplePlugin : Plugin<Project> {
override fun apply(target: Project) {
target.configure<JavaPluginExtension> {
sourceSets {
println(names)
}
}
}
}
See additional notes here: https://docs.gradle.org/current/userguide/kotlin_dsl.html#project_extensions_and_conventions
Basically for plugins, or other times when the plugins applied are not known, the accessors (sourceSets, configurations, etc) of extensions added by other plugins will need to go through a method call which sort of 'retrieves' that scope or object. Further down the link there is also an example of how to get tasks created by other plugins:
val test by target.tasks.existing(Test::class)
test.configure { useJUnitPlatform() }
// or
val test by target.tasks.existing(Test::class) {
useJUnitPlatform()
}
note that if the 'sourceSet' object does not exist on the project (because the java plugin was not applied), an exception will be thrown .
tested with gradle version 7.2, kotlin-dsl version 2.1.6
Trying to create a custom plugin to share the buildscript logic across projects. I have added the buildscript classpath dependencies but it is still saying that the plugin can't be found. I do not want to manually it in the project that is using the custom plugin because I may have to change the version number in the future. Is there any solution for this?
DependencyManagementPlugin.java
public class DependencyManagementPlugin implements Plugin<Project> {
#Override
public void apply(Project project) {
DependencyHandler dependencies = project.getBuildscript().getDependencies();
dependencies.add("classpath", "org.springframework.boot:spring-boot-gradle-plugin:2.4.10");
dependencies.add(
"classpath",
"io.spring.dependency-management:io.spring.dependency-management.gradle.plugin:1.0.11.RELEASE");
PluginContainer plugins = project.getPlugins();
plugins.apply(MavenPublishPlugin.class);
plugins.apply(JavaPlugin.class);
plugins.apply(JacocoPlugin.class);
plugins.apply("org.springframework.boot");
plugins.apply("io.spring.dependency-management");
}
}
build.gradle
plugins {
id 'groovy-gradle-plugin'
id 'maven-publish'
}
gradlePlugin {
plugins {
dependencyManagementPlugin {
id = 'com.example.dependency-management'
implementationClass = 'com.example.DependencyManagementPlugin'
}
}
}
using the plugin in another build.gradle
plugins {
id 'com.example.dependency-management'
}
...
Error message:
An exception occurred applying plugin request [id: 'com.example.dependency-management']
> Failed to apply plugin 'com.example.dependency-management'.
> Plugin with id 'org.springframework.boot' not found.
The solution is to add the dependency in the dependencies block of the build.gradle of the custom gradle plugin project.
https://docs.gradle.org/current/samples/sample_convention_plugins.html
I'm trying to build my own custom line marker for Clion following this tutorial - https://plugins.jetbrains.com/docs/intellij/line-marker-provider.html . My question is about the language attribute on the extension tag in the plugin.xml file ...
<extensions defaultExtensionNs="com.intellij">
<codeInsight.lineMarkerProvider language="JAVA"
implementationClass="org.intellij.sdk.language.SimpleLineMarkerProvider"/>
</extensions>
When i add this extension the language="JAVA" gets highlighted in red. What plugin/dependency do i need to add for this to be resolved?
My IDE is also not able to resolve PsiIdentifier and PsiMethod from the provided snippet ...
public class MyCorrectLineMarkerProvider implements LineMarkerProvider {
public LineMarkerInfo getLineMarkerInfo(#NotNull PsiElement element) {
if (element instanceof PsiIdentifier && element.getParent() instanceof PsiMethod) return new LineMarkerInfo(element, ...);
return null;
}
}
This is what my build.gradle looks like, i know there are some other dependencies i need to add but the tutorial i've been following isn't very clear about it.
plugins {
id 'org.jetbrains.intellij' version '1.2.0'
id 'java'
}
group 'com.example'
version '1.0-SNAPSHOT'
repositories {
mavenCentral()
}
dependencies {
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.7.0'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.7.0'
}
// See https://github.com/JetBrains/gradle-intellij-plugin/
intellij {
version = '2021.2.2'
}
runIde {
jvmArgs '--add-exports', 'java.base/jdk.internal.vm=ALL-UNNAMED'
}
patchPluginXml {
changeNotes = """
Add change notes here.<br>
<em>most HTML tags may be used</em>"""
}
test {
useJUnitPlatform()
}
You have to add a dependency on the java plugin in your build.gradle, like so
intellij {
plugins = ['java']
}
See the IntelliJ Dev Guide for more information on plugin dependencies.
The tutorial you are following is meant for adding support for a new language, instead you are adding a line marker to Java (existing language :p). Plugin dependencies are simply outside the scope of that tutorial.
I'm trying to get a simple non-Android Java project working with Dagger2 in IntelliJ (2016.3.3, not AndroidStudio) and Gradle (3.1), but nothing seems to get generated at all, I get no DaggerXXX classes output. Not sure if it's the Dagger annotation processing that doesn't work, the source set configuration in IntelliJ that's wrong, or something else. When building the project I get the following output:
build
|_classes
|_main
|_com
| |_<test classes correctly built>
|_generated
|_<empty, but should contain generated Dagger classes?>
What I've done is:
Configured the project to use annotation processing in the IntelliJ settings.
Used the following config:
buildscript {
repositories {
mavenCentral()
jcenter()
maven {
url("https://plugins.gradle.org/m2/")
}
}
dependencies {
classpath "net.ltgt.gradle:gradle-apt-plugin:0.9"
}
}
apply plugin: 'net.ltgt.apt'
apply plugin: 'java'
apply plugin: 'idea'
repositories {
mavenCentral()
}
dependencies {
compile 'com.google.dagger:dagger:2.8'
apt 'com.google.dagger:dagger-compiler:2.8'
}
sourceSets {
main {
java {
srcDirs 'src/main/java'
}
}
}
Test program:
public class Test {
#Inject
TestPojo testPojo;
public static void main(String[] args){
<no generated Dagger component available for building>
}
}
#Component(modules = Module.class)
public interface Component {
Pojo get();
}
#Module
public class Module {
#Provides
public Pojo get(){
return new Pojo();
}
}
public class Pojo {}
Update:
It's working if I build the project through the command line and not through the IntelliJ gui. That points to the issue being within the IntelliJ environment or its Gradle integration somehow, rather than in the build script itself.
I am trying to reorganize this Android (Java based) library to use the buildSrc folder to define all versions and dependencies as described in this article.
I already set this successfully up for several times for Kotlin bases projects. This time the project is pure Java.
In the buildSrc folder I created the following buildSrc/src/main/java/org/ligi/snackengage/Dependencies.java file:
package org.ligi.snackengage;
public class Dependencies {
public static class Android { /* ... */ }
public static class GradlePlugins {
public static final String ANDROID = "com.android.tools.build:gradle:3.6.3";
// ...
}
public static class Libs { /* ... */ }
}
Then I refer to the definitions in the project root build.gradle among others:
import org.ligi.snackengage.Dependencies.GradlePlugins
apply plugin: "com.github.ben-manes.versions"
buildscript {
repositories {
google()
jcenter()
}
dependencies {
classpath GradlePlugins.ANDROID
classpath GradlePlugins.MAVEN
classpath GradlePlugins.VERSIONS
}
}
allprojects {
repositories {
google()
jcenter()
}
}
Here is the work in progress branch. When I build the project then the following error occurs:
* Where:
Build file 'SnackEngage/build.gradle' line: 12
* What went wrong:
A problem occurred evaluating root project 'SnackEngage'.
> Could not get unknown property 'GradlePlugins' for object of type
org.gradle.api.internal.artifacts.dsl.dependencies.DefaultDependencyHandler.
Here is the build log.
You have defined GradlePlugins class as an inner static class of Dependencies, so you need to use Dependencies.GradlePlugins to access it from your build script.
Change your dependencies block as follows:
import org.ligi.snackengage.Dependencies // do not import org.ligi.snackengage.Dependencies.GradlePlugins
buildscript {
// ...
dependencies {
classpath Dependencies.GradlePlugins.ANDROID
classpath Dependencies.GradlePlugins.MAVEN
classpath Dependencies.GradlePlugins.VERSIONS
}
}
EDIT you could also use a static import, as follows:
import static org.ligi.snackengage.Dependencies.*
buildscript {
// ...
dependencies {
classpath GradlePlugins.ANDROID
classpath GradlePlugins.MAVEN
classpath GradlePlugins.VERSIONS
}
}
You need to define variable GradlePlugins with def (in Gradle) or public class GradlePlugins (in Java), before attempting to access it. Kotlin class GradlePlugins should also work.
dependencies {
classpath GradlePlugins.ANDROID
classpath GradlePlugins.MAVEN
classpath GradlePlugins.VERSIONS
}
And I think the buildSrc directory belongs into the module directory, as the Gradle manual shows.