Contents
- Usage
- Tasks
- Project layout
- Source sets
- Dependency management
- Contributed extension
- Convention properties(deprecated)
- Testing
- Publishing
- Incremental Java compilation
- Incremental annotation processing
- Compilation avoidance
- Variant aware selection
此插件为项目增加了Java编译以及测试和打包的功能. 他提供了许多其他JVM语言Gradle 插件的基础. 你能够发现对于Java Plugin的综合介绍 - in 链接
Usage
为了使用Java 插件,包括以下到构建脚本中
plugins {
id 'java'
}
Tasks
此插件增加了大量的任务到项目中,如下所述:
- compileJava - JavaCompile
依赖: 所有贡献编译类路径的任务,包括此项目依赖的所有项目的jar 任务 ..
使用JDK 编译器编译生产Java source files
- processResources - Copy
拷贝生产资源到生产资源目录中
- classes
依赖: compile Java, processResources
这是一个聚合任务(仅仅依赖于其他任务),其他插件可以依附一些额外的编译任务到它 ..
- compileTestJava - JavaCompile
依赖于: classes,以及所有共享到测试编译类路径的任务
使用JDK编译器编译测试Java source files;
- processTestResources - Copy
拷贝测试资源到 测试资源目录中
- testClasses
依赖于: compileTestJava,processTestResources
这是一个聚合任务 - 仅仅依赖于其他任务,其他插件也许可以依附额外的测试编译任务到它 ..
- jar
依赖于: classes
组装可交付的Jar文件,基于依附于main 资源集(source set)的classes 以及 资源 (resources)
- javadoc - Javadoc
依赖于: classes
生成API 文档 - 使用Javadoc 为项目 ..
- test - Test
依赖于: testClasses,以及所有产生测试运行时类路径的任务
使用JUnit 或者TestNG 运行单元测试 …
- clean - Delete
删除项目构建目录
- cleanTaskName - Delete
删除由指定的任务创建的文件, 例如cleanJar 将会删除由jar任务创建的Jar 文件 以及 cleanTest 将会删除由 test 任务创建的测试结果 …
SourceSet Tasks
对于增加到项目的每一个资源集,此插件增加了以下任务:
- compileSourceSetJava - JavaCompile
依赖于: 所有贡献source set的编译类路径的任务
使用JDK 编译器编译给定资源集的Java source files …
- processSourceSetResources - Copy
拷贝给定的资源集资源到资源目录
- sourceSetClasses - Task
依赖于 compileSourceSetJava , processSourceSetResources
预备为了打包和执行的给定资源集的classes 和资源(resources) .
某些插件也许会为给定的资源集增加额外的编译任务 .
Lifecycle Tasks
此插件也依附了一些任务到由Base Plugin 定义的生命周期任务 .. 此插件会自动应用 , 增加此插件将会自动增加少量的其他任务:
- assemble
依赖: jar,以及创建工件依附于给定archives 配置的其他所有任务
这是一个聚合任务 组装项目中所有的归档 ,此任务由Base 插件增加 .
- check
依赖: test
执行验证任务的聚合任务,例如运行测试,某些插件可能增加它们自己的验证任务到check. 你应该可以依附一些自定义Test任务到这个生命周期任务(在构建中如果你想要它们执行), 这个任务由Base Plugin 增加 ..
- build
依赖: check,assemble
执行完整 项目构建的聚合任务,这个任务由Base 插件增加 ..
- buildNeeded
依赖于: build,以及此项目的testRuntimeClasspath上的所有依赖的buildNeeded 任务..
执行此项目的完整构建 以及 它所有依赖的所有项目构建 ..
- buildDependents
依赖于: build,所有项目的testRuntimeClasspath包含此项目依赖的所有buildDependents 任务 ..
执行此项目的完整构建以及依赖于此项目的所有项目构建 .
- buildConfigName - task rule
依赖: 所有生成工件到给定名称为 ConfigName 的配置的任务
为给定的配置组装工件,这个规则由Base Plugin 增加 ..
- uploadConfigName - task rule, type: Upload
依赖于: 所有生成归档文件到给定名称为 ConfigName 的配置的任务
组装并上传指定配置的工件(这个规则由 Base Plugin 增加)
图解任务依赖关系
Project layout
此插件假设项目的结构如下所示,这些目录都不需要存在或其中包含任何内容。 Java 插件将编译它找到的任何东西,并处理任何丢失的东西。
- src/main/java
产生Java source
- src/main/resources
产生资源,例如 XML 以及 properties files.
- src/test/java
测试Java source .
- src/test/resources
测试资源
- src/sourceSet/java
指定资源集的Java source
- src/sourceSet/resources
Changing the project layout
你能够配置这个项目结构 - 通过配置合适的资源集.
例如:
sourceSets {
main {
java {
srcDirs = ['src/java']
}
resources {
srcDirs = ['src/resources']
}
}
}
Source sets
此插件增加了以下两种 source sets
- main
包括这个项目的生产source code ,它们将被编译并打包进Jar中 ..
- test
包含了项目的测试代码,它们将使用Junit 或者TestNG编译并执行 .. 这些通常进行单元测试,但是它们能够包含资源集中的任务测试(只要它们共享相同的编译以及运行时类路径)
Source set properties
以下列出了资源集的重要属性,你能够在API 文档中发现更多详情 …SourceSet
- name - (read only) String
资源集的名称,被用来标识它
- output -(read only) SourceSetOutput
资源集的输出文件,包含了它编译的文件和资源
- output.classesDirs - (read-only) FileCollection
默认值 $buildDir/classes/java/$name,例如 build/classes/java/main
这个目录生成资源集的classes,也许包含了其他JVM语言的目录 ..例如:
build/classes/kotlin/main
- output.resourcesDir - File
默认: $buildDir/resources/$name,例如 build/resources/main
这个目录生成资源集的资源
- compileClasspath - FileCollection
默认值: ${name}CompileClasspath 配置 …
当编译这个资源集的源文件时所使用的类路径 …
- annotationProcessPath - FileCollection
默认是: ${name}AnnotationProcess 配置
这个处理器路径仅在编译此资源集的源文件时使用
- runtimeClasspath - FileCollection
默认为: $output,${name}RuntimeClasspath 配置
当执行这个资源集的classes时使用的类路径 ..
- java -(read only) SourceDirectorySet
此资源集的Java 源文件. 仅包含.java 文件(位于 Java source 目录中) 并且排除其他所有文件 ..
- java.srcDirs
默认值: src/$name/java,例如 src/main/java
这个资源目录包含这个资源集的Java source files .. 这个目录可以设置为任意值 ..
详情
- java.destinationDirectory - DirectoryProperty
默认值: $buildDir/classes/java/$name,例如 build/classes/java/main
这个目录生成编译的Java sources,你能够设置为任意值详情
- resources - (read only) SourceDirectorySet
此资源集的资源, 仅包含资源,并且排除任何.java文件 …
其他插件,例如Groovy 插件,从此集合中排除额外的类型 ..
- resources.srcDirs - Set
默认值: [src/$name/resources]
包含此资源集的资源的目录 …
- allJava - (read-only) SourceDirectorySet
默认值: 等同于 java 属性 …
此资源集的所有Java 文件,某些插件,例如Groovy 插件,增加额外的Java 源文件到这个集合中 ..
- allSource -(read only) SourceDirectorySet
默认值: resources和java属性的总计(一切)
此资源集任意语言的所有源文件 .. 这包括所有资源文件以及所有Java 资源文件 …
某些插件,例如Groovy 插件, 增加一些额外的资源文件到此集合中 ..
Defining new source sets
查看 integration test example 了解更多
某些其他简单资源集的例子
增加一个包含资源集的classes的Jar
tasks.register('intTestJar', Jar) {
from sourceSets.intTest.output
}
增加测试套件在资源集中运行测试
tasks.register('intTest', Test) {
testClassesDirs = sourceSets.intTest.output.classesDirs
classpath = sourceSets.intTest.runtimeClasspath
}
依赖管理
此插件增加了大量的dependency configurations 到项目中,例如compileJava 以及 test任务 使用一个或者多个这样的配置去获取相关的文件并使用它们 .. 例如在编译和运行时路径上进行替换 ..
Dependency configurations
为了发现api 配置中的信息,请考虑The Java Library Plugin参考文档 以及 Dependency Management for Java Projects
- implementation
仅实现依赖项
- compileOnly
仅编译时依赖,不在运行时使用
- compileClasspath extends compileOnly,implementation
编译类路径,被用来编译资源,由compileJava 任务使用
- annotationProcessor
在编译阶段使用的注解处理器
- runtimeOnly
仅运行时依赖
- runtimeClasspath extends runtimeOnly,implementation
包含了实现的元素,同样也包含仅运行时元素的运行时类路径 ..
- testImplementation extends implementation
针对测试仅实现依赖 …
- testCompileOnly
编译测试的额外依赖,不在运行时使用
- testCompileClasspath extends testCompileOnly,testImplementation
测试编译类路径,编译测试资源时使用,由compileTestJava 使用 ..
- testRuntimeOnly extends runtimeOnly
运行测试的仅运行时依赖
- testRuntimeClasspath extends testRuntimeOnly,testImplementation
运行测试的运行时类路径,由test任务使用
- archives
由此项目产生的工件(例如,jars),当构建时由Gradle 决定”default”任务执行时使用
- default extends runtimeElements
此项目上由项目依赖所使用的默认配置,包含了工件以及此项目在运行时需要的依赖 ..
以下的表展示了main 和 test 资源集单独的依赖配置,你能够使用这个图例解释颜色:
- 灰色的文本 - 配置不建议
- 绿色背景 - 针对此配置声明的依赖
- 蓝灰色的背景 - 任务消费的配置,不是你声明的依赖 ..
- 具有淡蓝色 背景的文本 - 是一个任务 ..
Java plugin - main source set dependency configurations
Java plugin - test source set dependency configurations
SourceSet dependency configurations
- sourceSetImplementation
给定资源集的编译时依赖,由sourceSetCompileClasspath,sourceSetRuntimeClasspath 使用 ..
- sourceSetCompileOnly
给定资源集的仅编译时依赖,不在运行时使用
- sourceSetCompileClasspath extends sourceSetCompileOnly,sourceSetImplementation
编译类路径,编译source时使用,由 compileSourceSetJava 使用 …
- sourceSetAnnotationProcessor
在此资源集编译阶段使用的注解处理器
- sourceSetRuntimeOnly
给定资源集的仅运行时依赖
- sourceSetRuntimeClasspath extends sourceSetRuntimeOnly,sourceSetImplementation
此运行时包含了implementation的元素 同样也包含了仅运行时的元素 …
贡献扩展
此Java 插件增加了java 扩展到项目中,这允许配置大量的Java相关的属性在一个专有的DSL 块中 ..
java {
toolchain {
languageVersion = JavaLanguageVersion.of(11)
}
}
- JavaVersion sourceCompatibility 资源兼容性
当编译Java 资源时使用的Java 版本兼容能力 . 默认值: 当前使用的JVM版本 .
- JavaVersion targetCompatibility 目标兼容性
生成classes 文件的Java 版本,默认值 sourceCompatibility
- withJavadocJar()
自动打包Javadoc 以及 使用一个工件 -javadoc.jar 创建一个变种 javadocElements,它们将作为发布的一部分 ..
- withSourcesJar()
自动打包源代码并使用-sources.jar 创建一个变种 sourceElements,作为发布的一部分 …
Directory 属性
- String reporting.baseDir
生成报告放置的目录的名称,相对于build 目录,默认值 reports
- (read-only) File reportsDir
获取生成报告的目录,默认值 buildDir/reporting.baseDir
- String testResultsDirName
生成的测试结果result.xml文件的放置目录名称,相对于build目录,默认值 -test-results
- (read-only) File testResultsDir
testResultsDirName的getter,默认值 buildDir/testResultsDirName
- String testReportDirName
生成测试报告放置的目录名称,相对于报告目录,默认值tests
- (read-only) File testReportDir
testReportDirName的getter,默认值 reportsDir/testReportDirName
- String libsDirName
生成库的目录名称,相对于build 目录,默认值libs
- (read-only) File libsDir
生成库的目录,默认值 buildDir/libsDirName
- distsDirName
生成发布的目录名称,相对于构建目录,默认值distributions
- (read-only) File distsDir
生成库的目录, buildDir/distsDirName
- String docsDirName
生成文档的目录名称,相对于构建目录,默认值docs
- (read-only) File docsDir
生成文档的目录,默认值 buildDir/docsDirName
- String dependencyCacheDirName
用来缓存资源依赖信息的目录名称,相对于构建目录,默认值: dependency-cache
Other properties
- (read only) SourceSetContainer sourceSets
项目资源集的容器,默认值: 非空SourceSetContainer
- String archivesBaseName
归档文件的baseName,例如Jar或者ZIP文件 .. 默认值: projectName
- Manifset manifest
包括在所有Jar文件中的manifset,默认值: 一个空的manifest …
Convention properties(deprecated)
这个插件加入了大量的约定属性到项目中,你能够在构建脚本中使用这些属性 - 它们作为项目的属性 .. 这是一个废弃的且由扩展属性取代的特性.
查看 JavaPluginConvetion DSL 文档了解更多信息 …
Testing
查看Testing in Java & JVM project 了解更多 …
Publishing
- components.java
发布一个由jar任务创建的Jar的SoftwareComponent,这个组件包含了Jar 运行时依赖信息 ..
也可以查看 java extension .
Incremental Java Compilation
从Gradle 4.7开始,增量编译器支持增量注解处理,所有的注解处理器需要加入此特性,否则它们将触发完整的重编译 ..
作为一个用户你能够看到通过 —info 日志 了解那些注解处理器触发了完全重编译 .
增量注解处理将不会被激活(如果在编译任务上配置了自定义的executable 或者javaHome)
Making an annotation processor incremental
请先查看Incremental Java compilation,因为增量注解处理构建在它之上 ..
Gradle 支持为两类常用的注解处理器实行增量构建: “隔离的isolating” 以及 “聚合的aggregating”. 请考虑以下信息决定你的处理器适用于那种分类 .
你能够为增量构建注册你的处理器 - 通过在处理器的META-INF目录中使用文件 …
这个形式是 一行一个处理器,填充完整的处理器类的名称,以及大小写不敏感的分类(通过逗号分割)
例如:
org.gradle.EntityProcessor,isolating org.gradle.ServiceRegistryProcessor,dynamic
如果你的处理器能够在运行时是否开启增量,那么你能够设置它为一个”dynamic” - 在META-INF描述符中并且在运行时返回它的正确类型(通过Processor#getSupportedOptions()方法)
例如:
@Override
public Set<String> getSupportedOptions() {
return Collections.singleton("org.gradle.annotation.processing.aggregating");
}
两种分类都有以下限制:
- 它们必须通过Filer API生成它们的文件 .. 使用其他方式编写的文件将会导致失败,因为这些文件不会被正确清理. 如果你的处理器这样做,那么它不能是增量的 …
- 它们必须不能依赖特定于编译器的API(例如 com.sun.source.util.Trees).Gradle 包装这些处理APIs,因此尝试强转它们为编译器指定类型将会失败 .. 如果你的处理器这样做,它不能是增量的,除非你拥有兜底机制 …
- 如果它们使用了Filer#createResource),那么location 参数必须是来自StandardLocation的以下值:
- CLASS_OUTPUT
- SOURCE_OUTPUT
- NATIVE_HEADER_OUTPUT
“Isolating” 注解处理器
这是最快的分类,它们将独立的插件每一个注解的元素 .. 为它们创建生成的文件或者验证消息 …
对于一个EntityProcessor的实例 - 通过为注解了@Entity的每一个类型创建
Example: An isolated annotation processor
Set<? extends Element> entities = roundEnv.getElementsAnnotatedWith(entityAnnotation);
for (Element entity : entities) {
createRepository((TypeElement) entity);
}
此类型的处理器有以下限制:
- 它们必须做出所有的决定(代码生成,验证消息) - 从AST可达的每一个注解的类型信息做出决定,这就意味着你能够分析这些类型的超累,方法返回值,注解等等,甚至传递性 ..
但是你不能够基于RoundEnvironment的不相关的元素做出决定 .. 这样做将会导致一个错误,因为后面仅仅有一部分文件将重新编译 ..
如果您的处理器需要根据其他不相关元素的组合做出决定,那么使用”aggregating”代替 …
- 它们必须提供准确的一个由Filer API为每一个文件生成的原始元素 ..如果提供了0个或者多个,Gradle 将会重新编译所有的源文件 …
当一个源文件被重新编译,Gradle 将会重新编译所有的由它(源文件)生成的所有文件,当一个源文件被删除时,由它生成的文件将会被删除 …
“Aggregating” annotation processor
这些能够聚合各个源文件到一个或者多个输出文件或者验证消息 ..
举个例子,一个ServiceRegistryProcessor 能够创建一个ServiceRegistry(为每一个使用@Service注解的类型)且具有一个方法
Example: An Aggreating annotation processor
JavaFileObject serviceRegistry = filer.createSourceFile("ServiceRegistry");
Writer writer = serviceRegistry.openWriter();
writer.write("public class ServiceRegistry {");
for (Element service : roundEnv.getElementsAnnotatedWith(serviceAnnotation)) {
addServiceCreationMethod(writer, (TypeElement) service);
}
writer.write("}");
writer.close();
“Aggregating” 处理器具有以下限制:
- 它们能够读取CLASS 或者 RUNTIME 保留注解
- 它们能够读取参数名称(如果用户使用了 -parameters 编译器参数)
Gradle 将始终重新处理(但不重新编译)处理器注册的所有带注释的文件,Gradle 将总是重新编译处理器生成的所有文件 ..
State of support in popular annotation processors
许多受欢迎的注解处理器支持增量注解构建(查看下表). 检查对应的注解处理器项目以及最新的信息和文档 …
Annotation Processor | Supported since | Details |
---|---|---|
Auto Value | 1.6.3 | N/A |
Auto Service | 1.6.3 | N/A |
Auto Value extensions | Partly supported. | Details in issue |
Butterknife | 10.2.0 | N/A |
Lombok | 1.16.22 | N/A |
DataBinding | AGP 3.5.0-alpha5 | Hidden behind a feature toggle |
Dagger | 2.18 | 2.18 Feature toggle support, 2.24 Enabled by default |
kapt | 1.3.30 | Hidden behind a feature toggle |
Toothpick | 2.0 | N/A |
Glide | 4.9.0 | N/A |
Android-State | 1.3.0 | N/A |
Parceler | 1.1.11 | N/A |
Dart and Henson | 3.1.0 | N/A |
MapStruct | 1.4.0.Beta1 | N/A |
Assisted Inject | 0.5.0 | N/A |
Realm | 5.11.0 | N/A |
Requery | Open issue | N/A |
EventBus | 3.2.0 | N/A |
EclipseLink | Open issue | N/A |
PermissionsDispatcher | 4.2.0 | N/A |
Immutables | Open issue | N/A |
Room | 2.2.0 | 2.2.0 Feature toggle support, 2.3.0-alpha02 Enabled by default |
Lifecycle | 2.2.0-alpha02 | N/A |
AndroidAnnotations | 4.7.0 | N/A |
DBFlow | Open issue | N/A |
AndServer | Open issue | N/A |
Litho | 0.25.0 | N/A |
Moxy | 2.0 | N/A |
Epoxy | 4.0.0-beta1 | N/A |
JPA Static Metamodel Generator | 5.4.11 | N/A |
DeepLinkDispatch | 5.0.0-beta01 | Hidden behind a feature toggle |
Shortbread | 1.1.0 | N/A |
编译避免
如果一个依赖的项目在ABI兼容的方式发生了改变(仅仅只有私有API发生改变). 那么Java 编译任务将会是最新的.. 这就意味着如果A依赖了B并且B中的一个类以ABI二进制兼容的方式发生了改变(通常,,改变方法的body),那么Gradle 将不会重新编译A …
有些类型的改变不会影响公共API并且它们将被忽略:
- 改变方法体
- 改变注释
- 增加/移除或者改变私有方法,字段,内部类
- 增加或者移除或者改变一个资源
- 改变jar的名称或者类路径上的目录
- 重命名一个参数
由于注解处理器的实现细节非常重要,它们必须在注解处理器路径上单独声明,Gradle 将在编译类路径上忽略所有的注解处理器 …
dependencies {
// The dagger compiler and its transitive dependencies will only be found on annotation processing classpath
annotationProcessor 'com.google.dagger:dagger-compiler:2.8'
// And we still need the Dagger library on the compile classpath itself
implementation 'com.google.dagger:dagger:2.8'
}
Variant aware selection
整套 JVM 插件利用变体感知解析来处理所使用的依赖项,他们还安装了一组属性兼容性和消歧规则,以针对 JVM 生态系统的细节配置 Gradle 属性。