gradle脚本

构建块

每个Gradle构建都包含三个基本构建块,至少一个project,一个project又包含多个task,

  • project
    • project会被实例化org.gradle.api.Project类,并且有一个project的变量,可以使用,(这个很像jenkins pipeline中的env变量)
    • println "description project $name" + project.description
  • task
    • 任务动作 task action
    • 任务依赖 task dependency
  • property
    • 每个project和task都可以通过getter和setter访问属性
    • 扩展属性,使用ext{}定义,其他project可以通过project.ext访问
    • Gradle属性,在gradle.properties中定义
    • 命令行中-P指定项目属性,相当于在project中直接定义
    • 命令行中-D执行系统属性,被传送给启动Gradle的jvm,作为一个系统属性被jvm使用

task

默认,每个新创建的task都是org.gradle.api.DefaultTask类型的。

基本使用

Task接口提供了俩个相关的方法来声明task动作,doFirst(闭包),doLast(闭包)

1
2
3
4
5
6
7
8
9
10
11
12
version = '0.1-SNAPSHOT'

task printVersion{
	doLast{
		println "Version $version"
	}
}

#为printVersion添加一个前缀action
printVersion.doFirst {println "first action"}
#为printVersion添加一个后缀action,没错,符号<<是doLast的简写
printVersion << {println "last action"}

dependsOn

定义task依赖关系

1
2
3
4
5
6
7
task a << {println "a"}
task b << {println "b"}

// 实际上写在参数位或者函数体内,都一样,都是局部变量
task c(dependsOn:[a,b]){
	println "c"
}

type

type指定的类,实际上像是给task继承某个类,就是面向对象的继承特性,这样不用重复写相似的task,以下是一个自定的task

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class ReleaseVersionTask extends DefaultTask {
	@Input Boolean release //通过org.gradle.api.tasks包下的注解来声明输入输出
	@OutputFile File destFile
	ReleaseVersionTask(){
		group = 'versioning'
		description = 'Makes Project a release version.'
	}
	@TaskAction //使用注解声明执行代码,
	void start(){
		project.version.release = true
		ant.propertyfile(file: destFile){
			entry(key: 'release', type: 'string',operation: '=',value:'true')
		}
	}
}
1
2
3
4
task a(type: ReleaseVersionTask){
	release = true
	destFile = versionFile
}

当然,gradle也有内置的type,比如Zip

1
2
3
4
5
6
7
8
9
10
11
task createDistribution(type: Zip, dependsOn: makeReleaseVersion){
	from war.outputs.files //依赖推断

	from(sourceSets*.allSource){
		into 'src'
	}

	from(rootDir){
		include versionFile.name
	}
}

或者Delete

1
2
3
4
task clean(type: Delete){
	delete rootProject.buildDir
	delete new File(rootDir,DEFAULT_BUILD_DIR_NAME)
}

Gradle生命周期

  • 初始化,从settings.gradle创建项目数,确定project对象
  • 配置,对project对象进行配置,确定依赖和顺序
  • 执行,执行project内的task

hook

gradle提供了很多api,用于在各个生命周期各个节点提供hook操作

settings.gradle

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
include ':app'
rootProject.name = 'TestAndroid'

// 在初始化前就已经调用了 buildStarted 方法,所以在初始化阶段无法回调的到.
gradle.buildStarted {
    println 'buildStarted......'
}
// 1.初始化阶段
gradle.settingsEvaluated {
    println '初始化阶段 settingsEvaluated'
}
gradle.projectsLoaded  {
    println '初始化阶段 projectsLoaded'
}
// 2.配置阶段
gradle.beforeProject {
    println '配置阶段 beforeProject --- in settings.gradle'
}

build.gradle

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
// 1.自定义任务
task t1 {
    println 't1 configuration'
    doLast {
        println 't1 execute doLast'
    }
    doFirst {
        println 't1 execute doFirst'
    }
}
// 2.配置阶段
gradle.beforeProject {
    println '配置阶段 beforeProject'
}
project.beforeEvaluate {
    println '配置阶段 beforeEvaluate'
}
gradle.afterProject {
    println '配置阶段 afterProject'
}
project.afterEvaluate {
    println '配置阶段 afterEvaluate'
}

// 所有项目的build.gradle执行完毕
gradle.projectsEvaluated {
    println '配置阶段 projectsEvaluated'
}

// task依赖关系图建立完毕
gradle.taskGraph.whenReady {
    println '配置阶段 whenReady'
}
// 3.执行阶段
gradle.taskGraph.beforeTask {
    println "执行阶段 beforeTask"
}
gradle.taskGraph.afterTask {
    println "执行阶段 afterTask "
}
// 4.build结束
gradle.buildFinished {
    println '构建结束 buildFinished'
}

dependencies && repositories

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//从上到下依次连接maven仓库,如果失败,就找下一个
repositories {
	maven {
		url prop_MavenUrl
		credentials{
			username user
			password passwd
		}
	}
	maven{
		url "gradle/repo"
	}
}

dependencies {
	classpath "com.android.tools.build:gradle:${prop_gradleVersion}"
}

buildScript

buildScript代码块中,一般是配置gardle脚本自身使用的资源,相当于执行python脚本需要import一些仓库,一般buildScript中都是配置dependencies和repositories,然后就可以在gradle脚本中importr相关仓库,执行命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
buildscript {
    repositories {
        mavenLocal()
        mavenCentral()
    }

    dependencies {
        classpath 'org.apache.commons:commons-csv:1.0'
    }
}

import org.apache.commons.csv.*

task printCSV() {
    doLast {
        def records = CSVFormat.EXCEL.parse(new FileReader('config/sample.csv'))
        for (item in records) {
            print item.get(0) + ' '
            println item.get(1)
        }

    }
}

apply

实际上是类似python的import了,都是用于导入其他包

1
2
3
4
5
//导入本地../gradle/disableueslesstask.gradle这个gradle脚本里面的东西
apply from '../gradle/disableueslesstask.gradle'

//导入第三方插件,这个就会从buildScript中定义的repository中去查找了
apply plugin: 'com.android.library'

android

现在,我对gradle的使用,主要就是用来构建android的项目,当引用’com.android.library’的时候,就可以使用android块了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
android {
	compileSdkVersion prop_compileSdkVersion //定义编译版本,prop_compileSdkVersion一般都是在构建命令时使用-P指定
	buildToolsVersion prop_buildToolsVersion
	resourcePrefix project.name + "_" // 限定xml资源的前缀,避免不同项目之间资源文件冲突

	defaultConfig { //默认配置
		minSdkVersion prop_minSdkVersion
		targetSdkVersion prop_targetSdkVersion
		versionCode 1
		versionName "1.0"

		testInstrumentationRunner "androidx.test.runner.AndroidJunitRunner" //运行junit测试,AndroidJunitRunner支持junit3和junit4
		consumerProguardFiles "consumer-rules.pro" //支持aar中独立配置混淆文件的方法,以便于他人引用aar的时候不需要再进行混淆
	}

	buildTypes { //默认会有debug和release,对应的task就是assembleDebug和assembleRelease,这里就重写了这俩个块,当然也可以自行定义其他的块
		debug {
			matchingFallbacks = ['release','debug'] // 定在子模块中没找到对应的构建类型时要加载哪个类型,当执行gradle assembleDebug 构建 debug 版本时,而恰巧某个子模块又没有定义 debug 版本,则会一一按照你指定的 matchingFallbacks 从前往后依次寻找,直到类型匹配。
			minifyEnabled false // 是否开启混淆,debug模式下不能开启,所以选择false
			proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'),'proguard-rules.pro' // 配置混淆文件
		}
		release{
			matchingFallbacks = ['release','debug']
			minifyEnabled false
			proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'),'proguard-rules.pro'
		}
	}

	compileOptions { // 编译选项参数
		encoding 'UTF-8'
		sourceCompatibility JavaVersion.VERSION_1_8 // 指定编译编译.java文件的jdk版本
		targetCompatibility JavaVersion.VERSION_1_8 // 确保class文件与targetCompatibility指定版本,或者更新的java虚拟机兼容
	}

	kotlinOptions {
		jvmTarget = "1.8"
	}
}

多项目

实际上,一般都是多项目一起构建的,这个时候,查看setting.gradle文件就知道一共有多少个项目了,

如下

1
2
3
4
include ':model'
include ':main'
include ':app'
rootProject.name = "RUOK"

android项目使用的是分层布局,使用包括其他项目的关键字是include,如果是平面布局,包括与根项目同一嵌套层次的项目,需要使用includeFlat方法,要使用includeFlat,平面布局

gradle多项目 说明:https://blog.csdn.net/weixin_38062353/article/details/82719968