文章

02.Gradle生命周期

02.Gradle生命周期

Gradle 生命周期

Gradle 生命周期阶段

b5ooe

kt51h
Gradle 的执行分为三大阶段: Initialization -> Configuration -> Execution

阶段一: Initialization 初始化

Initialization 阶段主要目的是初始化构建, 它又分为两个子过程, 一个是执行 Init Script, 另一个是执行 Setting Script.

Init script (init.gradle.kts)

Initialization Scripts

Init script 会读取全局脚本 (类似于系统 /etc/init.d), 主要作用是初始化一些全局通用的属性, 例如获取 Gradle User Home 目录, Gradle version 等. 一般而言, 我们很少在 init script 中添加内容. Init script 执行顺序为:

  • $GRADLEUSERHOME/init.Gradle (. Kts)
  • $GRADLEUSERHOME/init. D/[*. Gradle (. Kts)]

由于 init script 主要任务是全局 Gradle 配置, 因此 Api 分为三大部分: 获取全局属性, 项目配置, 生命周期 Hook.

  1. Gradle 环境相关的属性gradleHomeDir/gradleUserHomeDir/gradleVersion
  2. 构建相关的全局属性: 我们从中可以获取 Gradle User Home, current/project dir, 所有 system/project properties, 是否开启 scan, 是否 offline 等所有命令行参数
  3. rootProject 可以获取当前构建的根项目对象.
  4. taskGraph 可以获取当前构建的 task graph. 这个对象只有在收到 taskGraph.whenReady { … } 后才具有内容, 在此之前是个空壳对象.

Setting Script (setting.gradle[.kts])

Setting Script 指的是项目根目录下的 settings.gradle(.kts). 所有需要被构建的模块都需要在 setting script 中注册, 因此它的作用是描述 “ 当前构建所参与的模块 “, 本机任何位置的项目都可以通过 setting script 被引入到当前构建中.
setting script 承担了统筹所有模块的重任, 因此 api 主要是在操作所参与构建的模块以及管理构建过程需要的插件

Settings

settings.gradle 里面的配置和方法调用委托的是 Settings 对象。

在 Gradle 构建时会创建一个 Settings 实例,并根据它执行设置文件。Settings 实例和 settings.gradle 文件是一对一的对应关系。

Settings:声明实例化和配置参与构建 Project 实例的层次结构所需的配置。

项目管理 include

Gradle 支持单项目或多项目构建:

  • 单项目构建,settings.gradle 文件是可选的;
  • 多项目构建,settings.gradle 文件是必需的,且必须位于项目的根目录下;
1
2
3
4
5
6
7
// 通过 rootProject.name 强制指定项目名称
rootProject.name = "main"

include(":app", ":libs:someLibrary")

include(":anotherLibrary")
project(":anotherLibrary").projectDir = File(rootDir, "../another-library")
  1. 项目名称中 : 代表项目的分隔符, 类似路径中的 “/”。 如果以 : 开头则表示相对于 root project
  2. 如果子项目不在根项目目录下时则必须使用路径描述, 而不可以使用 “`..:foo” 这种项目相对路径描述:
插件管理 pluginManagement

通过 settings.pluginManagement 相关接口实现的

  • repositories: plugin 仓库设置

在 build script 中通过 plugins {…} 引入插件的时候, 默认只从 Gradle 官方插件仓库 查找. 如果我们的插件不在官方仓库, 就需要在这里指定查找的仓库:

1
2
3
4
5
6
// setting script,pluginManagement需要放在第一行
pluginManagement {
    repositories { // repositories指定了插件所需要的下载仓库地址。如果自定义的插件发布在私有仓库,就需要在这里加上私有仓库的地址才可以找到你的插件
        maven(url = "../maven-repo")
    }
}
  • resolutionStrategy: Plugin 模块替换

pluginManagement 还支持设置 plugin 的决议策略:

1
2
3
4
5
6
7
8
9
10
// setting script
pluginManagement {
    resolutionStrategy {
        eachPlugin {
            if (requested.id.id == "org.gradle.sample") {
                useModule("org.gradle.sample:sample-plugins:1.0.0")
            }
        }
    }
}

看看 PluginResolutionStrategy 源码:

1
2
3
4
5
@HasInternalProtocol  
public interface PluginResolutionStrategy {  
	void eachPlugin(Action<? super PluginResolveDetails> rule);  
	}
}

PluginResolutionStrategy 允许在 PluginRequest 之前对其进行修改,并有唯一回调 eachPlugin,eachPlugin 的参数类型是 PluginResolveDetails 类型的闭包。

PluginResolveDetails:

1
2
3
4
5
- getRequested:获取请求的插件,返回PluginRequest对象,包含id、version、module信息;
- useModule:设置插件的模块;
- useVersion:设置插件的版本;
- getTarget:请求的目标插件;
- plugin 设置统一版本

插件替换主要用到的就是 useModule 方法:

1
2
3
4
5
6
7
8
9
pluginManagement {
    resolutionStrategy {
        eachPlugin {
            if (requested.id.id == "org.gradle.sample") {
                useModule("com.hacket.plugin:gradlexxx:1.0")
            }
        }
    }
}

除了替换 module 以外, 还可以在这里设置版本号,用 useVersion:

1
2
3
4
5
6
7
8
9
10
// setting script
pluginManagement {
    resolutionStrategy {
        eachPlugin {
            if (requested.id.id == "com.dorongold.task-tree") {
                useVersion("1.4")
            }
        }
    }
}

设置过版本后, 在所有的 build script 中通过 plugins {…} 引入插件则无需再次指定版本.

依赖 dependencyResolutionManagement

dependencyResolutionManagement 里面的 repositoriesMode,即 Gradle 对于 allprojects { } 和 subprojects { }中的依赖解析策略。

1
2
3
4
5
6
7
dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        google()
        mavenCentral()
    }
}

repositoriesMode:

  • PREFER_PROJECT:默认值,优先使用 build.gradle 中的 repositories { },忽略 settings.gradle 中的 repositories { }
  • PREFER_SETTINGS:优先 settings.gradle 中的 repositories { } ,忽略 build.gradle 中的 repositories { }
  • FAIL_ON_PROJECT_REPOS:表示在 build.gradle 中声明的 repositories { } 会导致编译错误;

如果只有 app 模块,可以把仓库地址都写在 dependencyResolutionManagement>repositories 里面,如果有多个模块,且依赖差别很大,还是建议分开写

如何寻找 settings.gradle?
  1. 首先会在项目的根目录下找 settings.gradle 文件,如果没找到,则作为单项目构建。
  2. 如果找到了,会再次校验 include 配置的合法性,不合法,则继续作为单项目构建,合法,则作为多项目构建。

阶段二:Configuration 配置

在 Configuration (配置) 阶段,Gradle 会评估构建项目中包含的所有构建脚本,随后应用插件、使用 DSL 配置构建,并在最后注册 Task,同时惰性注册它们的输入,因为并不一定会执行。

注意:无论请求执行哪个 Task,配置阶段都会执行。所以为了保持构建简洁高效,要避免在配置阶段执行任何耗时操作,类似 android 里面的 onDraw 方法。推荐用 register 替代 create 来创建 Task

Build Script

Build Script 就是模块目录下的 build.gradle(.kts). 每个模块都会有一个 build script 来配置当前模块的构建信息:

  • 根目录模块的 build script 叫做 root build script
  • 其他子模块的 build script 叫做 module build script.

单模块构建的执行流程大致为: init script -> setting script -> build script

而多模块的构建流程, 比单模块多了一步: init script -> setting script -> root build script -> build script

Gradle 构建时,会根据 Settings 对象解析出来的项目结构为每个项目都创建一个 Project 对象,Project 对象和 build.gradle 文件之间存在一对一的关系。

在 Gradle 生成 Task 依赖关系图之前,Project 对象还做了几件事:

  • 引入插件
  • 配置属性
  • 编译依赖
引入插件

build script 背后是 Project 类型的对象, plugins 是 Project 的一个方法, 用于设置当前模块所使用的插件.

plugins 闭包中还可以通过 version 指定插件的版本, 以及 apply 来决定是否立刻应用插件:

1
2
3
4
5
// plugins是Project对象的一个方法,用于设置当前模块所使用的插件
plugins {
    id("com.dorongold.task-tree")   version "1.4"
    id("com.dorongold.task-tree")   version "1.4"   apply false
}
配置属性

配置属性,就是对引入的插件进行配置。

  1. 插件属性
    build script 中并没有 android {…} 这个 dsl 属性, 这是 plugin 提供的. 一旦应用了某个插件, 就可以使用插件提供的 dsl 对其进行配置, 从而影响该模块的构建过程。这些插件提供的属性配置 dsl 就相当于插件 init 函数的参数, 最终传入到插件中. 当构建执行的时候就会根据配置对当前模块进行编译.
1
2
3
4
5
6
7
8
9
10
11
plugins {
    id("com.android.application")
}

android {
    compileSdkVersion(28)

    defaultConfig {
        // ....
    }
}
  1. 内置属性
    Project 对象 本身也提供了很多用于配置构建的 dsl. 我们来看几个常用的:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
repositories {
    maven {
        url = uri(...)
    }
}
// 如果 maven 仓库需要认证, 则通过 credentials 添加用户名密码:
repositories {
    maven {
        url = uri(...)

        credentials {
            username = "joe"
            password = "secret"
        }
    }
}
  1. 设置自定义变量: ext
    ext 即是 project 对象的一个扩展属性 (ext[“foo”] = …) 又是一个扩展方法 (ext {…}). 它类似于 Map, 可以随意添加 key-value, 相同 key 的 value 会发生覆盖.

在 Kotlin 脚本中, 除了 ext 还有一个 extra 的变量

编译依赖

dependencies { } 里面除了官方库之外,我们还经常在里面添加所需要的三方库,比如 okhttp、glide 等等。

1
2
3
4
5
6
7
8
dependencies {

    implementation 'androidx.core:core-ktx:1.7.0'
    implementation 'androidx.appcompat:appcompat:1.4.1'
    implementation 'com.google.android.material:material:1.5.0'
    
    // ...
}

在多项目构建中, 通常 repositories 出现在 root build script 中, 而 module build script 中只包含 dependencies {…} 部分

build script 之间的引用及依赖

默认情况下, 所有的模块是按照字母序进行 evaluate 的. 如果某个模块依赖另一个模块, 则需要使用 evaluationDependsOn 指明依赖关系, 这样被依赖的模块就会优先被 evaluate.

项目属性 vs. 额外属性
项目属性 -P

项目属性 是 Project 上的一个类似 Map 结构的对象属性. 只不过它是只读的, 通过命令行 -P 配置.
我们往往会通过 -P 实现动态的构建参数. 例如, 向构建脚本传入密码等参数:

1
gradle -Ppwd=secret-text ...

这时, 在 build script 中即可通过 property(…) 方法获取到 pwd 的值, 从而防止密码提交到 vcs 而泄漏.

1
2
3
4
5
6
7
8
9
10
repositories {
    maven {
        url = uri(...)

        credentials {
            username = "joe"
            password = property("pwd")
        }
    }
}

案例:

1
2
3
// build.gradle中配置
def pwd = property("pwd")
println("pwd=$pwd")

使用 -P 参数:

1
./gradlew -Ppwd=123  clean
额外属性 ext

Gradle 默认为我们配置了一个 key 为 ext 的特殊值, 称为额外属性. 额外属性也是一个类似 Map 的结构:
m80wf
额外属性最常见的场景是在一个构建过程中定义公共的变量, 例如: 在多模块构建中统一依赖的版本:

1
2
3
4
5
6
7
8
9
10
// root build.gradle.kts定义
ext {
    set("kotlin_version", "1.3.50")
}

// xxx/build.gradle.kts使用
dependencies {
    // ...
    implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk7:${property("kotlin_version")}")
}

这样多个版本就可以公用一个变量来统一依赖版本了.

阶段三:Execution 执行

当完成任务依赖图后, Gradle 就做好了一切准备, 然后进入 Execution 阶段. 这个阶段才真正进行编译和打包动作. 对于 Java 而言是调用 javac 编译源码, 然后打包成 jar. 对于 Android 而言则更加复杂些. 这些差异来源于我们应用的插件

在 Execution (执行) 阶段,Gradle 会执行构建所需的 Task 集合。

其实这个阶段才是真正的编译打包,于 Android 而言,比如我们常见的 compileDebugJavaWithJavac、mergeDebugNativeLibs 等等。

Gradle 生命周期监听/Hook

Project 提供的一些生命周期回调方法:

1
2
3
4
afterEvaluate(closure);
afterEvaluate(action);
beforeEvaluate(closure);
beforeEvaluate(action);

Gradle 提供的一些生命周期回调方法:

1
2
3
4
5
6
7
8
9
afterProject(closure)afterProject(action)
beforeProject(closure)beforeProject(action)
buildFinished(closure)buildFinished(action)
projectsEvaluated(closure)projectsEvaluated(action)
projectsLoaded(closure)projectsLoaded(action)
settingsEvaluated(closure)settingsEvaluated(action)
addBuildListener(buildListener)
addListener(listener)
addProjectEvaluationListener(listener)

Initialization Hook (Gradle、Settings 对象可用)

gradle.settingsEvaluated (Setting script 执行结束)

当 settings.gradle(.kts) 被 evaluate 完毕, 此时已经有初始化过的 Settings 对象.
通过 gradle.settingsEvaluated 方法添加 hook, 例如在 setting.gradle(.kts) 中:

1
2
3
4
5
6
// init.gradle.kts or settings.gradle.kts
// 在settings.gradle初始化完毕后调用
gradle.settingsEvaluated { // it为Settings对象
    Settings settings = it
    println("[settings.gradle] settingsEvaluated init end rootDir=${settings.rootDir}")
}

这个 hook 中可以获取到配置完毕的 Settings 对象。我们通常在这里管理所有构建的插件。

目前我们只能够使用 gradle 和 settings 对象。

gradle.projectsLoaded (创建 Project 对象)

projectsLoaded 是紧接着 settingsEvaluated 的 hook 方法. 我们可以通过 gradle.projectsLoaded 方法添加 hook, 例如在 setting.gradle(.kts) 中:

1
2
3
4
5
// init.gradle.kts or settings.gradle.kts
gradle.projectsLoaded { // it是Gradle对象
    Gradle gradle = it
    println("[settings.gradle] projectsLoaded. gradleVersion=${gradle.getGradleVersion()}.")
}

projectsLoaded 回调时已经根据 setting script 创建了各个模块的 Project 对象

这时的 project 对象包含了项目的基本信息, 但是尚未被 build script 配置. 因此, 类似于 android {….} 这种在 build.gradle(.kts) 的配置都是取不到的

Configuration Hook (Gradle、Settings 和 Project 可用)

Configuration 阶段, 用于初始化和配置参与到当前构建的所有模块。
Gradle 首先读取 root build script(根目录下 build.gradle(.kts)), 然后是各个子模块。每个子模块的生命周期都一样. 执行的顺序默认是根据模块名的字母序, 可以通过 evaluationDependsOn 设置依赖关系。

Build script 执行前(gradle.beforeProject/allprojects.beforeEvaluate)

在每个 build script 被执行前都会触发对应模块的 beforeEvaluate 和 beforeProject.

  1. gradle.beforeProject 为所有 project 设置 hook。
  2. 虽然 beforeProject/beforeEvalute 属于 project 的生命周期, 但是此时 build script 尚未被加载, 所以 beforeEvaluate/beforeProject 的设置依然要在 init script 或 setting script 中进行。
  3. 不要在 build script 中使用 project.beforeEvaluate 方法. 该 hook 点在执行到 build script 的内容是已经走过了, 所以不会生效
gradle.beforeProject

在各个 module 的 configuration 前执行

1
2
3
4
5
// init.gradle.kts or settings.gradle.kts
gradle.beforeProject {
    Project project = it
    println("[settings.gradle] === beforeProject ${project.name}")
}

输出:

1
2
3
4
5
> Configure project :
[settings.gradle] === beforeProject GradleDemos

> Configure project :app
[settings.gradle] === beforeProject app
gradle.allprojects beforeEvaluate

在各个 module 的 configuration 前执行,同 gradle.beforeProject

1
2
3
4
5
6
// init.gradle.kts or settings.gradle.kts
gradle.allprojects{
    beforeEvaluate {
        println("[settings.gradle]===  allprojects beforeEvaluate ${it.name}")
    }
}

输出:

1
2
3
4
5
> Configure project :
[settings.gradle]===  allprojects beforeEvaluate GradleDemos

> Configure project :app
[settings.gradle]===  allprojects beforeEvaluate app

Build script 执行后(gradle.afterProject/allprojects.afterEvaluate)

每当一个 build.gradle(.kts) 被执行完毕, 都会产生 afterEvaluate 回调, 代表着 project 被 evaluate 完成. 从此, project 对象内容完整了, 即: 当前 build.gradle(.kts) 中所有的配置项都能够被访问。

一般而言, 我们都会在 build script 中为当前模块配置 afterProject/afterEvaluate;也可以在 settings.gradle 中配置:

1
2
3
4
5
6
7
8
9
10
// init.gradle.kts or settings.gradle.kts
gradle.allprojects{
    beforeEvaluate {
        println("[settings.gradle]===  allprojects beforeEvaluate ${it.name}")
    }
}
gradle.afterProject {
    Project project = it
    println("[settings.gradle] === afterProject ${project.name}")
}

输出:

1
2
3
4
5
6
7
> Configure project :
[settings.gradle] === afterProject GradleDemos
[settings.gradle]===  allprojects afterEvaluate GradleDemos

> Configure project :app
[settings.gradle] === afterProject app
[settings.gradle]===  allprojects afterEvaluate app

gradle.afterProject/allprojects.afterEvaluate 可以在 settings.gradle 中配置,也可以在 root build.gradle 中配置,后者配置的话那么对于 root build.gradle 本身 beforeEvaluate/beforeProject 加载就打印不出来因为此时已经加载了,afterEvaluate/afterProject 可以正常加载。

projectsEvaluated (所有 Project 配置结束)

projectsEvaluated 是在所有的 build script 都执行完毕后回调

1
2
3
4
5
// init.gradle.kts or settings.gradle.kts
gradle.projectsEvaluated {
    Gradle gradle = it
    println("[settings.gradle] === projectsEvaluated. gradleVersion=${gradle.getGradleVersion()}.")
}

生成 Task Graph

Gradle 的核心逻辑就是根据 task 的依赖关系生成有向无环图, 然后依次执行图中的 task。 这个 task graph 就是在这个时机生成。

Gradle 没有提供直接的方法设置 hook, 也需要通过 addListener 添加:

1
2
3
4
5
6
7
// init.gradle.kts or settings.gradle.kts

gradle.addListener(object : TaskExecutionGraphListener {
    override fun graphPopulated(graph: TaskExecutionGraph) {
        ....
    }
})

Gradle 专门有一个 taskGraph 对象表示任务图. 我们同样可以使用 taskGraph.whenReady 和 addTaskExecutionGraphListener(这两个函数底层是同一套实现, 作用完全一致) 添加 hook:

1
2
3
4
5
// init.gradle.kts or settings.gradle.kts

gradle.taskGraph.whenReady {
    ....    
}

Execution Hook

Task 执行前/后: TaskExecutionListener

Gradle 对每个 task 执行前/后的 hook 点:

1
2
3
4
5
6
7
8
9
// init.gradle.kts or settings.gradle.kts
gradle.addListener(object : TaskExecutionListener {
    override fun beforeExecute(task: Task) {
        // ....
    }
    override fun afterExecute(task: Task, state: TaskState) {
        // ....
    }
})

对于 beforeExecute 而言, 由于还没有真正开始执行 actions, 这时我们还可以对 actions 进行增删改, 从而改变 task 的行为。

Actions 执行前/后: TaskActionListener

Gradle 的 task 是很多 action 的集合, 每个 action 才是执行期间真正运行的代码。
这个 hook 的调用时机位于每个 task 的 beforeExecute 之后或者 afterExecute 之前:

1
2
3
4
5
6
7
8
9
10
// init.gradle.kts or settings.gradle.kts

gradle.addListener(object : TaskActionListener {
    override fun beforeActions(task: Task) {
        ....
    }
    override fun afterActions(task: Task) {
        ....
    }
})

既然有了 TaskExecutionListener 还会有 TaskActionListener 呢? 这是由于如果某个 task 之前执行并被缓存 (增量编译或者 build cache), 那么 actions 则不会再次被执行. 也就是说, 每次构建过程中, task 的执行一个都不会少, 但是 actions 只会根据需要执行。

构建开始 1 结束: buildFinished

当所有 task 都执行完毕, 整个构建也宣告结束:

1
2
3
4
5
6
7
// init.gradle.kts or settings.gradle.kts
gradle.buildStarted {
    
}
gradle.buildFinished {
    // ....
}

在 gradle 对象中, 大部生命周期都提供了直接的 hook 方法, 例如上面提到的 settingsEvaluated, projectsLoaded 等。 除此之外, gradle 对象还提供了 addListeneraddBuildListener 两个添加生命周期的方法。

Gradle 生命周期总结

Android Gradle 构建流程:

1
settings.gradle → root build.gradle → app build.gradle → lib build.gradle

settings.gradle

root build.gradle

subprojects

配置所有子 module(Configure project 阶段)

  • 源码
1
2
// Project
void subprojects(Action<? super Project> action)
  • 示例
1
2
3
4
// root build.gradle
subprojects { subProject ->
    println("--------->>>>>>>>>>> [root build.gradle] subprojects ${subProject.name}")
}

输出:

1
2
3
--------->>>>>>>>>>> [root build.gradle] subprojects app
--------->>>>>>>>>>> [root build.gradle] subprojects mylibrary1
--------->>>>>>>>>>> [root build.gradle] subprojects mylibrary2
  • 应用
    1. 为所有的 module 应用相同的配置
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
subprojects { subProject ->
    apply from: "$rootDir/build_function.gradle"
    apply plugin: 'com.android.library'
    apply plugin: 'maven-publish'
    android {
        compileSdkVersion 31
        // ...
    }
    afterEvaluate {
        publishing {
            publications {
                release(MavenPublication) {
                    from subProject.components.release
                    groupId = projectConfig.groupId
                    artifactId = projectConfig.artifactId
                    version = projectConfig.versionName
                }
            }
            repositories {
                maven {
                    url = localMavenUrl
                }
            }
        }
    }
}

allprojects

配置自己及所有子 module(Configure project 阶段)

  • 源码
1
2
// Project
void allprojects(Action<? super Project> action)
  • 示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// root build.gradle
allprojects { project ->
    println("--------->>>>>>>>>>> [root build.gradle] allprojects ${project.name}")
}

// 也可以用gradle变量引用
gradle.allprojects { it->
    println("[settings.gradle]=== allprojects ${it.name}")
    it.beforeEvaluate {
        println("[settings.gradle]===  allprojects beforeEvaluate ${it.name}")
    }
    it.afterEvaluate {
        println("[settings.gradle]===  allprojects afterEvaluate ${it.name}")
    }
}

输出:

1
2
3
4
--------->>>>>>>>>>> [root build.gradle] allprojects GradleTest
--------->>>>>>>>>>> [root build.gradle] allprojects app
--------->>>>>>>>>>> [root build.gradle] allprojects mylibrary1
--------->>>>>>>>>>> [root build.gradle] allprojects mylibrary2

比 subprojects 多了 GradleTest

Gradle 变量

Gradle 提供的一些生命周期回调方法:

1
2
3
4
5
6
7
8
9
10
11
- StartParameter getStartParameter()
- void allprojects(Action<? super Project> action)
- afterProject(closure)afterProject(action)
- beforeProject(closure)beforeProject(action)
- buildFinished(closure)buildFinished(action)
- projectsEvaluated(closure)projectsEvaluated(action)
- projectsLoaded(closure)projectsLoaded(action)
- settingsEvaluated(closure)settingsEvaluated(action)
- addBuildListener(buildListener)
- addListener(listener)
- addProjectEvaluationListener(listener)

Project 变量

Project 提供的一些生命周期回调方法:

1
2
- beforeEvaluate(closure)/beforeEvaluate(action)
- afterEvaluate(closure)/afterEvaluate(action)

beforeEvaluate/afterEvaluate

module 配置前和配置的监听

1
2
3
4
5
6
7
8
9
10
// settings.gradle
gradle.allprojects { p->
    println("[settings.gradle]=== allprojects ${it.name}")
    p.beforeEvaluate {
        println("[settings.gradle]===  allprojects beforeEvaluate ${it.name}")
    }
    p.afterEvaluate {
        println("[settings.gradle]===  allprojects afterEvaluate ${it.name}")
    }
}

StartParameter 启动参数

获取 tasks

1
2
// settings.gradle
println("gradle.startParameter.taskNames=${gradle.startParameter.taskNames}")

输出:

1
2
3
./gradlew clean assembleDebug 

gradle.startParameter.taskNames=[clean, assembleDebug]
  • 应用
    debug 的 task 关掉某些插件
1
2
3
4
5
6
7
8
9
10
11
12
13
buildscript {
    ext {
        develop = gradle.startParameter.taskNames.any { it.toLowerCase().contains('debug') }
    }
    repositories {
        // ...
    }
    dependencies {
        if (!develop) { // 非debug下才依赖的插件
            // DataRanges插件, 对Activity/Fragment/Widgets进行埋点插桩, 开发时可忽略该操作
            classpath 'com.bytedance.applog:RangersAppLog-All-plugin:6.5.0'
        }
    }
本文由作者按照 CC BY 4.0 进行授权