Gradle Java Plugin: Difference between revisions
(13 intermediate revisions by the same user not shown) | |||
Line 6: | Line 6: | ||
* [[Gradle Dependencies and Dependency Configurations]] | * [[Gradle Dependencies and Dependency Configurations]] | ||
=Overview= | =Overview= | ||
The Java plugin adds Java compilation, testing and packaging capabilities to a project. | The Java plugin adds Java compilation, testing and packaging capabilities to a project. | ||
Line 32: | Line 30: | ||
==Source Set== | ==Source Set== | ||
{{External|https://docs.gradle.org/current/dsl/org.gradle.api.tasks.SourceSet.html}} | {{External|https://docs.gradle.org/current/dsl/org.gradle.api.tasks.SourceSet.html}} | ||
A source set is a logical grouping of source files and resources, typically associated on the base of their purpose: application production code, test code, etc. Each source set contains sources and resources from typically one, but possibly more directories, which are listed as part of the source set. The files that form a source set '''don't have to be located in the same directory'''. The source set concept was introduced by the Java plugin, | A source set is a logical grouping of source files and resources, typically associated on the base of their purpose: application production code, test code, etc. Each source set contains sources and resources from typically one, but possibly more directories, which are listed as part of the source set. The files that form a source set '''don't have to be located in the same directory'''. The source set concept was introduced by the Java plugin. A source set directory has subdirectories for java sources, and other types of sources. The Java plugin instantiates by default two source sets: [[#main_SourceSet|main]] and [[#test_SourceSet|test]]. They correspond to the conventional directories from "src": | ||
<syntaxhighlight lang='text'> | <syntaxhighlight lang='text'> | ||
. | . | ||
└─ src | └─ src | ||
├─ main ← source set "main" | ├─ main ← source set "main" | ||
│ | │ ├─ java ← the java subtree of the "main" source set | ||
│ | │ │ └─ playground | ||
│ | │ │ └─ Sample.java | ||
└─ test ← source set "test" | │ └─ resources ← the resource subtree of the "main" source set | ||
│ | |||
└─ test ← source set "test" | |||
├─ java ← the java subtree of the "test" source set | |||
│ └─ playground | |||
│ └─ SampleTest.java | |||
└─ resources ← the resource subtree of the "test" source set | |||
</syntaxhighlight> | </syntaxhighlight> | ||
<span id='SourceSet_Configuration'></span>Aside from the source files and resources, the source set also keeps track of various classpaths, including any dependencies, require the compile or run the code. It does that by maintaining a set of '''[[Gradle_Dependencies_and_Dependency_Configurations#Configuration|configurations]]''' corresponding to the compilation classpath, annotation processor classpath and runtime classpath. Each source set has associated an "<''source-set-name''>implementation" configuration. In case of the "main" source set, main is omitted and the configuration is named simply "implementation". Also see: {{Internal|Gradle_Dependencies_and_Dependency_Configurations#Dependency|Configuration}} | <span id='SourceSet_Configuration'></span>Aside from the source files and resources, the source set also keeps track of various classpaths, including any dependencies, require the compile or run the code. It does that by maintaining a set of '''[[Gradle_Dependencies_and_Dependency_Configurations#Configuration|configurations]]''' corresponding to the compilation classpath, annotation processor classpath and runtime classpath. Each source set has associated an "<''source-set-name''>implementation" configuration. In case of the "main" source set, main is omitted and the configuration is named simply "implementation". Also see: {{Internal|Gradle_Dependencies_and_Dependency_Configurations#Dependency|Configuration}} | ||
Line 64: | Line 66: | ||
java { | java { | ||
srcDirs = ['src/main/java'] | srcDirs = ['src/main/java'] | ||
} | |||
resources { | |||
srcDirs = ['src/main/resources'] | |||
excludes = ['**/something/**'] | |||
} | } | ||
} | } | ||
Line 69: | Line 75: | ||
java { | java { | ||
srcDirs = ['src/test/java'] | srcDirs = ['src/test/java'] | ||
} | |||
resources { | |||
srcDirs = ['src/test/resources'] | |||
excludes = ['**/something/**'] | |||
} | } | ||
} | } | ||
Line 139: | Line 149: | ||
The "processTestResources" task processes the [[#Resource_Files|resources]] managed by the [[#The_.22test.22_Source_Set|test source set]]. The task is an implementation of the Copy type. For more details see: {{Internal|Gradle_Copy_Task_Type#Overview|Copy task}} | The "processTestResources" task processes the [[#Resource_Files|resources]] managed by the [[#The_.22test.22_Source_Set|test source set]]. The task is an implementation of the Copy type. For more details see: {{Internal|Gradle_Copy_Task_Type#Overview|Copy task}} | ||
==<span id='jar_Task'></span><tt>jar</tt>== | ==<span id='jar_Task'></span><tt>jar</tt>== | ||
===Bytecode JAR=== | |||
Assembles the JAR file from the classes produced by the [[#The_.22main.22_Source_Set|"main" source set]] source files and "main" source set resources. No configuration is needed for a standard Java project. The task produces a single JAR conventionally named: | Assembles the JAR file from the classes produced by the [[#The_.22main.22_Source_Set|"main" source set]] source files and "main" source set resources. No configuration is needed for a standard Java project. The task produces a single JAR conventionally named: | ||
<''archiveBaseName''>[-''archiveAppendix'']<-''archiveVersion''>[-''archiveClassifier''].<''archiveExtension> | <''archiveBaseName''>[-''archiveAppendix'']<-''archiveVersion''>[-''archiveClassifier''].<''archiveExtension> | ||
By default, that translates to: | By default, that translates to: | ||
<''project''>-<''version''>.jar | <''project''>-<''version''>.jar | ||
The JAR is placed in the build/libs project directory. It depends on the [[#classes|classes]] task. | |||
No task configuration is necessary by default, but the task can be configured in <code>build.gradle</code> using a <code>jar {...}</code> configuration block: | |||
<syntaxhighlight lang='groovy'> | |||
jar { | |||
manifest.attributes 'Main-Class': 'playground.Main' | |||
} | |||
</syntaxhighlight> | |||
For example, the name of the JAR can be changed through configuration, as explained in the [[#Custom_JAR_Name|Custom JAR Name]] section below. The task is backed by the [[Gradle_Jar_Task_Type#Overview|Jar]] type, and detailed configuration documentation is available in {{Internal|Gradle_Jar_Task_Type#Configuration|Jar Task Type}} | |||
The plugin creates by default a "thin" JAR, which only includes the project classes. A "fat" JAR, or an uber-JAR, is a self-sufficient archive which contains both classes and dependencies needed to run an application. To create a "fat" JAR, see: {{Internal|Create_a_Fat_JAR_with_Gradle|Create a Fat JAR with Gradle}} | The plugin creates by default a "thin" JAR, which only includes the project classes. A "fat" JAR, or an uber-JAR, is a self-sufficient archive which contains both classes and dependencies needed to run an application. To create a "fat" JAR, see: {{Internal|Create_a_Fat_JAR_with_Gradle|Create a Fat JAR with Gradle}} | ||
Note that [[Gradle Java Library Plugin|Java Library]] plugin integrates the "jar" task with the standard lifecycle task [[Gradle_Base_Plugin#assemble|assemble]]. | Note that [[Gradle Java Library Plugin|Java Library]] plugin integrates the "jar" task with the standard lifecycle task [[Gradle_Base_Plugin#assemble|assemble]]. | ||
Also see: {{Internal|Gradle_Artifacts#Artifact|Gradle Artifacts}} | Also see: {{Internal|Gradle_Artifacts#Artifact|Gradle Artifacts}} | ||
====JAR Customizations==== | |||
=====Custom JAR Name===== | |||
=====FAT JAR===== | |||
{{Internal|Create_a_Fat_JAR_with_Gradle|Create a Fat JAR with Gradle}} | |||
===Source JAR=== | |||
<font color=darkgray>TODO</font>. | |||
==<tt>javadoc</tt>== | ==<tt>javadoc</tt>== | ||
Line 220: | Line 246: | ||
targetCompatibility = 11 | targetCompatibility = 11 | ||
</syntaxhighlight>If the toolchain is used, that makes it illegal to use sourceCompatibility and targetCompatibility. | </syntaxhighlight>If the toolchain is used, that makes it illegal to use sourceCompatibility and targetCompatibility. | ||
The target compatibility level reflects in the generated classes bytecode version. For more details, see: {{Internal|Java Bytecode Version|Java Bytecode Version}} | |||
==Compiler Options Customization== | ==Compiler Options Customization== | ||
Line 264: | Line 292: | ||
main { | main { | ||
resources { | resources { | ||
srcDirs "src/main/resources", "src/main/configs" | srcDirs = ["src/main/resources", "src/main/configs"] | ||
excludes = ['**/something/**'] | |||
} | } | ||
} | } | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
=Testing with Gradle Java Plugin= | =Testing with Gradle Java Plugin= | ||
{{Internal|Testing with Gradle Java Plugin#Overview|Testing with Gradle Java Plugin}} | {{Internal|Testing with Gradle Java Plugin#Overview|Testing with Gradle Java Plugin}} |
Latest revision as of 19:12, 12 June 2021
External
Internal
Overview
The Java plugin adds Java compilation, testing and packaging capabilities to a project.
plugins {
id 'java'
}
The Java plugin also serves as the basis for many of the other JVM language Gradle plugins. The Java plugin builds upon a Java Base plugin.
However, it is the Java Library plugin that should be used by default with Java projects instead of Java plugin. Java Library plugin extends the Java plugin, so it offers all the features of the Java plugin, plus a set of additional ones:
The Java plugin instantiates by default two source sets ("main" and "test"). Each of these source sets has an associated compile task: compileJava (which is the abbreviation of "compileMainJava") for the "main" source set and compileTestJava for the "test" source set. To compile the production and test code:
- put the production source code in 'src/main/java' directory.
- put the test source code under 'src/test/java' directory.
- declare your production compile dependencies in the compileOnly or implementation configurations.
- declare your test compile dependencies in the testCompileOnly or testImplementation configurations.
- Run the compileJava task for the production code and compileTestJava for the tests.
The Java plugin also adds a jar task that assembles a JAR file with the classes produced from the "main" source set code.
The default configuration of the source sets is convention-based, borrowing the directory layout from Maven projects. As such, if those conventions are followed, generally not much needs to be added to the build script to get a useful build.
Concepts
Source Set
A source set is a logical grouping of source files and resources, typically associated on the base of their purpose: application production code, test code, etc. Each source set contains sources and resources from typically one, but possibly more directories, which are listed as part of the source set. The files that form a source set don't have to be located in the same directory. The source set concept was introduced by the Java plugin. A source set directory has subdirectories for java sources, and other types of sources. The Java plugin instantiates by default two source sets: main and test. They correspond to the conventional directories from "src":
.
└─ src
├─ main ← source set "main"
│ ├─ java ← the java subtree of the "main" source set
│ │ └─ playground
│ │ └─ Sample.java
│ └─ resources ← the resource subtree of the "main" source set
│
└─ test ← source set "test"
├─ java ← the java subtree of the "test" source set
│ └─ playground
│ └─ SampleTest.java
└─ resources ← the resource subtree of the "test" source set
Aside from the source files and resources, the source set also keeps track of various classpaths, including any dependencies, require the compile or run the code. It does that by maintaining a set of configurations corresponding to the compilation classpath, annotation processor classpath and runtime classpath. Each source set has associated an "<source-set-name>implementation" configuration. In case of the "main" source set, main is omitted and the configuration is named simply "implementation". Also see:
Finally, the source set keeps track of where the compiled class files are placed, as a source set output.
The Java plugin automatically creates compilation tasks for each source set, naming them "compile<source-set-name>Java". In case of the "main" source set, the <source-set-name> is omitted and the task is called "compileJava".
Each source set is internally maintained in the runtime project hierarchy as child of the Java plugin. However, it can be configured via a top-level script blocks:
plugins {
id 'java'
}
sourceSets {
main {
java {
srcDirs = ['src/main/java']
}
resources {
srcDirs = ['src/main/resources']
excludes = ['**/something/**']
}
}
test {
java {
srcDirs = ['src/test/java']
}
resources {
srcDirs = ['src/test/resources']
excludes = ['**/something/**']
}
}
}
More details on how to reconfigure existing source sets is available below in the section Source Set Customization.
Source Set Lifecycle
How is a source set configured during the project lifecycle? How are configurations injected?
Resource Files
Java projects typically include resource other than source files, such as property files, that may need processing - for example by replacing tokens within the files - and packaging them within the final JAR. Typical use cases for resource files are images, configuration files, localization data. The Java plugin handles this automatically by creating a dedicated task for each source set, called "process<source-set-name>Resources", or "processResources" for the main source set. The processing consists in copying files from src/<source-set>/resources to a directory that will be included in the project's JAR. This target directory will also be included in the runtime classpath of the tests.
Default Source Sets
The "main" Source Set
The main source set is conventionally associated with all source files found under src/main/java and all resource files from src/main/resources. The sources managed by the main source set are compiled by the compileJava task. The resources are processed by the processResources task. The main source set is associated with the "compileOnly", "runtimeOnly" and "implementation" configurations. The jar task packages the main source set compiled classes and resources.
└─ src
└─ main
├─ java
└─ resources
The "test" Source Set
The "test" source set is conventionally associated with all the source file under src/test/java. It contains test source code, which is compiled and executed using JUnit or TestNG. These are typically unit tests, but any test can be include in this source set as long as they all share the same compilation and runtime classpaths. The sources managed by the "test" source set are compiled by the compileTestJava task, and the tests are executed by the test task. The resources are processed by the processTestResources task. The test source set is associated with the "testCompileOnly", "testRuntimeOnly" and "testImplementation" configurations.
└─ src
└─ test
├─ java
└─ resources
Custom Source Set
New source sets can be defined, typically for one or both of the following reasons:
- The source code should be keep separate from the existing source sets for aesthetics and manageability.
- The source code requires a different, unique compilation or runtime classpaths.
- The generated code should be handled differently than the code from main and test source set.
Java Toolchain
The toolchain options protect against problems with the project being built with different Java versions.
TODO: https://docs.gradle.org/current/userguide/toolchains.html.
Component
The plugin adds a "java" software component accessible via components.java
. The JAR file produced by the jar task is the artifact associated with the Java component, and its dependencies are those of the runtime configuration.
Dependency Configurations
Tasks
compileJava
The "compileJava" task compiles the sources managed by the "main" source set. The task is backed by the JavaCompile type.
To change compiler options, configure the task as follows:
compileJava {
options.incremental = true
options.fork = true
options.failOnError = false
}
For more details, see:
compileTestJava
The "compileTestJava" task compiles the sources managed by the "test" source set. The task is backed by the JavaCompile type, and can be used to change compilation options for test compilation. The syntax is similar to the one shown above, just applied inside the "compileTestJava" script block.
processResources
The "processResources" task processes the resources managed by the main source set. The task is an implementation of the Copy type. The task will automatically copy any files in src/main/resources to a directory that will be included in the project's JAR. This target directory will also be included in the runtime classpath of the tests. For more details see:
processTestResources
The "processTestResources" task processes the resources managed by the test source set. The task is an implementation of the Copy type. For more details see:
jar
Bytecode JAR
Assembles the JAR file from the classes produced by the "main" source set source files and "main" source set resources. No configuration is needed for a standard Java project. The task produces a single JAR conventionally named:
<archiveBaseName>[-archiveAppendix]<-archiveVersion>[-archiveClassifier].<archiveExtension>
By default, that translates to:
<project>-<version>.jar
The JAR is placed in the build/libs project directory. It depends on the classes task.
No task configuration is necessary by default, but the task can be configured in build.gradle
using a jar {...}
configuration block:
jar {
manifest.attributes 'Main-Class': 'playground.Main'
}
For example, the name of the JAR can be changed through configuration, as explained in the Custom JAR Name section below. The task is backed by the Jar type, and detailed configuration documentation is available in
The plugin creates by default a "thin" JAR, which only includes the project classes. A "fat" JAR, or an uber-JAR, is a self-sufficient archive which contains both classes and dependencies needed to run an application. To create a "fat" JAR, see:
Note that Java Library plugin integrates the "jar" task with the standard lifecycle task assemble.
Also see:
JAR Customizations
Custom JAR Name
FAT JAR
Source JAR
TODO.
javadoc
Generates Javadoc for the "main" source set classes.
test
The "test" task runs all the tests from the "test" source set (src/test/java). Note that Java Library plugin integrates the "test" task with the standard lifecycle task check. For more details, see:
testClasses
classes
Lifecycle Tasks
Are these introduced by the Java plugin or they're also inherited?
buildDependents
buildNeeded
Inherited Tasks
The following tasks are lifecycle tasks inherited from the Base plugin.
assemble
Standard lifecycle task, inherited from the Base plugin. For the Java plugin, the 'assemble' task compiles the code and builds the JAR but does not run the tests. Other plugins, such as the War Plugin, add more artifacts to this task. More details:
build
Standard lifecycle task:
check
Standard lifecycle task:
clean
Java Plugin Predefined Task Types
JavaCompile
JavaCompile exposed as "compileJava" task
Jar
JavaExec
Properties
The Java plugin adds a number of properties to your project. These properties have default values which are usually sufficient to get started.
sourceCompatibility
'sourceCompatibility' defines the language version of the source code. See Use a Specific Java Version below.
targetCompatibility
'targetCompatibility' defines the minimum JVM version the code should be run on (the version of the bytecode the compiler generates). See Use a Specific Java Version below.
Customization
Various aspects related to Java compilation are set in the "java" script block:
java {
toolchain {
languageVersion = JavaLanguageVersion.of(11)
}
}
Use a Specific Java Version
By default, Gradle will compile Java code to the language level of the JVM running Gradle. Since version 8, the Java compiler can be configured to produce bytecode for an older Java version, while making sure the code does not use any APIs from a more recent version.
This can be changed with the usage of Java toolchains.
java {
toolchain {
languageVersion = JavaLanguageVersion.of(11)
}
}
The level can be changed at task level:
compileJava {
options.release = 11
}
The legacy way to configure this is to set the "sourceCompatibility" and "targetCompatibility" properties at the top level of build.gradle file:
sourceCompatibility = 15
targetCompatibility = 11
If the toolchain is used, that makes it illegal to use sourceCompatibility and targetCompatibility. The target compatibility level reflects in the generated classes bytecode version. For more details, see:
Compiler Options Customization
Compiler options can be configured in the compileJava and compileTestJava tasks, as shown above.
Source Set Customization
Custom Source Directories
The source directories for both main and test source sets can be reconfigured as follows (the example only shows main, test is similar):
sourceSets {
main {
java {
srcDirs = ['src/somethingelse/java']
}
}
}
To add directories, use this syntax:
sourceSets {
main {
java {
srcDir 'src/somethingelse/java'
}
}
}
or
sourceSets.main.java.srcDirs += ['src/somethingelse/java']
It is equivalent with:
sourceSets {
main {
java {
srcDirs = ['src/main/java', 'src/somethingelse/java']
}
}
}
Custom Resource Directories
sourceSets {
main {
resources {
srcDirs = ["src/main/resources", "src/main/configs"]
excludes = ['**/something/**']
}
}
}