Gradle Release Notes

Version 4.0-rc-1

The Gradle team is pleased to announce Gradle 4.0.

We are excited to share some great new features and improvements with you in this release:

First and foremost, Gradle's Build Cache is now production-ready for Java and Groovy compilation and Java test tasks! This is further improved by overlapping outputs detection, configurable classpath normalization that avoids unnecessary task execution, and more listed in the full release notes. The cacheability of other tasks, including other languages, will be completed in future releases.

Now on to user experience: this release has a number of enhancements in logging and terminal display. Log output is now grouped by project and task when attached to a terminal — output from tasks run in parallel will no longer be interleaved. However, logging behaves the same as previous Gradle versions in non-interactive environments, and with --console=plain , to allow automated tools like CI systems to parse the logs they expect.

The console output now shows more detail about what exactly is in-progress, and parallel work in-progress is now displayed by default. You can learn more about logging and console output in the user guide.

Speaking of parallel work-in-progress, artifacts and metadata from remote repositories are now downloaded in parallel! Gradle also avoids downloading the same dependency twice even if parallel tasks request the same one simultaneously.

Gradle Script Kotlin v0.9.0 (included in this release) brings very welcome improvements: auto-detection of Kotlin build scripts, default imports for the whole Gradle API, improved samples and docs with an API reference, better IntelliJ experience and more!

Finally, this release introduces a public type that represents lazily-evaluated properties (aka ConventionMapping ). This is one of the most-requested features by plugin authors. You can learn more about PropertyState s here. A good example of their usage can be found in the gradle-site-plugin.

We hope you will build happiness with Gradle 4.0, and we look forward to your feedback via Twitter or on GitHub.

New and noteworthy Here are the new features introduced in this Gradle release. Parallel download of dependencies Gradle will now download dependencies from remote repositories in parallel (both metadata and artifacts). It will also make sure that if you build multiple projects in parallel (with --parallel ) and that 2 projects try to download the same dependency at the same time, that dependency will not be downloaded twice. This is complemented very well by the improved console output that shows parallel downloads. Build cache improvements Remote build cache honors --offline When running with --offline , Gradle will disable the remote build cache. Detecting overlapping task outputs When two tasks write into the same directory, Gradle will now disable task output caching for the second task to execute. This prevents issues where task outputs for a different task are captured for the wrong build cache key. On subsequent builds, if overlapping outputs are detected, Gradle will also prevent you from loading task outputs from the cache if it would remove existing outputs from another task. You can diagnose overlapping task output issues by running Gradle at the --info log level. If you are using Gradle Build Scans, the same detailed reason for disabling task output caching will be included in the build timeline. Stricter validation of task properties When a plugin is built with the Java Gradle Plugin Development Plugin, custom task types declared in the plugin will go through validation. In Gradle 4.0, additional problems are now detected. A warning is shown when: a task has a property without an input or output annotation (this might indicate a forgotten input or output),

a task has @Input on a File property (instead of using @InputFile of @InputDirectory ),

on a property (instead of using of ), a task declares conflicting types for a property (say, both @InputFile and @InputDirectory ),

and ), a cacheable task declares a property without specifying @PathSensitive . In such a case, we default to ABSOLUTE path sensitivity, which will prevent the task's outputs from being shared across different users via a shared cache. For more info on using task property annotations, see the user guide chapter. Cache-safe mixed JVM language compilation In Gradle 3.5, projects that used both Java and another JVM language (like Groovy or Scala) would encounter problems when using the build cache. The class files created by multiple compilation tasks were all placed into the same output directory, which made determining the set of outputs to cache for each task difficult and would cause Gradle to cache the wrong outputs for each compilation task. Gradle now uses separate output directories for each JVM language. Automatic clean-up of local build cache By default, Gradle limits the size of the local build cache to 5GB. In Gradle 3.5, the local build cache was allowed to grow indefinitely. You can increase or decrease the size of the local build cache by configuring your local cache: buildCache { local { targetSizeInMB = 10240 } } This is a target size for the build cache. Gradle will periodically check if the local build cache has grown too large and trim it to below the target size. The least recently used build cache entries will be deleted first. Improved tracking of additional task actions When computing the build cache key for a task, Gradle takes into account all the inputs of the task. These inputs included the class name and the full classpath of the task's type since 3.0. However, Gradle was not tracking the implementation of additional actions attached to the task via doFirst and doLast . Due to this, Gradle 3.5 and before would reuse the result of the first task for the second task: task first { outputs . cacheIf { true } outputs . file file ( "first.txt" ) doFirst { file ( "first.txt" ). text = "Hello from the first task" } } task second { outputs . cacheIf { true } outputs . file file ( "second.txt" ) doFirst { file ( "second.txt" ). text = "Hello from the second task" } } Gradle 4.0 recognizes the two doFirst actions to be different, and will not reuse cached results between first and second . Public type for representing lazily evaluated properties Because Gradle's build lifecycle clearly distinguishes between configuration phase and execution phase the evaluation of property values has to be deferred under certain conditions to properly capture end user input. A typical use case is the mapping of extension properties to custom task properties as part of a plugin implementation. In the past, many plugin developers were forced to solve evaluation order problems by using the concept of convention mapping, an internal API in Gradle subject to change. This release of Gradle introduces a mutable type to the public API representing a property with state. The relevant interface is called PropertyState . An instance of this type can be created through the method Project.property(Class) . The following example demonstrates how to use the property state API to map an extension property to a custom task property without running into evaluation ordering issues: apply plugin : GreetingPlugin greeting { message = 'Hi from Gradle' outputFiles = files ( 'a.txt' , 'b.txt' ) } class GreetingPlugin implements Plugin < Project > { void apply ( Project project ) { def extension = project . extensions . create ( 'greeting' , GreetingPluginExtension , project ) project . tasks . create ( 'hello' , Greeting ) { message = extension . messageProvider outputFiles = extension . outputFiles } } } class GreetingPluginExtension { final PropertyState < String > message final ConfigurableFileCollection outputFiles GreetingPluginExtension ( Project project ) { message = project . property ( String ) setMessage ( 'Hello from GreetingPlugin' ) outputFiles = project . files () } String getMessage () { message . get () } Provider < String > getMessageProvider () { message } void setMessage ( String message ) { this . message . set ( message ) } FileCollection getOutputFiles () { outputFiles } void setOutputFiles ( FileCollection outputFiles ) { this . outputFiles . setFrom ( outputFiles ) } } class Greeting extends DefaultTask { final PropertyState < String > message = project . property ( String ) final ConfigurableFileCollection outputFiles = project . files () @ Input String getMessage () { message . get () } void setMessage ( String message ) { this . message . set ( message ) } void setMessage ( Provider < String > message ) { this . message . set ( message ) } FileCollection getOutputFiles () { outputFiles } void setOutputFiles ( FileCollection outputFiles ) { this . outputFiles . setFrom ( outputFiles ) } @ TaskAction void printMessage () { getOutputFiles (). each { it . text = getMessage () } } } Gradle 4.0 supports ignoring particular resources on a runtime classpath. This affects up-to-date checks and the calculation of build cache keys. It's common for a project to have a file that contains volatile data that frequently changes without affecting runtime behavior. This information can be used to audit artifacts, identify the CI job that published the artifact or identify when an artifact was produced. Including files like this on your runtime classpath can cause tasks like the test task to never be up-to-date or cause build cache misses since every build can have a different build cache key. It is now possible to tell Gradle about these files by configuring project level input normalization: normalization { runtimeClasspath { ignore 'build-info.properties' } } This configuration tells Gradle to ignore changes to files named build-info.properties on the runtime classpath. Please note that this will not affect the runtime classpath that the Test task will use. In other words, any test is still free to load build-info.properties as it is still available on the classpath. For more information about this feature, see the corresponding section in the user guide. Convenience method for adding Google repository A convenience method for the Google repository was added to RepositoryHandler . You can now add Google's Maven repository to your build to resolve Android Support Library dependencies instead of downloading them from the Android SDK Manager. The following example demonstrates using the new shortcut repository declaration: repositories { google () } User experience improvements Logs grouped by project and task Parallel execution causes logs from simultaneous tasks to be interleaved, rendering them less useful. Gradle 4.0 buffers output by project and task and flushes upon completion or every few seconds for long-running tasks. Default logging reduced Gradle sometimes outputs very verbose logs in mid-to-large sized projects, which makes it far too easy to miss the logs you actually want to act on. Output is nearly identical to previous releases when not attached to a terminal or using --console=plain to allow users or CI systems to parse logs as they always have. We recommend the use of build scans, --info , or a plain console for granular task outcomes information. Parallel console The terminal display of work in-progress now shows parallel work by default, and will adjust to parallel tasks added, growing as needed up to one-half the height of the attached console. This is not displayed in non-interactive environments. Better modeling of tasks that delete files A task can now annotate properties with @Destroys to explicitly model that a task deletes a file or collection of files. class RemoveTempDirs extends DefaultTask { @ Destroys FileCollection tempDirs @ TaskAction void removeDirs () { project . delete ( tempDirs ) } } A task can also programmatically declare files it will delete using the API on Task.getDestroyables() . By explicitly modeling the files that a task deletes, this allows Gradle to take this information into account when selecting tasks to execute from the task graph while running with --parallel . Gradle can use this information to avoid starting a deletion task when: A task is currently running that creates the same files as the deletion task would remove.

A task has created a set of files that the deletion task would remove and there is another task that will consume those files but has not yet executed. Conversely, Gradle will also avoid starting tasks that create or consume a set of files while a deletion task that removes those files is currently running. The Delete task automatically uses the @Destroys annotation, so any files added via its delete() API will be safe when running in parallel. For instance, it is safe to run clean build or build clean while using --parallel now. To read more about this feature, see the userguide section on Incremental Build. Checkstyle configuration directory conventions If you use additional configuration files with Checkstyle, like suppressions.xml , these files need to be specified with an absolute path. Most projects use a variable like config_loc to build the path to these configuration files. Gradle now defines a config_loc property that can be used in your checkstyle.xml . See the user guide for more information. This change makes Checkstyle build cache friendly, so that your build does not need to depend on machine-specific paths and is more likely to keep track of all inputs to the Checkstyle task. Default Zinc compiler upgraded from 0.3.7 to 0.3.13 This will take advantage of performance optimizations in the latest Zinc releases. Ivy plugin repositories support patterns and layouts Ivy plugin repositories now support the same API for patterns and layouts that Ivy artifact repositories support. Track Java version for Groovy compilation The Java version used by Groovy compilation influences the compiled Groovy and Java classes for the GroovyCompile task. Gradle now tracks changes to this version and recompiles whenever necessary. Configure log level using Gradle properties Gradle now allows you to specify the log level as a Gradle property, allowing a default log level to be set for a project, a machine, etc. See the user guide for more information.

Promoted features Promoted features are features that were incubating in previous versions of Gradle but are now supported and subject to backwards compatibility. See the User guide section on the “Feature Lifecycle” for more information. The following are the features that have been promoted in this Gradle release.

Fixed issues

Deprecations Features that have become superseded or irrelevant due to the natural evolution of Gradle become deprecated, and scheduled to be removed in the next major Gradle version (Gradle 4.0). See the User guide section on the “Feature Lifecycle” for more information. The following are the newly deprecated items in this Gradle release. If you have concerns about a deprecation, please raise it via the Gradle Forums. Setting the compiler executable is no longer deprecated In Gradle 3.5 ForkOptions.executable has been deprecated. In Gradle 4.0 it is not deprecated anymore, but using it to fork a compiler will disable task output caching for the compile task. Deprecated APIs JDepend File getClassesDir() - Use FileCollection getClassesDirs() setClassesDir(File) - Use setClassesDirs(FileCollection)

Test File getTestClassesDir() - Use FileCollection getTestClassesDirs() setTestClassesDir(File) - Use setTestClassesDirs(FileCollection)

SourceSetOutput File getClassesDir() - Use FileCollection getClassesDirs() or SourceDirectorySet.getOutputDir() setClassesDir(File) - Use SourceDirectorySet.setOutputDir(File)



Potential breaking changes Build Scan 1.7.2 or newer is required when used with Gradle 4.0 To support additional features, you must use Build Scan 1.7.2 or newer with Gradle 4.0. Multiple class directories for a single source set In projects that use multiple JVM languages (Java and Scala, Groovy and other languages) in separate source directories (e.g., src/main/groovy and src/main/java ), Gradle now uses separate output directories for each language. To return to the old behavior, explicitly set the classes directory: sourceSets . main . output . classesDir = new File ( buildDir , "classes/main" ) Please be aware that this will interfere with the effectiveness of the build cache when using multiple JVM languages in the same source set. Gradle will disable caching for tasks when it detects that multiple tasks create outputs in the same location. Location of classes in the build directory The default location of classes when using the java , groovy or scala plugin has changed from: Java : build / classes / main Groovy : build / classes / main Scala : build / classes / main Generically : build / classes / $ { sourceSet . name } to Java : build / classes / java / main Groovy : build / classes / groovy / main Scala : build / classes / scala / main Generically : build / classes / $ { sourceDirectorySet . name } / $ { sourceSet . name } Plugins, tasks or builds that used hardcoded paths may fail. You can access the specific output directory for a particular language via SourceDirectorySet#outputDir or the collection of all of the output directories with SourceSetOutput#getClassesDirs() . maven-publish and ivy-publish mirror multi-project behavior When using the java plugin, all compile and runtime dependencies will now be mapped to the compile scope, i.e. "leaked" into the consumer's compile classpath. This is in line with how these legacy configurations work in multi-project builds. We strongly encourage you to use the api (java-library plugin only), implementation and runtimeOnly configurations instead. These are mapped as expected, with api being exposed to the consumer's compile classpath and implementation and runtimeOnly only available on the consumer's runtime classpath. Memory settings not tracked as inputs for JVM compilation Previously Gradle would treat JVM compilation tasks as out-of-date whenever their memory settings changed compared to the previous execution. Since Gradle 4.0, these parameters are not treated as inputs anymore, and thus the compilation tasks will stay up-to-date when they are changed. Groovy upgraded to 2.4.11 The version of Groovy bundled with Gradle was changed from Groovy 2.4.10 to Groovy 2.4.11. This release fixes several issues where Groovy compilation could produce different (but functionally equivalent) bytecode given the same source files due to nondeterministic ordering in the compiler. These problems could cause build cache misses in Gradle 3.5 when compiling Groovy and Gradle script sources. Version of PMD has been upgraded By default, Gradle now uses PMD 5.6.1. Previously, Gradle used PMD 5.5.1. Newer versions of PMD usually bring new rules, better inspections and bug fixes. Your build may fail due to these changes. You can upgrade or downgrade the version of PMD with: pmd { toolVersion = '5.5.1' } Changes to previously deprecated APIs The JacocoPluginExtension methods getLogger() , setLogger(Logger) are removed.

methods , are removed. The JacocoTaskExtension methods getClassDumpFile() , setClassDumpFile(File) , getAgent() and setAgent(JacocoAgentJar) are removed.

methods , , and are removed. Removed constructor AccessRule(Object, Object) .

. Removed constructor ProjectDependency(String, String) and the methods getGradlePath() , setGradlePath(String) .

and the methods , . Removed constructor WbDependentModule(Object) .

. Removed constructor WbProperty(Object) .

. Removed constructor WbResource(Object) .

. Removed constructor JarDirectory(Object, Object) .

. Removed constructor Jdk(Object, Object, Object, Object) .

. Removed constructor ModuleDependency(Object, Object) .

. Moved classes RhinoWorkerHandleFactory and RhinoWorkerUtils into internal package.

and into internal package. Removed RhinoWorker .

. Removed constructor EarPluginConvention(Instantiator) .

. Removed the method registerWatchPoints(FileSystemSubset.Builder) from FileCollectionDependency .

from . Removed the method getConfiguration() from ModuleDependency .

from . Removed the method getProjectConfiguration() from ProjectDependency .

from . Removed class org.gradle.caching.BuildCache .

. Removed class org.gradle.caching.MapBasedBuildCache .

. Removed the Gradle GUI. All classes for this feature have been removed as well as all leftovers supporting class from the Open API partly removed due to deprecation in Gradle 2.0.

Removed the annotation @OrderSensitive and the method TaskInputFilePropertyBuilder.orderSensitive .

and the method . Removed dependencyCacheDir with getter and setters in java plugin, JavaPluginConvention , and CompileOptions (commit edadbed1)

with getter and setters in java plugin, , and (commit edadbed1) Removed Ant related classes AntDepend , AntDependsStaleClassCleaner , and DependOptions

Removed Javadoc#setOptions

Removed Manifest.writeTo(Writer) . Please use Manifest.writeTo(Object)

. Please use Removed TaskInputs.source() and sourceDir() . Please use TaskInputs.file().skipWhenEmpty() , files().skipWhenEmpty() and dir().skipWhenEmpty() .

and . Please use , and . Chaining calls to TaskInputs.file() , files() , dir() and TaskOutputs.file() , files() and dir() are not supported anymore.

, , and , and are not supported anymore. Removed TaskOutputs.doNotCacheIf(Spec) , use doNotCacheIf(String, Spec) instead.

, use instead. Removed ValidateTaskProperties.classesDir , use ValidateTaskProperties.classes . The deprecated jetty plugin has been removed. We recommend using the Gretty plugin for developing Java web applications. The deprecated pluginRepositories block for declaring custom plugin repositories has been removed in favor of pluginManagement.repositories . Adding copy specs is not allowed during task execution of a AbstractCopyTask task You can no longer add copy specs to a copy (like Copy and Sync ) or archive task (like Zip and Tar ) when the task is executing. Tasks that used this behavior could produce incorrect results and not honor task dependencies. Starting with Gradle 4.0, builds that rely on this behavior will fail. Previously, Gradle only failed if the task was cacheable and emitted a warning otherwise. ```groovy // This task adds a copy spec during the execution phase. task copy(type: Copy) { from ("some-dir") into ("build/output") doFirst { from ( "some-other-dir" ) { exclude "non-existent-file" } } } ``` Changes to how build cache configurations are described The (incubating) BuildCacheServiceFactory and BuildCacheService interfaces have changed in this release. This only affects custom build cache connector implementations. It does not affect usage of the build cache connectors that ship with Gradle. Previously, the BuildCacheService was responsible for providing a getDescription() method that returned a human friendly description of the cache. This responsibility has been moved to the associated BuildCacheServiceFactory implementation, that now receives a Describer parameter. The custom service factory can use this to declare the type of the service and configuration parameters that are relevant to the build cache connector being created. getDescription() has been removed. An example of the factory method used to create a custom build cache connector with a BuildCacheServiceFactory : java public class InMemoryBuildCacheServiceFactory implements BuildCacheServiceFactory<InMemoryBuildCache> { @Override public BuildCacheService createBuildCacheService(InMemoryBuildCache config, Describer describer) { int maxSize = config.getMaxSize(); describer.type("in-memory").config("size", String.valueOf(maxSize)); return new InMemoryBuildCacheService(maxSize); } } Changes to IDE plugins New constructor parameter for EclipsePlugin and IdeaPlugin . Note that these types are not designed to be directly instantiated.

and . Note that these types are not designed to be directly instantiated. Deprecated EclipsePlugin.performPostEvaluationActions() and IdeaPlugin.performPostEvaluationActions() . Post-evaluation actions are no longer used. Changes to dependency ordering Several changes have been made to the way that Gradle orders files in the dependency resolution results: Files are now ordered in 'consumer first' order. That means that a particular file appears in the result before all of its dependencies. The order is unspecified in the case of a cycle in the dependency graph.

File dependencies, such as gradleApi() are now ordered in the same way as other dependencies, in consumer first order. In previous Gradle versions these dependencies were always added at the start of the result. Beyond this, Gradle does not make any other guarantees about the ordering of files. However, file order is always the same for a given dependency graph.