Introduction:

This article is based on the Gradle document, the length is long, please read as needed

Gradle overview

Gradle is an open source build automation tool that focuses on flexibility and performance. Build scripts are typically written in Groovy or KotlinDSL. This article uses Groovy only

Gradle features:

  • A high performance

Gradle avoids unnecessary work by running only the tasks that need to be run. The build cache can be used to reuse the output of previously run tasks, or even with other machines that have shared build caches.

  • The JVM based

Gradle runs on the JVM. Users familiar with Java can use standard Java apis in their build logic, such as custom task types and plug-ins. This makes It easier for Gradle to cross platform. (Gradle is not limited to building JVM projects, it even comes with support for building native projects.)

  • The constraint

Like Maven, Gradle implements constraints to make common types of projects (such as Java projects) easy to build. With the right plug-ins, you can easily use lean build scripts for many projects. But these conventions don’t limit you: Gradle allows you to override them, add your own tasks, and do many other custom operations on convention-based builds.

  • scalability

You can easily extend Gradle to provide your own task types and even build models.

  • IDE support

Supported ides: Android Studio, IntelliJ IDEA, Eclipse and NetBeans. Gradle also supports the generation of solution files needed to load projects into Visual Studio.

  • Can be insightful

Build scans provide extensive information about build runs that can be used to identify build problems. They are particularly good at helping you determine build performance issues. You can also share build scans with others, which is especially useful if you need to consult to solve build problems.

Five things you need to know about Gradle

This section is mentioned repeatedly in the official documentation. I have outlined it briefly, which can be seen in the Gradle documentation

Gradle is a universal build tool

Gradle allows you to build any software because it doesn’t care about your specific work.

2. The core model is task-based

Gradle models its build model as a directed acyclic graph (DAG) of tasks (units of work). This means that the build essentially configures a set of tasks and wires them together based on their dependencies to create the DAG. After the task diagram is created, Gradle determines the tasks that need to be run in sequence and then proceeds to execute them.

The task itself consists of the following parts, which are linked together by dependencies:

  • Action – The work of doing something, such as copying a file or compiling source code
  • Input – Operations Values, files, and directories used or operated on
  • Output – Operation modified or generated files and directories

3. Gradle has several fixed build phases

It is important to understand that Gradle evaluates and executes build scripts in three stages:

  • Initialize the

Set up the build environment and determine which projects will participate.

  • configuration

Construct and configure the built task graph, and then determine which tasks need to run and in what order, based on the tasks the user wants to run.

  • perform

Run the tasks selected at the end of the configuration phase.

These phases make up Gradle’s build life cycle.

4. Gradle extends in more than one way

Gradle’s bundled build logic will not work for every build. Most builds have special requirements that require you to add custom build logic. Gradle provides several mechanisms to extend it, such as:

  • User-defined task types.
  • Custom task actions.
  • Additional properties for projects and tasks.
  • Custom constraints.
  • Custom Module.

5. The build script runs against the API

Gradle’s build scripts can be thought of as executable code, but well-designed build scripts describe what steps are required to build software, regardless of how those steps should get the job done.

Because Gradle runs on the JVM, build scripts can also use standard Java apis. Groovy build scripts can use the Groovy API separately, and Kotlin build scripts can use Kotlin.

The life cycle of a feature

A function can be in one of four states:

  • Internal: Internal functions without interfaces
  • Incubating: incubation function. It will continue to change before becoming a public feature
  • Public: Public functions that can be used safely
  • Deprecated: Deprecated feature that will be removed in the future

Gradle installation

Install the JDK

There is too much information about installing the JDK to cover in detail in this article. You can use the command to check whether your computer is successfully installed

Install the Gradle

Install Gradle with a software package

SDKMAN

sdk install gradle
Copy the code

Homebrew

brew install gradle
Copy the code

Manual installation (recommended)

download

Services.gradle.org/distributio… Address (full version catalogue, you can view the latest version) services.gradle.org/distributio… (Up to 2021.02.24)

The file is introduced

Zip gradle-6.8.3-all. Zip gradle-6.8.3-all. Zip gradle-6.8.3-allCopy the code
Bin: run file lib: dependent library docs: document SRC: source file init.d: initialization script directory, which can be added by yourselfCopy the code

Configuring environment Variables

Export GRADLE_HOME = / Users/DXS/temp/gradle - 6.8.3 export PATH = $PATH: $GRADLE_HOME/binCopy the code

run

Type gradle -v to check whether the configuration is successful

HelloWord

To write a build.gradle file, type the following

task hello{
    doLast {
        println 'Hello World'
    }
}
Copy the code

Run gradle -q hello

Version management

  • Update from 4.x to 5.0
  • Update from 5.x to 6.0
  • Update from 6.x to latest

The program

  • Migrate projects from Maven to Gradle
  • Migrate projects from Ant to Gradle

Gradle Wrapper

define

Gradle Wrapper is a script that calls a declared version of Gradle and is pre-downloaded if necessary. As a result, developers can quickly get Gradle projects up and running without having to follow a manual installation process

To add a wrapper

The gradle Wrapper directory can be generated using the command gradle Wrapper in the build.gradle directory

gradle wrapper
Copy the code

  • gradle-wrapper.jar

    WrapJAR file that contains the code to download the Gradle distribution.

  • gradle-wrapper.properties

    A properties file for configuring the Wrapper runtime behavior, such as the Gradle version compatible with that version. Note that more general Settings (for example, configuring Wrap to use a proxy) require access to other files.

  • Gradlew, gradlew. Bat

    A shell script and a Windows batch script to perform the build using the Wrap program.

Build options can be controlled by command

--gradle-version Gradle version used to download and execute the Wrap program. --distribution-type Gradle distribution type used by Wrap. The available options are bin and all. The default value is bin. Gradle-distribution-url Points to the full URL of the gradle distribution-zip file. With this option, --gradle-version and -- distribution-type outdated urls already contain this information. This option is valuable if you want to host Gradle distributions within your corporate network. --gradle-distribution-sha256-sum Sha256 hash and gradle distribution used to verify downloads.Copy the code

Ex. :

Gradle wrapper --gradle-version 6.8.3 --distribution-type allCopy the code

Wrapper property file

Gradle-wrapper.properties is the usual result of generating a Wrapper

distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.3-bin.zip zipStoreBase = GRADLE_USER_HOME zipStorePath=wrapper/distsCopy the code

GRADLE_USER_HOME is your environment variable. If not configured, the default is the. Gradle folder in the user directory

  • DistributionBase The home directory where the downloaded Gradle compressed package is stored after it is decompressed
  • DistributionPath Path to the decompressed Gradle package relative to distributionBase
  • ZipStoreBase is the same as the distributionBase, but it is used to store zip packages
  • ZipStorePath is the same as distributionPath, but it is used to store zip packages
  • DistributionUrl Specifies the download address of the Gradle distribution zip

Build with a Wrapper

Run the following command under gradlew: Windows:

gradlew.bat build
Copy the code

Shell:

./gradlew build
Copy the code

upgrade

  • Change the distributionUrl property in the gradle-wrapper.properties file
  • Use the gradlew wrap –gradle-version command
. / gradlew wrap - gradle - version 6.8.3Copy the code

Custom Gradle_Wrap

You can use custom wrappers to eliminate duplication or custom functionality, such as

build.gradle

tasks.named('wrapper') { distributionType = Wrapper.DistributionType.ALL } task wrapper(type: Wrapper) {gradleVersion = '6.8.3'}Copy the code

Gradle environment

The environment variable

GRADLE_OPTS

Specifies the JVM parameters to use when starting the Gradle client VM. The client VM only handles command line input/output, so it rarely needs to change its VM options. The actual build is run by the Gradle daemon and is not affected by this environment variable.Copy the code

GRADLE_USER_HOME

Specifies the Gradle user's home directory ($USER_HOME/.gradle by default if not set).Copy the code

JAVA_HOME

Specify the JDK installation directory to use on the client VM. This virtual machine is also used for daemons unless the Gradle property file specifies another virtual machine using org.gradle.java.home.Copy the code

Note: Command line options and system properties take precedence over environment variables.

Gradle properties

You can configure your project properties by themselves, and if there are more than one, they will be read from top to bottom first:

  • System properties, such as on the command line-Dgradle.user.home
  • GRADLE_USER_HOME gradle.properties in the GRADLE_USER_HOME directory
  • Gradle.properties in the project root directory
  • Gradle.properties in the Gradle installation directory

gradle.properties

# When set to true, Gradle will reuse the output of any previously built task if possible, making builds faster org.gradle.caching=true # When set to true, individual input property hashes and build cache keys for each task are recorded on the console. Org.gradle.caching. Debug =true # Enable incubation on demand configuration, Gradle will try to configure only the necessary items. Org. Gradle. Configureondemand = true # custom color or detail of the console output. The default value depends on how Gradle is called. Optional (auto,plain,rich,verbose) org.gradle.console=auto # When setting true to gradle daemon to run the build. The default value is true. Gradle daemon=true # The gradle daemon will terminate after the specified number of idle milliseconds. The default value is 10800000 (3 hours). Daemon. Org. Gradle. Idletimeout = 10800000 # set true too, under the condition of gradle will enable remote debugging running builds, listen port 5005. Note that this is equivalent to adding -agentlib: JDWP =transport=dt_socket,server=y,suspend=y,address=5005 to the JVM command line and will suspend the virtual machine until the debugger is connected. The default value is false. Org.gradle.debug =true # Specifies the Java home page for the Gradle build process. You can set the value to a JDK or JRE location, but depending on how you build, it's safer to use the JDK. # If no setting is specified, derive reasonable defaults from your environment (JAVA_HOME or the path Java). This does not affect the Version of Java used to start the Gradle client VM (see Environment variables). Org.gradle.java. home=/usr/bin/java # Specifies JVM parameters for gradle daemons. This setting is particularly useful for configuring JVM memory Settings to improve build performance. This does not affect the JVM Settings of the Gradle client VM. Org. Gradle. Jvmargs = - Xmx2048m # when set to quiet, warn, lifecycle, info, debug, gradle will use this log level. These values are case insensitive. This Lifecycle level is the default level. # optional (quiet, warn, lifecycle, info, the debug) org. Gradle. Logging. The level after # = the debug configuration, Gradle bifurcation to org. Gradle. Workers. MaxJVM to parallel execution project org. Gradle. The parallel = true # specified Gradle daemon and start all process scheduling priority. The default value is Normal. (low,normal) org.gradle.priority=normal # Configure detailed logging when monitoring file systems. The default value is disabled. Org.gradle.vvfs. Verbose =true # Toggle to view the file system. Allows Gradle to reuse information about the file system in the next release. The default value is disabled. Watch =true # When set to all, summary or None, Gradle uses a different warning type of display. (all,fail,summary, None) org.gradle.warning.mode=all # After configuration, Gradle will use up to a given number of workers. The default value is number of CPU processors. org.gradle.workers.max=5Copy the code

System property

# specify a user name to use HTTP basic authentication from the server to download Gradle distributions systemProp. Gradle. WrapperUser = myuser # specified using Gradle Wrapper download Gradle distributions of the password SystemProp. Gradle. WrapperPassword = mypassword # specified gradle systemProp user's home directory. The gradle. User. Home = (the path to the directory)Copy the code

The project properties

org.gradle.project.foo = bar
Copy the code

A daemon

Gradle runs on a Java Virtual machine (JVM) and uses supporting libraries that require a very short initialization time. But sometimes it starts slowly. The solution to this problem is Gradle Daemon: a long-standing background process that can perform builds faster than ever before.

You can obtain the running daemon status by running commands

IDLE means IDLE, BUSY means BUSY, STOPPED means closed

Daemon default open, can be closed by a following properties. The gradle/gradle. Properties

org.gradle.daemon=false
Copy the code

You can also manually shut down the daemon with the gradle –stop command

Gradle command line

Command line format

gradle [taskName ...]  [--option-name ...]Copy the code

If multiple tasks are specified, they should be separated by Spaces.

It is recommended to specify = between options and parameters.

--console=plain
Copy the code

The option to enable behavior has a long-form option with the inverse function –no- specified. Here’s the opposite.

--build-cache
--no-build-cache
Copy the code

Many commands have abbreviations. For example, the following command is equivalent:

--help
-h
Copy the code

Gradle should be replaced with./gradlew or gradlew. Bat when using Wrapper

Gradle -? Gradle -h gradle -help # Displays a list of subprojects of the selected project in a hierarchical structure. Gradle help - Task # In a Gradle build, the usual 'build' task is specified to assemble all the output and run all the checks. Gradle Build # performs all validation tasks (including test and linting). Assemble gradle startCmd == gradle sc # Gradle dist -- excide-task test # Enforce gradle test -- Rerun-tasks # Continuously Build # gradle test --continue # Build scan provides a complete visual report of which dependencies are present in which configurations, transitable dependencies, and dependency version selection. $gradle myTask $gradle dependenciesCopy the code

For more command lines, see Command Line Options

Projects and Tasks

Everything in Gradle sits on top of two basic concepts:

  • Projects: Every Gradle build consists of one or more projects. What a project represents depends on what you are doing with Gradle. For example, a projects might represent a JAR library or a Web application.
  • Tasks: Each project consists of one or more tasks. Tasks represent some of the atomic work performed by the build. This might be compiling some classes, creating jars, generating Javadoc, or publishing some archives to the repository.

project

Table. Item properties

The name of the type The default value
project Project The Project instance
name String The name of the project directory.
path String The absolute path to the project.
description String Project description.
projectDir File The directory containing the build script.
buildDir File projectDir /build
group Object unspecified
version Object unspecified
ant ant build An instance of AntBuilder

task

Define the task

  1. Define a task using a string as the task name
  2. Use the Tasks container to define tasks
  3. Define tasks using DSL-specific syntax

Example: the build. Gradle

Task ('hello') {doLast {println "hello"}} tasks.create('hello') {doLast { Println "hello"}} task(hello) {doLast {println "hello"}} task('copy', type: Copy) { from(file('srcDir')) into(buildDir) }Copy the code

To locate

  • Access tasks using DSL-specific syntax
  • Access tasks through task sets
  • Access by path
  • Access tasks by task type
task hello task copy(type: Copy) // Access the task using DSL-specific syntax println hello.name println project.hello.name println copy.destinationDir println Project. Copy. DestinationDir / / by task set access tasks println tasks. Hello. The name println tasks, named (' hello '). The get (). The name println Tasks. Copy. DestinationDir println tasks. Named (' copy '). The get () destinationDir / / task by task type access tasks. WithType (Tar). ConfigureEach  { enabled = false } task test { dependsOn tasks.withType(Copy) }Copy the code

Access by path

project-a / build.gradle

task hello
Copy the code

build.gradle

task hello

println tasks.getByPath('hello').path
println tasks.getByPath(':hello').path
println tasks.getByPath('project-a:hello').path
println tasks.getByPath(':project-a:hello').path
Copy the code

Configuration tasks

Configure tasks using the API

Example: the build. Gradle

Copy myCopy = tasks.getByName("myCopy")
myCopy.from 'resources'
myCopy.into 'target'
myCopy.include('**/*.txt', '**/*.xml', '**/*.properties')
Copy the code

Configure tasks using DSL-specific syntax

Example: the build. Gradle

// Configure task using Groovy dynamic task configuration block
myCopy {
   from 'resources'
   into 'target'
}
myCopy.include('**/*.txt', '**/*.xml', '**/*.properties')
Copy the code

Define a task with a configuration block

Example: the build. Gradle

task copy(type: Copy) {
   from 'resources'
   into 'target'
   include('**/*.txt', '**/*.xml', '**/*.properties')
}
Copy the code

Pass the parameters to the task constructor

Instead of configuring mutable properties after a Task is created, you can pass parameter values to the constructor of the Task class. To pass the value to the Task constructor, you must annotate the relevant constructor with @javax.inject.Inject.

Start by creating a task class with the @Inject constructor

class CustomTask extends DefaultTask {
    final String message
    final int number

    @Inject
    CustomTask(String message, int number) {
        this.message = message
        this.number = number
    }
}
Copy the code

Then create a task and pass the constructor arguments at the end of the argument list.

tasks.create('myTask', CustomTask, 'hello', 42)
Copy the code

You can also use Map to create tasks with constructor parameters

task myTask(type: CustomTask, constructorArgs: ['hello', 42])
Copy the code

Add dependencies to tasks

Add a dependency on a task from another project

project('project-a') {
    task taskX {
        dependsOn ':project-b:taskY'
        doLast {
            println 'taskX'
        }
    }
}

project('project-b') {
    task taskY {
        doLast {
            println 'taskY'
        }
    }
}
Copy the code

Use task objects to add dependencies

task taskX {

    doLast {

        println 'taskX'

    }

}



task taskY {

    doLast {

        println 'taskY'

    }

}



taskX.dependsOn taskY
Copy the code

Use lazy blocks to add dependencies

task taskX {
    doLast {
        println 'taskX'
    }
}

// Using a Groovy Closure
taskX.dependsOn {
    tasks.findAll { task -> task.name.startsWith('lib') }
}

task lib1 {
    doLast {
        println 'lib1'
    }
}

task lib2 {
    doLast {
        println 'lib2'
    }
}

task notALib {
    doLast {
        println 'notALib'
    }
}
Copy the code

Task scheduling

There are two ways to control task sequencing:

  • Must run after: must run after
  • Should run after: Should run after

case

task taskX {
    doLast {
        println 'taskX'
    }
}
task taskY {
    doLast {
        println 'taskY'
    }
}
taskY.mustRunAfter taskX
Copy the code

Should run after

  • Introduce sorting cycles.
  • With parallel execution, all dependencies of a task are satisfied except for the “should run after “task,

Introduce the sorting cycle example

task taskX {
    doLast {
        println 'taskX'
    }
}
task taskY {
    doLast {
        println 'taskY'
    }
}
task taskZ {
    doLast {
        println 'taskZ'
    }
}
taskX.dependsOn taskY
taskY.dependsOn taskZ
taskZ.shouldRunAfter taskX
Copy the code

Add a description for the task

You can add a description to the task. This description is displayed when gradle Tasks is executed.

build.gradle

task copy(type: Copy) {
   description 'Copies the resource directory to the target directory.'
   from 'resources'
   into 'target'
   include('**/*.txt', '**/*.xml', '**/*.properties')
}
Copy the code

Skip the task

OnlyIf skip

hello.onlyIf { ! Project.hasproperty ('skipHello')} //StopExecutionException skips compile.dofirst {if (true) {throw new StopExecutionException() } }Copy the code

Disable tasks

task disableMe {
    doLast {
        println 'This should not be printed if the task is disabled.'
    }
}
disableMe.enabled = false
Copy the code

Mission timeouts

task hangingTask() {
    doLast {
        Thread.sleep(100000)
    }
    timeout = Duration.ofMillis(500)
}
Copy the code

Task rules

Sometimes you want to perform a task whose behavior depends on a large or infinite number of parameter values. A good way to provide such tasks is with task rules:

Task rules

tasks.addRule("Pattern: ping<ID>") { String taskName ->
    if (taskName.startsWith("ping")) {
        task(taskName) {
            doLast {
                println "Pinging: " + (taskName - 'ping')
            }
        }
    }
}

task groupPing {
    dependsOn pingServer1, pingServer2
}
Copy the code
> gradle -q groupPing Ping: Server1 Ping: Server2Copy the code

Finalizer task

When you plan to run a terminating task, the terminating task is automatically added to the task diagram. The finalizer task is executed even if completion fails.

task taskX {
    doLast {
        println 'taskX'
    }
}
task taskY {
    doLast {
        println 'taskY'
    }
}
taskX.finalizedBy taskY
Copy the code
> gradle -q taskX

TaskX
TaskY
Copy the code

Dynamic task

Groovy or Kotlin’s capabilities can be used to define functionality beyond tasks. For example, you can also use it to create tasks on the fly.

build.gradle

4.times { counter ->
    task "task$counter" {
        doLast {
            println "I'm task number $counter"
        }
    }
}
Copy the code

Gradle -q task1 Output

> gradle -q task1
I'm task number 1
Copy the code

Groovy_DSL shortcut symbol

Access tasks have a convenient representation. Each task can be used as an attribute of the build script:

As a property access task for the build script

build.gradle

task hello { doLast { println 'Hello world! ' } } hello.doLast { println "Greetings from the $hello.name task." }Copy the code

Output gradle -q hello

> gradle -q hello
Hello world!
Greetings from the hello task.
Copy the code

This enables very readable code, especially when using tasks provided by plug-ins, such as the Compile task.

Additional task attributes

You can add your own properties to the task. To add a property named myProperty, set ext.myProperty to the initial value. From then on, properties can be read and set like predefined task properties.

build.gradle

task myTask {
    ext.myProperty = "myValue"
}

task printTaskProperties {
    doLast {
        println myTask.myProperty
    }
}
Copy the code

Output gradle -q printTaskProperties

> gradle -q printTaskProperties
myValue
Copy the code

Additional attributes are not limited to tasks. You can read more about them in the Extra properties.

The default task

Gradle allows you to define one or more default tasks.

build.gradle

defaultTasks 'clean', 'run' task clean { doLast { println 'Default Cleaning! ' } } task run { doLast { println 'Default Running! ' } } task other { doLast { println "I'm not a default task!" }}Copy the code

Output gradle – q

> gradle -q
Default Cleaning!
Default Running!
Copy the code

This is equivalent to running Gradle Clean Run. In a multi-project build, each subproject can have its own specific default task. If the child project does not specify a default task, the parent project’s default task, if defined, is used.

Groovy based

The basic rule

  • No semicolon
  • The method parentheses can be omitted
  • Method can not write return, return the last line of code
  • Blocks of code can be passed as arguments

define

def param = 'hello world'
def param1 = "hello world"
println "${param1} ,li" 
Copy the code

${} can be a variable or an expression. Only double quotation marks can be used

Declare a variable

You can declare two kinds of variables in your build script: local variables and extra attributes.

A local variable

Local variables are declared with the def keyword. They are visible only within the scope in which they are declared. Local variables are a feature of the basic Groovy language.

def dest = "dest"
task copy(type: Copy) {
    from "source"
    into dest
}
Copy the code

Ext properties

All enhanced objects in Gradle’s domain model can hold additional user-defined properties.

You can add, read, and set additional properties by owning the ext property of the object. You can use an Ext block to add multiple attributes at once.

Plugins {id 'Java'} ext {springVersion = "3.1.0.release" emailNotification = "[email protected]"} sourcesets. all {plugins {id 'Java'} ext {springVersion = "3.1.0.release" emailNotification = "[email protected]"} sourceSets. ext.purpose = null } sourceSets { main { purpose = "production" } test { purpose = "test" } plugin { purpose = "production" } } task printProperties { doLast { println springVersion println emailNotification sourceSets.matching { it.purpose == "production" }.each { println it.name } } }Copy the code

Output gradle -q printProperties

> gradle -q printProperties
3.1.0.RELEASE
[email protected]
main
plugin
Copy the code

Variable scope: local and script scope

Variables declared with type modifiers are visible in closures, but not in methods.

String localScope1 = 'localScope1'
def localScope2 = 'localScope2'
scriptScope = 'scriptScope'

println localScope1
println localScope2
println scriptScope

closure = {
    println localScope1
    println localScope2
    println scriptScope
}

def method() {
    try {
        localScope1
    } catch (MissingPropertyException e) {
        println 'localScope1NotAvailable'
    }
    try {
        localScope2
    } catch(MissingPropertyException e) {
        println 'localScope2NotAvailable'
    }
    println scriptScope
}

closure.call()
method()
Copy the code

Output groovy scope. Groovy

> groovy scope1 localScope2 scriptScope localScope1 localScope2 scriptScope localScope1NotAvailable localScope2NotAvailable scriptScopeCopy the code

object

Using the object

You can configure any object in the following easy-to-read way.

build.gradle

import java.text.FieldPosition

task configure {
    doLast {
        def pos = configure(new FieldPosition(10)) {
            beginIndex = 1
            endIndex = 5
        }
        println pos.beginIndex
        println pos.endIndex
    }
}
Copy the code
> gradle -q configure
1
5
Copy the code

Use external scripts to configure arbitrary objects

You can also configure arbitrary objects using external scripts.

build.gradle

task configure {
    doLast {
        def pos = new java.text.FieldPosition(10)
        // Apply the script
        apply from: 'other.gradle', to: pos
        println pos.beginIndex
        println pos.endIndex
    }
}
Copy the code

other.gradle

// Set properties.
beginIndex = 1
endIndex = 5
Copy the code

Output gradle -q configure

> gradle -q configure
1
5
Copy the code

Attribute accessor

Groovy automatically translates property references into calls to the appropriate getter or setter methods.

build.gradle

// Using a getter method
println project.buildDir
println getProject().getBuildDir()

// Using a setter method
project.buildDir = 'target'
getProject().setBuildDir('target')
Copy the code

closure

Closures (close blocks of code that can reference variables passed in)

task testClosure {
    doLast {
        func {
            println it
        }
        funa { a, b ->
            println a + b
        }
    }
}

def funa(closure) {
    closure(10, 3)
}

def func(closure) {
    closure(10)
}
Copy the code

Commissioned by the closure

Each closure has a delegate object, which Groovy uses to find variable and method references that are not local variables or parameters of the closure.

Example. Closure delegate

class Info { int id; String code; def log() { println("code:${code}; ${id}")}} def info(Closure< info > Closure) {info p = new info() Closure. Delegate = p closure.setResolveStrategy(Closure.DELEGATE_FIRST) closure(p) } task configClosure { doLast { info { code = "cix" id = 1  log() } } }Copy the code

The output

> Task :configClosure code:cix; id:1 BUILD SUCCESSFUL in 276msCopy the code

Example: Set dependencies using mandatory delegates

Dependencies {assert delegate == project.dependencies testImplementation('junit:junit:4.13') Delegate. TestImplementation (' junit: junit: 4.13 ')}Copy the code

methods

Optional parentheses on method calls

Parentheses are optional for method calls.

build.gradle

test.systemProperty 'some.prop', 'value'
test.systemProperty('some.prop', 'value')
Copy the code

Closure as the last parameter in the method

When the last argument to a method is a closure, we can place the closure after the method call:

build.gradle

repositories {
    println "in a closure"
}
repositories() { println "in a closure" }
repositories({ println "in a closure" })
Copy the code

A collection of

List

Def list = [1,2,3,4] println list[0] // 1 println list[-1] // 4 last println list[-2] // 3 penultimate println list[0..2] // List. Each {// iteration println it}Copy the code

Map

def map= ['name':'li', 'age':18] println map[name] // li println map.age // 18 list.each {// iteration println "${it.Copy the code

JavaBean

class A{ private int a; Public int getB(){public int getB(){public int getB(){public int getB(){public int getB(){Copy the code

build.gradle

// List literal
test.includes = ['org/gradle/api/**', 'org/gradle/internal/**']

List<String> list = new ArrayList<String>()
list.add('org/gradle/api/**')
list.add('org/gradle/internal/**')
test.includes = list

// Map literal.
Map<String, String> map = [key1:'value1', key2: 'value2']

// Groovy will coerce named arguments
// into a single map argument
apply plugin: 'java'
Copy the code

The default import

To make the build script more concise, Gradle automatically adds classes to the Gradle script.

import org.gradle.*
import org.gradle.api.*
import org.gradle.api.artifacts.*
import org.gradle.api.artifacts.component.*
import org.gradle.api.artifacts.dsl.*
import org.gradle.api.artifacts.ivy.*
import org.gradle.api.artifacts.maven.*
import org.gradle.api.artifacts.query.*
import org.gradle.api.artifacts.repositories.*
import org.gradle.api.artifacts.result.*
import org.gradle.api.artifacts.transform.*
import org.gradle.api.artifacts.type.*
import org.gradle.api.artifacts.verification.*
import org.gradle.api.attributes.*
import org.gradle.api.attributes.java.*
import org.gradle.api.capabilities.*
import org.gradle.api.component.*
import org.gradle.api.credentials.*
import org.gradle.api.distribution.*
import org.gradle.api.distribution.plugins.*
import org.gradle.api.execution.*
import org.gradle.api.file.*
import org.gradle.api.initialization.*
import org.gradle.api.initialization.definition.*
import org.gradle.api.initialization.dsl.*
import org.gradle.api.invocation.*
import org.gradle.api.java.archives.*
import org.gradle.api.jvm.*
import org.gradle.api.logging.*
import org.gradle.api.logging.configuration.*
import org.gradle.api.model.*
import org.gradle.api.plugins.*
import org.gradle.api.plugins.antlr.*
import org.gradle.api.plugins.quality.*
import org.gradle.api.plugins.scala.*
import org.gradle.api.provider.*
import org.gradle.api.publish.*
import org.gradle.api.publish.ivy.*
import org.gradle.api.publish.ivy.plugins.*
import org.gradle.api.publish.ivy.tasks.*
import org.gradle.api.publish.maven.*
import org.gradle.api.publish.maven.plugins.*
import org.gradle.api.publish.maven.tasks.*
import org.gradle.api.publish.plugins.*
import org.gradle.api.publish.tasks.*
import org.gradle.api.reflect.*
import org.gradle.api.reporting.*
import org.gradle.api.reporting.components.*
import org.gradle.api.reporting.dependencies.*
import org.gradle.api.reporting.dependents.*
import org.gradle.api.reporting.model.*
import org.gradle.api.reporting.plugins.*
import org.gradle.api.resources.*
import org.gradle.api.services.*
import org.gradle.api.specs.*
import org.gradle.api.tasks.*
import org.gradle.api.tasks.ant.*
import org.gradle.api.tasks.application.*
import org.gradle.api.tasks.bundling.*
import org.gradle.api.tasks.compile.*
import org.gradle.api.tasks.diagnostics.*
import org.gradle.api.tasks.incremental.*
import org.gradle.api.tasks.javadoc.*
import org.gradle.api.tasks.options.*
import org.gradle.api.tasks.scala.*
import org.gradle.api.tasks.testing.*
import org.gradle.api.tasks.testing.junit.*
import org.gradle.api.tasks.testing.junitplatform.*
import org.gradle.api.tasks.testing.testng.*
import org.gradle.api.tasks.util.*
import org.gradle.api.tasks.wrapper.*
import org.gradle.authentication.*
import org.gradle.authentication.aws.*
import org.gradle.authentication.http.*
import org.gradle.build.event.*
import org.gradle.buildinit.plugins.*
import org.gradle.buildinit.tasks.*
import org.gradle.caching.*
import org.gradle.caching.configuration.*
import org.gradle.caching.http.*
import org.gradle.caching.local.*
import org.gradle.concurrent.*
import org.gradle.external.javadoc.*
import org.gradle.ide.visualstudio.*
import org.gradle.ide.visualstudio.plugins.*
import org.gradle.ide.visualstudio.tasks.*
import org.gradle.ide.xcode.*
import org.gradle.ide.xcode.plugins.*
import org.gradle.ide.xcode.tasks.*
import org.gradle.ivy.*
import org.gradle.jvm.*
import org.gradle.jvm.application.scripts.*
import org.gradle.jvm.application.tasks.*
import org.gradle.jvm.platform.*
import org.gradle.jvm.plugins.*
import org.gradle.jvm.tasks.*
import org.gradle.jvm.tasks.api.*
import org.gradle.jvm.test.*
import org.gradle.jvm.toolchain.*
import org.gradle.language.*
import org.gradle.language.assembler.*
import org.gradle.language.assembler.plugins.*
import org.gradle.language.assembler.tasks.*
import org.gradle.language.base.*
import org.gradle.language.base.artifact.*
import org.gradle.language.base.compile.*
import org.gradle.language.base.plugins.*
import org.gradle.language.base.sources.*
import org.gradle.language.c.*
import org.gradle.language.c.plugins.*
import org.gradle.language.c.tasks.*
import org.gradle.language.coffeescript.*
import org.gradle.language.cpp.*
import org.gradle.language.cpp.plugins.*
import org.gradle.language.cpp.tasks.*
import org.gradle.language.java.*
import org.gradle.language.java.artifact.*
import org.gradle.language.java.plugins.*
import org.gradle.language.java.tasks.*
import org.gradle.language.javascript.*
import org.gradle.language.jvm.*
import org.gradle.language.jvm.plugins.*
import org.gradle.language.jvm.tasks.*
import org.gradle.language.nativeplatform.*
import org.gradle.language.nativeplatform.tasks.*
import org.gradle.language.objectivec.*
import org.gradle.language.objectivec.plugins.*
import org.gradle.language.objectivec.tasks.*
import org.gradle.language.objectivecpp.*
import org.gradle.language.objectivecpp.plugins.*
import org.gradle.language.objectivecpp.tasks.*
import org.gradle.language.plugins.*
import org.gradle.language.rc.*
import org.gradle.language.rc.plugins.*
import org.gradle.language.rc.tasks.*
import org.gradle.language.routes.*
import org.gradle.language.scala.*
import org.gradle.language.scala.plugins.*
import org.gradle.language.scala.tasks.*
import org.gradle.language.scala.toolchain.*
import org.gradle.language.swift.*
import org.gradle.language.swift.plugins.*
import org.gradle.language.swift.tasks.*
import org.gradle.language.twirl.*
import org.gradle.maven.*
import org.gradle.model.*
import org.gradle.nativeplatform.*
import org.gradle.nativeplatform.platform.*
import org.gradle.nativeplatform.plugins.*
import org.gradle.nativeplatform.tasks.*
import org.gradle.nativeplatform.test.*
import org.gradle.nativeplatform.test.cpp.*
import org.gradle.nativeplatform.test.cpp.plugins.*
import org.gradle.nativeplatform.test.cunit.*
import org.gradle.nativeplatform.test.cunit.plugins.*
import org.gradle.nativeplatform.test.cunit.tasks.*
import org.gradle.nativeplatform.test.googletest.*
import org.gradle.nativeplatform.test.googletest.plugins.*
import org.gradle.nativeplatform.test.plugins.*
import org.gradle.nativeplatform.test.tasks.*
import org.gradle.nativeplatform.test.xctest.*
import org.gradle.nativeplatform.test.xctest.plugins.*
import org.gradle.nativeplatform.test.xctest.tasks.*
import org.gradle.nativeplatform.toolchain.*
import org.gradle.nativeplatform.toolchain.plugins.*
import org.gradle.normalization.*
import org.gradle.platform.base.*
import org.gradle.platform.base.binary.*
import org.gradle.platform.base.component.*
import org.gradle.platform.base.plugins.*
import org.gradle.play.*
import org.gradle.play.distribution.*
import org.gradle.play.platform.*
import org.gradle.play.plugins.*
import org.gradle.play.plugins.ide.*
import org.gradle.play.tasks.*
import org.gradle.play.toolchain.*
import org.gradle.plugin.devel.*
import org.gradle.plugin.devel.plugins.*
import org.gradle.plugin.devel.tasks.*
import org.gradle.plugin.management.*
import org.gradle.plugin.use.*
import org.gradle.plugins.ear.*
import org.gradle.plugins.ear.descriptor.*
import org.gradle.plugins.ide.*
import org.gradle.plugins.ide.api.*
import org.gradle.plugins.ide.eclipse.*
import org.gradle.plugins.ide.idea.*
import org.gradle.plugins.javascript.base.*
import org.gradle.plugins.javascript.coffeescript.*
import org.gradle.plugins.javascript.envjs.*
import org.gradle.plugins.javascript.envjs.browser.*
import org.gradle.plugins.javascript.envjs.http.*
import org.gradle.plugins.javascript.envjs.http.simple.*
import org.gradle.plugins.javascript.jshint.*
import org.gradle.plugins.javascript.rhino.*
import org.gradle.plugins.signing.*
import org.gradle.plugins.signing.signatory.*
import org.gradle.plugins.signing.signatory.pgp.*
import org.gradle.plugins.signing.type.*
import org.gradle.plugins.signing.type.pgp.*
import org.gradle.process.*
import org.gradle.swiftpm.*
import org.gradle.swiftpm.plugins.*
import org.gradle.swiftpm.tasks.*
import org.gradle.testing.base.*
import org.gradle.testing.base.plugins.*
import org.gradle.testing.jacoco.plugins.*
import org.gradle.testing.jacoco.tasks.*
import org.gradle.testing.jacoco.tasks.rules.*
import org.gradle.testkit.runner.*
import org.gradle.vcs.*
import org.gradle.vcs.git.*
import org.gradle.work.*
import org.gradle.workers.*
Copy the code

Import dependence

buildscript { repositories { mavenCentral() } dependencies { classpath group: 'commons-codec', name: 'commons-codec', version: '1.2'}}Copy the code

Logging

The level of logging

The level of logging instructions
ERROR Error message
QUIET Important information message
WARNING Warning message
LIFECYCLE Progress message
INFO Information message
DEBUG Debugging information

Select a Log Level

This can be configured using command line options or the gradle.properties file

options Output Log Level
No record option LIFECYCLE and higher
-q or–quiet QUIET and higher
-w or –warn WARNING and higher
-i or –info The INFO and higher
-d or –debug DEBUG and later (that is, all log messages)

Stacktrace command-line option

-s or –stacktrace

Prints concise stack trace information. RecommendedCopy the code

-S or –full-stacktrace

Prints the complete stack trace information.Copy the code

Write the log

Write log messages using stdout

println 'A message which is logged at QUIET level'
Copy the code

Write your own log messages

logger.quiet('An info log message which is always logged.') logger.error('An error log message.') logger.warn('A warning  log message.') logger.lifecycle('A lifecycle info log message.') logger.info('An info log message.') logger.debug('A Debug log message.') logger.trace('A trace log message.') // Gradle never logs trace level logs // Write A log message with A placeholder logger.info('A {} log message', 'info')Copy the code

A property is provided by the Logger build script, which is an instance of Logger. This interface extends the SLF4JLogger interface and adds gradle-specific methods to it

Write log messages using SLF4J

import org.slf4j.LoggerFactory

def slf4jLogger = LoggerFactory.getLogger('some-logger')
slf4jLogger.info('An info log message logged using SLF4j')
Copy the code

build

Build life cycle

At its core, Gradle is a dependency-based programming language, which means you can define tasks and dependencies between tasks. Gradle guarantees that these tasks are executed in the order of their dependencies and that each task is executed only once. These tasks form a directional acyclic graph.

The construction phase

Gradle builds have three distinct stages.

  • Initialize the

    Gradle supports both single and multi-project builds. During the initialization phase, Gradle decides which projects to participate in the build and creates a Project instance for each Project.

  • configuration

    At this stage, the project object is configured. Execute build scripts for all projects that are part of the build.

  • perform

    Gradle determines the subset of tasks to be created and configured during the configuration phase. The subset is determined by the task name parameter passed to the gradle command and the current directory. Gradle then executes each selected task.

Settings file

The default name is settings.gradle

Projects built in a multi-project hierarchy must have a settings.gradle file in the root project.

For single-project builds, the Settings file is optional

Initialize the

Look in settings.gradle to see if there are multiple projects

Gradle without settings.gradle or Settings. gradle without multiple project configurations is a single project

Example: Add the test task to each project with a specific set of attributes

build.gradle


allprojects {
    afterEvaluate { project ->
        if (project.hasTests) {
            println "Adding test task to $project"
            project.task('test') {
                doLast {
                    println "Running tests for $project"
                }
            }
        }
    }
}

Copy the code

Output gradle -q test

> gradle -q test
Adding test task to project ':project-a'
Running tests for project ':project-a'
Copy the code

Initialization script

The initialization script is similar to other scripts in Gradle. However, these scripts run before the build begins. Initialization scripts cannot access the classes in the buildSrc project.

Use the initialization script

There are several ways to use an initialization script:

  • Specify a file on the command line. The command line options are -i or -init-script, followed by the path to the script.

The command-line option can appear more than once, with another init script added each time. If the file specified on the command line does not exist, compilation will fail.

  • inUSER_HOMEPlace a file named init.gradle (or init.gradle.ktskotlin) in the /.gradle/ directory.
  • inUSER_HOME/.gradle/init.d/ place a file that ends with.gradle (or.init.gradle.ktskotlin).
  • In Gradle distributionGRADLE_HOMEPlace a file ending with.gradle (or.init.gradle.ktskotlin) in the /init.d/ directory. This allows you to package a custom Gradle distribution that contains some custom build logic and plug-ins. You can use this in conjunction with Gradle Wrapper to make custom logic available to all builds in your enterprise.

If more than one initialization script is found, they are executed in the order specified above.

The sample

build.gradle

repositories { mavenCentral() } task showRepos { doLast { println "All repos:" println repositories.collect { it.name } }}Copy the code

init.gradle

allprojects {
    repositories {
        mavenLocal()
    }
}
Copy the code

Running tasks:

Initialize dependencies in scripts to add dependencies

init.gradle

Dependencies initscript {repositories {mavenCentral ()} {the classpath 'org.apache.com mons: Commons - math: 2.0'}}Copy the code

Multiple projects

You can set multiple project relationships in settings.gradle file, as shown in the following project structure

.├ ─ app │... │ ├ ─ └─ buildCopy the code

settings.gradle

Rootproject. name = 'basic-multiproject' // rootProject name include 'app' // subprojectCopy the code

Inter-project dependencies

dependencies {
    implementation(project(":shared"))
}
Copy the code

Build optimization

For build optimization, see Build Optimization

Rely on

configurations

Configurations Configures the dependency information

build.gradle

Configurations {// exposedApi {// canBeResolved is a resolvable configuration if it is true, For consumer canBeResolved = false // canBeConsumed is true for consumption analysis configuration, for producer canBeConsumed = true} // For consumer needs to implement this component configuration. exposedRuntime { canBeResolved = false canBeConsumed = true } }Copy the code

Depend on the way

Module is dependent on

build.gradle

dependencies { runtimeOnly group: 'org.springframework', name: 'spring-core', version: '2.5' runtimeOnly 'org. Springframework: spring - the core: 2.5', 'org. Springframework: spring - aop: 2.5' runtimeOnly ([group: 'org. springFramework ', name: 'spring-core', version: '2.5'], [group: 'org.springframework', name: 'spring - aop version:' 2.5 ']) runtimeOnly (' org. Hibernate: hibernate: 3.0.5 ') {transitive = true} runtimeOnly group: 'org.hibernate', name: 'hibernate', version: '3.0.5', transitive: true runtimeOnly(group: 'org.hibernate', name: 'Hibernate ', version: '3.0.5') {transitive = true}}Copy the code

File is dependent on

build.gradle

dependencies {
    runtimeOnly files('libs/a.jar', 'libs/b.jar')
    runtimeOnly fileTree('libs') { include '*.jar' }
}
Copy the code

Project depend on

build.gradle

dependencies {
    implementation project(':shared')
}
Copy the code

Depend on the way

  • CompileOnly – Dependencies necessary to compile production code, but should not be part of the runtime classpath
  • Implementation (instead of compile) – for compile and run time
  • RuntimeOnly (instead of Runtime) – Used only at runtime, not for compilation
  • TestCompileOnly – Same as the compileOnly test
  • TestImplementation – The test is equivalent to implementation
  • TestRuntimeOnly – The test corresponds to runtimeOnly

repositories

Popular public repositories include Maven Central, Bintray JCenter, and the Google Android repository.

MavenCentral () {// Maven Central Repository jCenter () // Maven Repository Google () // Maven Repository mavenLocal() FlatDir {dirs 'lib'} flatDir {dirs 'lib1', 'lib2} / / add custom Maven repositories Maven {url "http://repo.mycompany.com/maven2" / / for the JAR file to add additional Maven repository artifactUrls "http://repo.mycompany.com/jars" } //Ivy ivy { url "http://repo.mycompany.com/repo" layout "maven" // Valid named layout values are 'gradle' (default) 'maven' and 'Ivy'. }}Copy the code

Declare repository filters

Declare the contents of the repository

build.gradle

repositories {
    maven {
        url "https://repo.mycompany.com/maven2"
        content {
            // this repository *only* contains artifacts with group "my.company"
            includeGroup "my.company"
        }
    }
    jcenter {
        content {
            // this repository contains everything BUT artifacts with group starting with "my.company"
            excludeGroupByRegex "my\\.company.*"
        }
    }
}
Copy the code

By default, the repository contains everything and nothing:

  • If you declare include, it excludes everything other than include.
  • If you declare exclude, it will include everything except exclude.
  • If you declare include and exclude, it only includes content that is explicitly included but not excluded.

Split snapshots and distributions

build.gradle

repositories {
    maven {
        url "https://repo.mycompany.com/releases"
        mavenContent {
            releasesOnly()
        }
    }
    maven {
        url "https://repo.mycompany.com/snapshots"
        mavenContent {
            snapshotsOnly()
        }
    }
}
Copy the code

Supported metadata sources

Supported metadata sources

Metadata sources describe The sorting Maven Ivy/flat dir
gradleMetadata() Look for the gradle. module file 1 is is
mavenPom() Look for maven.pom files 2 is is
ivyDescriptor() Find the ivy. XML file 2 There is no is
artifact() Direct artifact search 3 is is

Starting with Gradle 5.3, when parsing a metadata file (whether Ivy or Maven), Gradle looks for a flag indicating the existence of a matching Gradle Module metadata file. If it is found, it will be used instead of Ivy or Maven files.

Since Gradle5.6, you can add ignoreGradleMetadataRedirection () to metadataSources statement to disable this behavior.

Maven repository that does not use Gradle metadata redirection

build.gradle

repositories {
    maven {
        url "http://repo.mycompany.com/repo"
        metadataSources {
            mavenPom()
            artifact()
            ignoreGradleMetadataRedirection()
        }
    }
}
Copy the code

GAV coordinates

GAV coordinates generally refer to group, artifact, version

variant

Build variants are configurations for different environments, such as Debug and Release variants in Android development

Declare functional variants

Functional variants can be declared by applying Java or the Java-Library plug-in. The following code shows how to declare a function called mongodbSupport:

Example 1. Declare a function variable

Groovy``Kotlin

build.gradle

Group = 'org.gradle.demo' version = '1.0' Java {registerFeature('mongodbSupport') {usingSourceSet(sourcesets.main)}}Copy the code

metadata

Each module extracted from the repository has metadata associated with it, such as its group, name, version, and the different variants it provides with artifacts and dependencies

Examples of configurable component metadata rules

build.gradle

class TargetJvmVersionRule implements ComponentMetadataRule { final Integer jvmVersion @Inject TargetJvmVersionRule(Integer jvmVersion) { this.jvmVersion = jvmVersion } @Inject ObjectFactory getObjects() { } void execute(ComponentMetadataContext context) { context.details.withVariant("compile") { attributes { attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, jvmVersion) attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage, Usage.JAVA_API)) } } } } dependencies { components { withModule("commons-io:commons-io", TargetJvmVersionRule) { params(7) } withModule("commons-collections:commons-collections", TargetJvmVersionRule) {params(8)}} implementation("commons-io:commons-io:2.6") Implementation (" Commons - collections: Commons - collections: 3.2.2 ")}Copy the code

Variations can be modified by:

  • AllVariants: modify allVariants of the component

  • WithVariant (name) : Modifies a single variant identified by name

  • AddVariant (name) or addVariant(name, base) : Add a new variant to a component from scratch or by copying the details of an existing variant (base)

You can adjust the following details for each variant:

  • Attributes {} block that identifies variants
  • This variant provides the withCapabilities {} block
  • Variants of dependencies, including a rich version of the -withDependencies {} block
  • Variant dependency constraints, including rich version – withDependencyConstraints {} block
  • The location of the published file that constitutes the actual content of the variant – the withFiles {} block

platform

Use the platform

Gets the version declared in the platform

build.gradle

dependencies {
    // get recommended versions from the platform project
    api platform(project(':platform'))
    // no version required
    api 'commons-httpclient:commons-httpclient'
}
Copy the code

The platform notation is a shorthand notation that actually does something in the background:

  • It sets the org.gradle.category property to platform, which means that Gradle selects the platform component of the dependency.
  • It sets the endorseStrictVersions behavior by default, which means that if the platform declares strict dependencies, they will be enforced.

This means that by default, dependencies on a platform trigger inheritance of all strict versions defined in that platform, which is useful for platform authors to ensure that all consumers follow their own decisions about the version of dependencies. By explicitly call doNotEndorseStrictVersions method to close it.

Rely on a BOM to import its dependency constraints

build.gradle

dependencies { // import a BOM implementation Platform (' org. Springframework. The boot: spring - the boot - dependencies: 1.5.8. RELEASE ') / / define dependencies without versions implementation 'com.google.code.gson:gson' implementation 'dom4j:dom4j' }Copy the code

Import the BOM to ensure that the version it defines overwrites any other versions found

build.gradle

dependencies { // import a BOM. The versions used in this file will override any other version found in the graph Implementation enforcedPlatform (' org. Springframework. The boot: spring - the boot - dependencies: 1.5.8. RELEASE ') / / define dependencies without versions implementation 'com.google.code.gson:gson' implementation 'dom4j:dom4j' // this version Will be overridden by the one found in the BOM implementation 'org. Codehaus. Groovy: groovy: 1.8.6'}Copy the code

Capability

Declare the capability of the component

build.gradle

Configurations {apiElements {outgoing {capability("com.acme:my-library:1.0") capability("com.other:module:1.1")}} RuntimeElements {outgoing {capability("com.acme:my-library:1.0") capability("com.other:module:1.1")}}Copy the code

Resolve the conflict

Resolve conflicts according to Capability, (dependencies with the same Capability will fail)

build.gradle

@CompileStatic
class AsmCapability implements ComponentMetadataRule {
    void execute(ComponentMetadataContext context) {
        context.details.with {
            if (id.group == "asm" && id.name == "asm") {
                allVariants {
                    it.withCapabilities {
                        // Declare that ASM provides the org.ow2.asm:asm capability, but with an older version
                        it.addCapability("org.ow2.asm", "asm", id.version)
                    }
                }
            }
        }
    }
}

Copy the code

A build file with an implicit conflict for the logging framework

build.gradle

dependencies {
    // Activate the "LoggingCapability" rule
    components.all(LoggingCapability)
}

@CompileStatic
class LoggingCapability implements ComponentMetadataRule {
    final static Set<String> LOGGING_MODULES = ["log4j", "log4j-over-slf4j"] as Set<String>

    void execute(ComponentMetadataContext context) {
        context.details.with {
            if (LOGGING_MODULES.contains(id.name)) {
                allVariants {
                    it.withCapabilities {
                        // Declare that both log4j and log4j-over-slf4j provide the same capability
                        it.addCapability("log4j", "log4j", id.version)
                    }
                }
            }
        }
    }
}
Copy the code

version

Version of the rules

Gradle supports different versions of string declarations:

  • An exact version: e.g1.3.1.3.0 -beta3.1.0-20150201.131010-1
  • A Maven-style version range: for example[1.0,).[1.1, 2.0).(1.2, 1.5]
    • [and]The symbol of represents the inclusion constraint;(and)Represents an exclusive constraint.
    • When an upper or lower bound is missing, the range has no upper or lower bound.
    • symbol]Can be used instead(Used of the lower bound of exclusivity,[Instead of)Used of an exclusive upper bound. For example,] 1.0, 2.0 [
  • Prefix version range: for example1. +.1.3. +
    • Contains only with+Previous partially fully matched versions.
    • +The scope itself will include any version.
  • A latest-status version: for example, latest.integration, latest.release
  • Maven’s SNAPSHOT version identifier: for example, 1.0-snapshot, 1.4.9-beta1-snapshot

Version of the sort

  • Each edition is divided into its constituent “parts” :
    • The character [. -_ +] is used to separate different parts of the version.
    • Any part containing both numbers and letters will be divided into the following sections:1a1 == 1.a.1
    • Only parts of the version are compared. The actual delimiter is not important:1.a.1 == 1-a+1 == 1.a-1 == 1a1
  • Compare the equivalent parts of the two versions using the following rules:
    • If both parts are numbers, the highest digit value is higher:1.1 < 1.2
    • If a part is numeric, it is considered higher than the non-numeric part:1. A < 1.1
    • If neither part is a number, compare it alphabetically, case sensitive:1.A< 1.B< 1.a<1.b
    • Versions with extra numeric parts are considered higher than those without:1.1 < 1.1.0
    • Versions with additional non-digital parts are considered lower than versions without digital parts:1.1. A < 1.1
  • Some string values have special meanings for sorting purposes:
    • The string dev is considered lower than any other string part:1.0 alpha 1.0 dev < < 1.0 rc.
    • The strings RC, release, and final are considered higher than any other part of the string (in that order:1.0-Zeta < 1.0-RC < 1.0-release< 1.0-final< 1.0.
    • The string SNAPSHOT has no special meaning and is sorted alphabetically like other string parts:1.0-alpha< 1.0-Snapshot < 1.0-Zeta < 1.0-RC < 1.0.
    • The numeric snapshot version has no special meaning and is sorted like any other numeric part:1.0 < 1.0-20150201.121010-123 < 1.1.

In simple terms: Numbers > Final > Release > RC > letters >dev

Declarations have no version dependencies

For larger projects, the recommended approach is to declare dependencies that have no version and use dependency constraints for version declarations. The advantage is that dependency constraints allow you to manage all versions of dependencies in one place, including transitive dependencies.

build.gradle

dependencies { implementation 'org.springframework:spring-web' } dependencies { constraints { implementation 'org. Springframework: spring - web: 5.0.2. RELEASE'}}Copy the code

Depend on the way

strictly

Any version that does not match the version symbol will be excluded. This is the strongest version statement. Strictly can degrade versions of declared dependencies. On passing a dependency, failure to select an acceptable version of this clause will cause dependency resolution to fail. For more information, see Override dependency Versions. The term supports dynamic versioning.Copy the code

Once defined, the previous require declaration is overridden and the previous reject is cleared.

require

Indicates that the selected version cannot be lower than the version acceptable to require, but can be improved through conflict resolution, even if higher versions have higher bounds of exclusivity. This is what the direct version on the dependency transforms. The term supports dynamic versioning.Copy the code

When defined, the previous STRICTLY declaration is overridden and the previous reject is cleared.

prefer

This is a very soft version declaration. This applies only if there is no stronger non-dynamic view of the version of the module. Dynamic version is not supported by this term.Copy the code

The definition can be supplemented by strictly or require.

There is an additional term beyond the level hierarchy:

reject

Declare that a module does not accept a particular version. If the only alternative version is also rejected, this will cause dependency resolution to fail. The term supports dynamic versioning.Copy the code

Dynamic version

build.gradle

plugins {
    id 'java-library'
}

repositories {
    mavenCentral()
}

dependencies {
    implementation 'org.springframework:spring-web:5.+'
}
Copy the code

Version snapshot

Declare a version-changing dependency

build.gradle

plugins { id 'java-library' } repositories { mavenCentral() maven { url 'https://repo.spring.io/snapshot/' } } Dependencies {implementation 'org. Springframework: spring - web: 5.0.3. BUILD - the SNAPSHOT'}Copy the code

Programmatic control of dependency caching

You can use ResolutionStrategy to program the configuration to fine-tune some aspects of the cache. Programmatically, this is useful if you want to change Settings permanently.

Gradle caches dynamic versions for 24 hours by default. To change the time Gradle caches a parsed version as a dynamic version, use:

Dynamic version cache control

build.gradle

configurations.all {
    resolutionStrategy.cacheDynamicVersionsFor 10, 'minutes'
}

Copy the code

By default, Gradle caches changed modules for 24 hours. To change the time Gradle will cache metadata and artifacts for the changed modules, use:

Example. Change the module cache control

build.gradle

configurations.all {
    resolutionStrategy.cacheChangingModulesFor 4, 'hours'
}
Copy the code

Lock the configuration

Locking a specific configuration

build.gradle

configurations {
    compileClasspath {
        resolutionStrategy.activateDependencyLocking()
    }
}
Copy the code

Lock all configurations

build.gradle

dependencyLocking {
    lockAllConfigurations()
}
Copy the code

Unlocking specific configurations

build.gradle

configurations {
    compileClasspath {
        resolutionStrategy.deactivateDependencyLocking()
    }
}
Copy the code

Lock the BuildScript classpath configuration

If you are applying plug-ins to build, you may also need to leverage dependency locking. To lock the CLASspath configuration for script plug-ins, do the following:

build.gradle

buildscript {
    configurations.classpath {
        resolutionStrategy.activateDependencyLocking()
    }
}

Copy the code

Fine-tune the dependency locking behavior with locking mode

Although the behavior of the default lock mode is described above, there are two other modes available:

  • Strict mode: In this mode, dependency locking fails if a configuration marked as locked does not have a locking state associated with it, in addition to the validation described above.

  • Lenient mode: In this mode, dependency locking is still fixed to the dynamic version, but otherwise changes in dependency resolution are no longer errors.

The locking mode can be controlled from the dependencyLocking block as follows:

build.gradle

dependencyLocking {
    lockMode = LockMode.STRICT
}
Copy the code

Version conflict

Use force to enforce a dependent version

build.gradle

Dependencies {implementation 'org, apache httpcomponents: httpclient: 4.5.4' Implementation ('commons-codec:commons-codec:1.9') {force = true}}Copy the code

Transitive dependencies that exclude specific dependency declarations

build.gradle

Dependencies {implementation('commons-beanutils:commons-beanutils:1.9.4') {exclude group: 'commons-collections', module: 'commons-collections' } }Copy the code

Failed during version conflict

build.gradle

configurations.all {
    resolutionStrategy {
        failOnVersionConflict()
    }
}

Copy the code

Failed with dynamic version

build.gradle

configurations.all {
    resolutionStrategy {
        failOnDynamicVersions()
    }
}
Copy the code

Failed to change version

build.gradle

configurations.all {
    resolutionStrategy {
        failOnChangingVersions()
    }
}
Copy the code

Failed when parsing cannot be reproduced

build.gradle

configurations.all {
    resolutionStrategy {
        failOnNonReproducibleResolution()
    }
}

Copy the code

The plug-in

What plug-ins do: Applying plug-ins to a project enables plug-ins to extend the functionality of the project. It can do the following:

  • Extending the Gradle model (for example, adding new DSL elements that can be configured)
  • Configure items according to convention (for example, add new tasks or configure reasonable defaults)
  • Applying a specific configuration (for example, adding an organizational repository or enforcing standards)

Simply put, plug-ins extend project functionality such as tasks, dependencies, extended properties, and constraints

Plug-in type

  • Binary plug-ins: Binary plug-ins are written programmatically by implementing the plug-in interface, or declaratively using a DSL language of Gradle
  • Script plug-ins: Script plug-ins are other build scripts that further configure the build and often take a declarative approach to manipulating the build

Plug-ins typically start as script plug-ins (because they are easy to write), and then, as the code becomes more valuable, migrate to binary plug-ins that can be easily tested and shared across multiple projects or organizations.

Application of plug-in

Binary plug-in

The org.gradle.api.Plugin interface is implemented

apply plugin: 'com.android.application'
Copy the code

apply plugin

Apply the plugin: 'Java' / / id = = the apply plugin: org. Gradle. API. Plugins. The JavaPlugin / / type = = the apply the plugin: JavaPlugin //org.gradle.api.plugins are imported by defaultCopy the code

plugins DSL

Plugins {id 'Java' // App core plugin ID 'com.jfrog. Bintray 'version '0.4.1' // App community plugin ID 'com.example. Hello' version '1.0.0' // Use the 'apply false' syntax to tell Gradle not to apply the plug-in to the current project}Copy the code

Scripting plug-ins

Script plug-ins are automatically parsed and can be applied from scripts in local file systems or remote locations. Multiple script plug-ins, in any form, can be applied to a given target.

apply from:'version.gradle'
Copy the code

Apply passes in content

void apply(Map<String,? options);
void apply(Closure closure);
void apply(Action<? super ObjectConfigurationAction> action);
Copy the code

Define the plugin

Define a buildSrc plugin with an ID: buildSrc/build.gradle

plugins {
    id 'java-gradle-plugin'
}
gradlePlugin {
    plugins {
        myPlugins {
            id = 'my-plugin'
            implementationClass = 'my.MyPlugin'
        }
    }
}
Copy the code

Third-party plug-ins

Binary plug-ins published as external JAR files can be added to a project by adding the plug-in to the build script CLASspath and then applying the plug-in. External jars can be added to the buildscript classpath using the buildscript {} block.

Jcenter buildscript {repositories {Google () ()} dependencies {classpath "com. Android. View the build: gradle: 4.0.1"}}Copy the code

Plug-in management

The pluginManagement {} block can only appear in settings.gradle files, must be the first block in the file, and can also appear in initialization scripts as Settings.

settings.gradle

pluginManagement {
    plugins {
    }
    resolutionStrategy {
    }
    repositories {
    }
}
rootProject.name = 'plugin-management'
Copy the code

init.gradle

settingsEvaluated { settings ->
    settings.pluginManagement {
        plugins {
        }
        resolutionStrategy {
        }
        repositories {
        }
    }
}
Copy the code

Example: Manage plug-in versions through pluginManagement.

settings.gradle

pluginManagement {
  plugins {
        id 'com.example.hello' version "${helloPluginVersion}"
  }
}

Copy the code

gradle.properties

HelloPluginVersion = 1.0.0Copy the code

Custom plug-in repositories

To specify a custom plug-in repository, use pluginManagement {} in the {} block:

settings.gradle

pluginManagement { repositories { maven { url '.. /maven-repo' } gradlePluginPortal() ivy { url '.. /ivy-repo' } } }Copy the code

Java library

Import the Java

apply plugin:'java'
Copy the code

Custom path

sourceSets {
    main {
         java {
            srcDirs = ['src']
         }
    }

    test {
        java {
            srcDirs = ['test']
        }
    }
}
Copy the code
sourceSets {
    main {
        java {
            srcDir 'thirdParty/src/main/java'
        }
    }
}
Copy the code

Import dependence

repositories { jcenter() } dependencies { implementation Group: 'com. Android. Support', name: 'appcompat - v7, version:' 28.0.0 'implementation 'com. Android. Support: appcompat - v7:28.0.0' implementation protect (' : 'p) implementation file (' libs/ss. Jar', 'libs/ss2. Jar)  implementation fileTree(dir: "libs", include: ["*.jar"]) }Copy the code

Set settings.gradle for multiple projects

include ':app'
rootProject.name = "GradleTest"
Copy the code

Android practical

Set the signature

android { signingConfig = { release { storeFile file("MYKEY.keystore") storePassword "storePassword" keyAlias "keyAlias"  keyPassword "keyPassword" } } }Copy the code

Custom output APK file name

applicationVariants.all { variant -> variant.outputs.all { output -> def fileName = VersionName}_release.apk" def outFile = output.outputFile if (outFile! = null && outFile.name.endsWith('.apk')) { outputFileName = fileName } } }Copy the code

Dynamic AndroidManifest

<meta-data android:name="paramName" android:value="${PARAM_NAME}">
android {
    productFlavors{
        google{
            manifestPlaceholders.put("PARAM_NAME",'google')
        }
    }
}
Copy the code

multi-channel

android {
    productFlavors{
        google{
            
        },
        baidu{
            
        }
    }
    productFlavors.all{ flavor->
        manifestPlaceholders.put("PARAM_NAME",name)
    }
}
Copy the code

The adb is set

The adb tool

Android {adbOptions{timeOutInMs = 5000 //5s Timeout installOptions '-r','-s' // setup directives}}Copy the code

dexOptions

Dex tools

Android {dexOptions{incremental true // incremental javaMaxHeapSize '4G'//dx maximum memory jumboMode true // Forcibly enable the jumbo skip 65535 limit PreDexLibraries true // increase the incremental build speed of threadCount 1 //dx thread number}}Copy the code

Ant

Pass nested elements to Ant

build.gradle

task zip {
    doLast {
        ant.zip(destfile: 'archive.zip') {
            fileset(dir: 'src') {
                include(name: '**.xml')
                exclude(name: '**.java')
            }
        }
    }
}
Copy the code

Example: Use the Ant type

build.gradle

task list {
    doLast {
        def path = ant.path {
            fileset(dir: 'libs', includes: '*.jar')
        }
        path.list().each {
            println it
        }
    }
}
Copy the code

Use custom Ant tasks

build.gradle

task check {
    doLast {
        ant.taskdef(resource: 'checkstyletask.properties') {
            classpath {
                fileset(dir: 'libs', includes: '*.jar')
            }
        }
        ant.checkstyle(config: 'checkstyle.xml') {
            fileset(dir: 'src')
        }
    }
}
Copy the code

Lint

Lint: Tool in the Android tool directory, a code scanning tool that helps identify problems with resources and code structures

LintOptions Android {lintOptions{abortOnError true // Launch Gradle absolutePaths true // Configuration error whether the output shows absolute path check 'NewApi','InlinedApi' // Check lint check's issue ID enable 'NewApi','InlinedApi' // Enable Lint Check's issue ID disable 'NewApi','InlinedApi' // disable lint check issue id checkAllWarnings true // check all warnings issue ignoreWarning true // ignoreWarning check, Default false checkReleaseBuilds true // Check fatal errors, default true explainIssues true // Error reports contain explanations, Default true htmlOutput new File("/xx.html") // HTML report output path htmlReport true // Whether to generate HTML report, LintConfig new File("/xx.xml") //lint configures noLines true // Output without line numbers default true quite true // showAll true // Whether to display all output, Untruncated}}Copy the code

reference

  • Gradle document
  • The Definitive Guide to Android Gradle