我的组织为许多项目使用相同的Gradle插件和依赖项。我的自定义插件知识很薄弱,但是我想做的是将这些插件和依赖项包装到一个独立的插件中。我坚持了解如何将插件所需的插件/依赖项与我想在使用项目中使用的插件/依赖项区分开。这是一个基于gradle custom plugin docs和一些information about storing the plugin in a maven repo to allow it to automatically download dependencies的简单示例:
// build.gradle from standalone plugin
plugins {
id 'java-gradle-plugin'
id 'maven-publish'
// these ones I don't need in the plugin, just in the project where I apply the plugin
id 'war'
id 'org.springframework.boot' version '2.2.4.RELEASE'
id 'io.spring.dependency-management' version '1.0.9.RELEASE'
id 'org.asciidoctor.convert' version '1.5.8'
}
group = 'org.sample'
version = '1.0.0'
publishing {
repositories {
maven {
url "../maven-repo"
}
}
}
gradlePlugin {
plugins {
greeting {
id = "org.sample.greeter"
implementationClass = "org.sample.GreetingPlugin"
}
}
}
dependencies {
implementation gradleApi() // I think I need this for the imports in GreetingPlugin.java
implementation localGroovy() // I think I would need this if GreetingPlugin was written in Groovy
// these ones I don't need in the plugin, just in the project where I apply the plugin
implementation 'org.springframework.boot:spring-boot-starter-web'
testImplementation 'org.springframework.boot:spring-boot-starter-test' {
exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
}
testImplementation 'org.junit.jupiter:junit-jupiter-engine'
}
// this is only needed in the project where I apply the plugin
// I believe this should be in the GreetingPlugin.java file though
test {
useJUnitPlatform()
}
和支持类...
package org.sample;
import org.gradle.api.DefaultTask;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.tasks.TaskAction;
class Greeting Plugin implements Plugin<Project> {
@Override
public void apply(Project project) {
project.getTasks().create("hello", MyTask.class);
}
public static class MyTask extends DefaultTask {
@TaskAction
public void myTask() {
System.out.println("Hello, World!");
}
}
}
在我要使用该插件的项目中,我具有以下文件:
// settings.gradle
pluginManagement {
repositories {
maven {
url "../maven-repo"
}
gradlePluginPortal()
}
}
// build.gradle
plugins {
id 'org.sample.greeter' version '1.0.0'
}
我的想法是,以这种方式使用插件,项目将继承插件代码中列出的插件和依赖项。我想我已经接近了,就像我./gradlew publish
看到插件被应用时一样,但它不喜欢spring-starter-web
依赖项没有版本(我知道一个多项目gradle仓库,我需要在mavenBOM中包含dependencyManagement块,所以这可能是关键吗?)我试图遵循SpringBoot gradle plugin进行深入了解,但这对我来说有点太复杂了。 >
那么,这是创建包含内置插件/依赖项的独立插件的正确方法吗?为什么Spring依赖管理器不应用版本控制?
编辑:我遵循了@Alan Hay的链接,而不是自定义插件,而是尝试使用“应用自”。但是,它仍然不起作用。这是基于该方法的文件:
// build.gradle from 'parent' build.gradle
plugins {
id 'war'
id 'org.springframework.boot' version '2.2.4.RELEASE'
id 'io.spring.dependency-management' version '1.0.9.RELEASE'
id 'org.asciidoctor.convert' version '1.5.8'
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
testImplementation 'org.springframework.boot:spring-boot-starter-test' {
exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
}
testImplementation 'org.junit.jupiter:junit-jupiter-engine'
}
test {
useJUnitPlatform()
}
并尝试引用另一个项目,这是文件中的唯一一行:
apply from: '<path-to-above>/build.gradle'
此错误如下:
script '<path-to-above>/build.gradle': 15: Only Project build scripts can contain plugins {} blocks
See https://docs.gradle.org/5.5.1/userguide/plugins.html#sec:plugins_block for information on the plugins {} block
@ line 15, column 1.
plugins {
^
1 error
答案 0 :(得分:0)
当需要在多个独立项目中共享相同的构建逻辑时,首选独立的二进制插件。此外,良好的插件设计可将功能与常规功能区分开。在这种情况下,该功能由Gradle和某些第三方插件提供,但是您要在此插件的顶部添加自己的约定。
在实现此功能时,您实际上需要将代码向下推一层。 build.gradle
中需要配置的所有内容都必须包含在插件的源代码中。会影响构建脚本的类路径的任何内容(即buildscript { }
或plugins { }
)都属于插件的依赖项。插件中的plugins { }
块仅应具有构建插件所需的构建插件。
// build.gradle from standalone plugin
// plugins {} should contain only plugins you need in the build of the plugin itself
plugins {
id 'java-gradle-plugin'
id 'maven-publish'
}
group = 'org.sample'
version = '1.0.0'
dependencies {
implementation gradleApi()
// Dependencies for plugins you will apply to the target build
implementation 'io.spring.gradle:dependency-management-plugin:1.0.9.RELEASE'
implementation 'org.asciidoctor:asciidoctor-gradle-jvm:2.4.0'
implementation 'org.springframework.boot:spring-boot-gradle-plugin:2.2.4.RELEASE'
}
gradlePlugin {
plugins {
greeting {
id = "org.sample.greeter"
implementationClass = "org.sample.GreetingPlugin"
}
}
}
publishing {
repositories {
maven {
url "../maven-repo"
}
}
}
package org.sample;
import org.gradle.api.DefaultTask;
import org.gradle.api.Plugin;
import org.gradle.api.plugins.JavaPlugin;
import org.gradle.api.Project;
import org.gradle.api.tasks.TaskAction;
import org.gradle.api.tasks.testing.Test;
class Greeting Plugin implements Plugin<Project> {
@Override
public void apply(Project project) {
// Apply plugins to the project (already on the classpath)
project.getPluginManager().apply("war");
project.getPluginManager().apply("org.springframework.boot");
project.getPluginManager().apply("io.spring.dependency-management");
project.getPluginManager().apply(" org.asciidoctor.convert");
// Dependencies that you need for the code in the project that this plugin is applied
DependencyHandler dependencies = project.getDependencies();
dependencies.add(JavaPlugin.IMPLEMENTATION_CONFIGURATION_NAME, "org.springframework.boot:spring-boot-starter-web");
dependencies.add(JavaPlugin.TEST_IMPLEMENTATION_CONFIGURATION_NAME, "org.junit.jupiter:junit-jupiter-engine");
dependencies.add(JavaPlugin.TEST_IMPLEMENTATION_CONFIGURATION_NAME, springBootStarterTest(dependencies));
projects.getTasks().withType(Test.class, test -> {
test.useJUnitPlatform();
});
}
private Dependency springBootStarterTest(DependencyHandler dependencies) {
Map<String, String> exclude = new HashMap<>();
exclude.put("group", "org.junit.vintage");
exclude.put("module", "junit-vintage-engine");
return ((ModuleDependency) dependencies.module("org.springframework.boot:spring-boot-starter-test")).exclude(exclude);
}
}
由于使用Java编写,因此更为冗长,但在功能上等同于将其放入项目的build.gradle
:
plugins {
id 'war'
id 'org.springframework.boot' version '2.2.4.RELEASE'
id 'io.spring.dependency-management' version '1.0.9.RELEASE'
id 'org.asciidoctor.convert' version '1.5.8'
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
testImplementation 'org.springframework.boot:spring-boot-starter-test' {
exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
}
testImplementation 'org.junit.jupiter:junit-jupiter-engine'
}
test {
useJUnitPlatform()
}