资讯详情

Android Gradle构建脚本

Gradle构建脚本使用Groovy写作。默认构建文件名为build.gradle 。Gradle当命令构建时,它会找到一个名字build.gradle然后执行文件。

在android studio在项目中,默认情况下,根目录有一份build.gradle ,各个module各有一份。

在android studio任何一个项目build.gradle在文件中定义一个hello任务,执行gradle这些都是命令build.gradle在文件中找到所有定义hello从根目录中逐一执行任务,如: 在根目录的build.gradle文件定义:

task hello { 
            println 'Hello world root' } 

在app module目录的build.gradle文件定义:

task hello { 
            println 'Hello world app' } 
  • 在build.gradle使用目录gradle命令运行这个task
juk@Juk-MacBook-Pro HelloWorld % /Users/juk/.gradle/wrapper/dists/gradle-7.2-bin/2dnblmf4td7x66yl1d74lt32g/gradle-7.2/bin/gradle -q hello Hello world root Hello world app 
  • 项目也可以直接运行,然后在build输出的日志窗口可以看到 在这里插入图片描述

Gradle在脚本中构建Project对象

Project对象实现了org.gradle.api.Project接口对象build.gradle这个脚本中, 我们将使用它Project对象与Gradle处理命令。通过它,我们访问了很多Gradle提供的功能特性。

build.gradle文件与Project对象有一对一的关系。构建初始化时,gradle每个参与建设的项目模块都将参与(module)组装一个Project对象,具体流程如下:

  1. 首先,为本次建设创建org.gradle.api.initialization.Settings实例。执行settings.gradle并对脚本中的内容Settings配置对象。它主要声明参与实例化和配置构建的一些配置Project对象层次Settings对象对应一份settings.gradle文件。这一步是在开始构建之前完成的。
  2. 配置好的Settings对象创建Project实例的层次
  3. 最后,通过实施每个项目(module)的build.gradle配置各自的Project对象。执行顺序,默认情况来自父亲项目(父亲项目)module)子项目(子module)。

build.gradle的组成

一般,一个项目(module)对应一份build.gradle脚本。我们会用的build.gradle脚本去配置Project对象。所以 build.gradle的组成就是Project对象的组成。

Tasks

一个Project对象基本上是Tasks对象的集合。每个task一些基本工作,如编译、操作单元测试、压缩等WAR包,生成JavaDoc。每个task都属于某一个Project对象。Task对象是由TaskContainer如果对象负责创建,可以直接在脚本中使用task直接调用名称。用于构建脚本task可以声明关键字task了:

task helloTask task helloTask { 
        } task helloTask(type:Delete) task helloTask(type:Delete){ 
        } // 创建hello1 task task(hello1) { 
             println "Good morning!1" } // 创建hello2 task task('hello2') { 
             println "Good morning!" } // 创建hello3 task tasks.create(name:'hello3') { 
             println "Good afternoon!" } 

上述声明都是合法的

一个task它由一系列行为对象组成。task当它们被执行时,它们被执行。

task 的依赖关系

给task hello添加依赖

task hello1 { 
             doLast { 
                 println 'Hello world 1'     } }  task helo2(dependsOn: 'hello1') { 
        
    doLast { 
        
        println 'Hello world 2'
    }
}

上面这种方式还可以换成以下这种方式:

task hello2 { 
        
    doLast { 
        
        println 'Hello world 2'
    }
}

task hello1 { 
        
    doLast { 
        
        println 'Hello world 1'
    }
}

hello2.dependsOn hello1

依赖还可以这样来写:


task hello2 { 
        
    doLast { 
        
        println 'Hello world 2'
    }
}

task hello1 { 
        
    doLast { 
        
        println 'Hello world 1'
    }
}

hello2.dependsOn { 
        
    tasks.findAll { 
        
        taskIt -> taskIt.name.startsWith('hello1')
    }
}

运行结果都是:

juk@JukLings-MacBook-Pro HelloWorld % /Users/juk/.gradle/wrapper/dists/gradle-7.2-bin/2dnblmf4td7x66yl1d74lt32g/gradle-7.2/bin/gradle -q hello2
Hello world 1
Hello world 2

doLast的意思就是将这个task 行为放到task的行为列表的最后面。

根据某些情况跳过task的执行

project.ext.skipStage = 'Hello'
task skipTask { 
        
    doLast { 
        
        println 'Hello world'
    }
}

// 当有这个skipStage属性时才执行skipTask,没有时跳过skipTask,因当前面有定义skipStage这个属性,因此会执行skipTask
skipTask.onlyIf{ 
        
    project.hasProperty('skipStage')
}

还可以通过抛异常的方式来跳过,如上面的代码可以换成下面的来实现:

project.ext.skipStage = 'Hello'
task skipTask { 
        
    doLast { 
        
        println 'Hello world'
    }
}

skipTask.doFirst { 
        
    if(!project.hasProperty('skipStage')){ 
        
        throw new StopExecutionException()
    }
}

结果都是:

juk@JukLings-MacBook-Pro HelloWorld % /Users/juk/.gradle/wrapper/dists/gradle-7.2-bin/2dnblmf4td7x66yl1d74lt32g/gradle-7.2/bin/gradle -q skipTask
Hello world

在它要执行task之前,Gradle会经历不同的阶段。首先是配置阶段,过后就是执行阶段,这个阶段它就会执行task的doFirst或doLast闭包里的代码。

这里要给大家说明一下, 下面这种task的写法是OK的:

task hello { 
        
    println 'Hello world 1'
}

hello { 
        
    println 'Hello world 2'
}

结果:

juk@JukLings-MacBook-Pro HelloWorld % /Users/juk/.gradle/wrapper/dists/gradle-7.2-bin/2dnblmf4td7x66yl1d74lt32g/gradle-7.2/bin/gradle -q hello   
Hello world 1
Hello world 2

Dependencies

依赖配置应该是大家最熟悉的了。最常见就是下面这些:

dependencies { 
        
	// 只能在当前项目(module)使用
	implementation 'group:name:version'
	// 共享
	api 'group:name:version'
	// 单元测试
	testImplementation 'group:name:version'
	// android测试
	androidTestImplementation 'group:name:version'
	...
}

在脚本就是这样配置的,它在Project对象中是由DependencyHandler对象管着的。

Repositories

指定外部依赖的源,就是告诉gradle去这个仓库下载我们添加的依赖。

repositories { 
        
        google()
        mavenCentral()
    }

指定自己的依赖仓库,也是用这个

repositories { 
        
        maven { 
        
        	url "http://repo.juk.com/maven2"
        	}
    }

在脚本中配置的这些会用来配置在Project对象中的RepositoryHandler对象管着的。

如果你要上传你压缩包到maven仓库,那么你可以在maven插件的uploadArchives task用repositories指定上传位置

apply plugin: 'maven' // 要先把maven插件加进来,否则没有uploadArchives任务
uploadArchives { 
        
   repositories { 
        
        mavenDeployer { 
        
        	repository(url: "http://repo.juk.com/maven2")
        	}
    }
}

Plugins

其实插件并没有什么特殊之处,它就是一些task的集合,例如有些插件里有编译的task,设置源文件的task设置等等。添加插件到项目中来其实就是为了扩充Project对象的能力,让它能做更多事。android项目的build.gradle就会有如下的插件:

plugins { 
        
    id 'com.android.application'
    id 'kotlin-android'
}

一般来说插件有两种类型:

  1. 一种是脚本插件,它是一构建脚本,会用于构建过程中。
  2. 另一种是二进制插件,它们是一些实现了插件接口的类,通过程序的方法来控制构建。

对应的,添加插件也有两种方式:

  1. 从本地文件系统添加一份脚本
apply from: 'other.gradle'
  1. 添加二进制插件
plugins { 
        
    id 'com.android.application'
}

apply plugin: 'com.android.application'

自定义一个插件

首先在build.gradle的开头引用我们的插件

apply plugin: HelloPlugin

然后在build.gradle找一个地方定义我们的插件,如文件末尾:

class HelloPlugin implements Plugin<Project> { 
        

    @Override
    void apply(Project project) { 
        
        project.task("myHelloTask") { 
        
            doLast { 
        
                println 'Hello,My first plugin!'
            }
        }

    }
}

如你所见,自定义的插件,需要实现Plugin接口,apply方法的参数,就是当前build.gradle脚本对应的Project对象,从我们定义里可以看出我们往Project对象里添加了一个task,名为myHelloTask,我们也可以通过传进来的project对象去访问它的东西,如定义的属性。 我们来运行一下这个task:

juk@JukLings-MacBook-Pro HelloWorld % /Users/juk/.gradle/wrapper/dists/gradle-7.2-bin/2dnblmf4td7x66yl1d74lt32g/gradle-7.2/bin/gradle -q myHelloTask
Hello,My first plugin!

如何从build.gradle中获得输入?我们可以扩展Project对象,然后通过扩展后的对象来实现,具体如下:

apply plugin: HelloPlugin

...

// step 2:使用插件扩展出来的属性对象设置它的属性值
myParameter.message = 'Halo Wo'

class HelloPlugin implements Plugin<Project> { 
        

    @Override
    void apply(Project project) { 
        
        
	// step 1:在Project对象中扩展一个属性 myParameter,类型是我们定义的HelloPluginExtension
        project.extensions.create('myParameter',HelloPluginExtension)
        project.task("myHelloTask") { 
        
            doLast { 
        
            // step 3: 获取build.gradle输入的值
                println project.myParameter.message
            }
        }

    }
}

class HelloPluginExtension { 
        
    def String message = 'hello plugin'
}

运行任务myHelloTask:

juk@JukLings-MacBook-Pro HelloWorld % /Users/juk/.gradle/wrapper/dists/gradle-7.2-bin/2dnblmf4td7x66yl1d74lt32g/gradle-7.2/bin/gradle -q myHelloTask
Halo Wo

注意:在Gradle的版本中已有很多标准插件,如编程语言插件:java ,scala,assembler, c,cpp

例如要引用CPP插件:

apply plugin: cpp

查看构建信息

  • 查看Project对象的层次结构
juk@JukLings-MacBook-Pro HelloWorld % /Users/juk/.gradle/wrapper/dists/gradle-7.2-bin/2dnblmf4td7x66yl1d74lt32g/gradle-7.2/bin/gradle -q projects   

------------------------------------------------------------
Root project 'HelloWorld'
------------------------------------------------------------

Root project 'HelloWorld'
+--- Project ':app'
\--- Project ':houseware'

To see a list of the tasks of a project, run gradle <project-path>:tasks
For example, try running gradle :app:tasks

  • 查看任务
juk@JukLings-MacBook-Pro HelloWorld % /Users/juk/.gradle/wrapper/dists/gradle-7.2-bin/2dnblmf4td7x66yl1d74lt32g/gradle-7.2/bin/gradle -q tasks   

------------------------------------------------------------
Tasks runnable from root project 'HelloWorld'
------------------------------------------------------------

Android tasks
-------------
androidDependencies - Displays the Android dependencies of the project.
signingReport - Displays the signing info for the base and test modules
sourceSets - Prints out all the source sets defined in this project.

Build tasks
-----------
assemble - Assemble main outputs for all the variants.
assembleAndroidTest - Assembles all the Test applications.
build - Assembles and tests this project.
buildDependents - Assembles and tests this project and all projects that depend on it.
buildKotlinToolingMetadata - Build metadata json file containing information about the used Kotlin tooling
buildNeeded - Assembles and tests this project and all projects it depends on.
bundle - Assemble bundles for all the variants.
clean - Deletes the build directory.
......

当然你也可以指定看某个项目的task,如houseware项目的task

juklinglee@JukLings-MacBook-Pro HelloWorld % /Users/juklinglee/.gradle/wrapper/dists/gradle-7.2-bin/2dnblmf4td7x66yl1d74lt32g/gradle-7.2/bin/gradle -q :houseware:tasks

------------------------------------------------------------
Tasks runnable from project ':houseware'
------------------------------------------------------------

Android tasks
-------------
androidDependencies - Displays the Android dependencies of the project.
signingReport - Displays the signing info for the base and test modules
sourceSets - Prints out all the source sets defined in this project.

Build tasks
-----------
assemble - Assemble main outputs for all the variants.
assembleAndroidTest - Assembles all the Test applications.
build - Assembles and tests this project.
......
  • 查看所有属性值
juk@JukLings-MacBook-Pro HelloWorld % /Users/juk/.gradle/wrapper/dists/gradle-7.2-bin/2dnblmf4td7x66yl1d74lt32g/gradle-7.2/bin/gradle -q properties  

------------------------------------------------------------
Root project 'HelloWorld'
------------------------------------------------------------

AGP_INTERNAL__MIN_PLUGIN_VERSION_CHECK_STARTED: true
_internalAndroidGradlePluginDependencyCheckerRegistered: true
allprojects: [root project 'HelloWorld', project ':app', project ':houseware']
android.enableJetifier: true
android.useAndroidX: true
ant: org.gradle.api.internal.project.DefaultAntBuilder@62b07301
antBuilderFactory: org.gradle.api.internal.project.DefaultAntBuilderFactory@3dbfb745
artifacts: org.gradle.api.internal.artifacts.dsl.DefaultArtifactHandler_Decorated@4bbf11cf
asDynamicObject: DynamicObject for root project 'HelloWorld'
baseClassLoaderScope: org.gradle.api.internal.initialization.DefaultClassLoaderScope@187dbbc2
buildDir: /Users/juklinglee/AndroidStudioProjects/HelloWorld/build
buildFile: /Users/juklinglee/AndroidStudioProjects/HelloWorld/build.gradle
......
  • 查看编译环境
juk@JukLings-MacBook-Pro HelloWorld % /Users/juk/.gradle/wrapper/dists/gradle-7.2-bin/2dnblmf4td7x66yl1d74lt32g/gradle-7.2/bin/gradle -q buildEnvironment

------------------------------------------------------------
Root project 'HelloWorld'
------------------------------------------------------------

classpath
+--- com.android.tools.build:gradle:7.1.2
|    +--- com.android.tools:sdk-common:30.1.2
|    |    +--- com.android.tools:sdklib:30.1.2
|    |    |    +--- com.android.tools.layoutlib:layoutlib-api:30.1.2
|    |    |    |    +--- com.android.tools:common:30.1.2
|    |    |    |    |    +--- com.android.tools:annotations:30.1.2
|    |    |    |    |    +--- com.google.guava:guava:30.1-jre
|    |    |    |    |    |    +--- com.google.guava:failureaccess:1.0.1
|    |    |
  • 查看某个task的详细使用信息,如查看build 任务:
juklinglee@JukLings-MacBook-Pro HelloWorld % /Users/juklinglee/.gradle/wrapper/dists/gradle-7.2-bin/2dnblmf4td7x66yl1d74lt32g/gradle-7.2/bin/gradle help --task build      

> Configure project :app
C/C++: Could not execute cmake at 
......
> Task :help
Detailed task information for build

Paths
     :app:build
     :houseware:build

Type
     Task (org.gradle.api.Task)

Description
     Assembles and tests this project.

Group
     build

现在,通过查询我们知道build任务就是用来构建项目的。

最后,以上内容只是gradle的冰山一角,但是看它的源码,你将能很好的理解它是怎么工作的。 Gradle Github地址

标签: yl1雨量传感器

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台