Gradle学习笔记-Project

基于Gradle 7.3.3源码分析

可以通过执行./gradlew projects打印工程下所有Project。

Project对应着项目中的build.gradle文件,每个gradle文件被解析后都会生成一个Project对象。所有build.gradle中定义的属性及方法都可以通过Project进行调用。

graph TB
A(Project API组成) --- B(Project API)
A---C(管理Task及Task本身API)
A---D(Project属性API)
A---E(Gradle生命周期API)
A---F(Project下File相关API)
A---G(其他类型API)

Project相关API主要由以下几部分组成,它们分别有以下能力:

  • Project API:可以操作父Project以及管理子Project
  • Task相关API:可在Project下管理Task,包括新增、修改等
  • Project属性相关API:获取与设置Project相关属性及配置,包括ext设置
  • Project下File相关API:获取Project下文件路径以及对文件的操作等
  • Project生命周期API:可在Project对应生命周期下的操作
  • 其他API:配置项目依赖等

常用属性

每个build.gradle最后都会编译成一个Project对象,下面对应的API调用也都写在build.gradle中。

Project API文档

Project API

可获取父Project子Project,并可对他们进行操作

getAllprojects / allprojects

返回当前Project对象以及所有子Project的集合,后续可对获取的数据进行设置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//build.gradle 
//getAllprojects
project.getAllprojects().eachWithIndex{Project project , int index->
if(index == 0){
println("root Project is $project")
} else{
println("child Project is $project")
}
}

//allprojects
allprojects {
println(it)
}

输出结果

1
2
3
4
5
6
7
8
root Project is root project 'GradlePluginDemo'
child Project is project ':app'
child Project is project ':mylibrary'


root project 'GradlePluginDemo'
project ':app'
project ':mylibrary'

两者最终都是得到Project集合

getSubprojects / subprojects

返回所有子Project的集合,后续可对获取的数据进行设置

1
2
3
4
5
6
7
8
//build.gradle
project.getSubprojects().eachWithIndex { Project project, int index ->
println("child Project is $project")
}

subprojects {
println(it)
}

输出结果

1
2
3
4
5
6
child Project is project ':app'
child Project is project ':mylibrary'


project ':app'
project ':mylibrary'

两者最终都是得到所有子Project集合

getParent / getRootProject / getProject / project

返回的都是一个独立的Project对象

getParent:返回当前Project的父类,如果为Root Project,返回则为null

getRootProject:返回Root Project

getProject / project:返回当前工程对象,或根据name获取指定Project

1
2
3
4
5
6
//build.gradle
project("app",{
println("根工程 "+getRootProject())
println("父工程 "+getParent())
println("当前工程 "+getProject())
})

输出结果

1
2
3
根工程 root project 'GradlePluginDemo'
父工程 root project 'GradlePluginDemo'
当前工程 project ':app'

getChildProjects

返回所有直系子Project的集合,可以看作近似于getSubprojects

1
2
3
project.getChildProjects().each{
println("${it.key} : ${it.value}")
}

输出结果

1
2
app  : project ':app'
mylibrary : project ':mylibrary'

Task 相关API

Project下管理Task

task

创建一个Task,添加到Project

1
2
3
4
//build.gradle
task clean(type: Delete) {
delete rootProject.buildDir
}

getAllTasks

获取当前Project下所有Task,通过设置recursive判断是否需要子ProjectTask

1
2
3
4
5
6
//build.gradle
gradle.buildFinished {
rootProject.getAllTasks(false).each {
println("${it.key} and task is ${it.value}")
}
}

输出结果

1
root project 'GradlePluginDemo' and task is [task ':buildEnvironment', task ':clean', task ':cleanIdea', task ':cleanIdeaModule', task ':cleanIdeaProject', task ':cleanIdeaWorkspace', task ':components', task ':dependencies', task ':dependencyInsight', task ':dependentComponents', task ':help', task ':idea', task ':ideaModule', task ':ideaProject', task ':ideaWorkspace', task ':init', task ':javaToolchains', task ':model', task ':openIdea', task ':outgoingVariants', task ':prepareKotlinBuildScriptModel', task ':prii', task ':projects', task ':properties', task ':tasks', task ':wrapper']

getTasks

获取当前Project下所有Task,返回的对象为TaskContainer,可以对Task进行操作

1
2
3
4
5
6
//build.gradle
gradle.buildFinished {
rootProject.getTasks().all {
println(it)
}
}

getTasksByName

根据TaskName返回所有相关的Task

Project属性API

可以获取Project一些默认定义属性,也可以通过ext扩展自定义属性。

默认自定义属性

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
public interface Project extends Comparable<Project>, ExtensionAware, PluginAware {
/**
* The default project build file name.
*/

String DEFAULT_BUILD_FILE = "build.gradle";

/**
* The hierarchy separator for project and task path names.
*/

String PATH_SEPARATOR = ":";

/**
* The default build directory name.
*/

String DEFAULT_BUILD_DIR_NAME = "build";

String GRADLE_PROPERTIES = "gradle.properties";

String SYSTEM_PROP_PREFIX = "systemProp";

String DEFAULT_VERSION = "unspecified";

String DEFAULT_STATUS = "release";
...
}
  • DEFAULT_BUILD_FILE:默认读取配置文件
  • DEFAULT_BUILD_DIR_NAME:默认生成的build文件存放目录
  • GRADLE_PROPERTIES:自定义部分属性读取配置文件

扩展属性

通过ext实现扩展
1
2
3
4
5
6
7
8
9
10
11
12
//root build.gradle
ext {
compileSdkVersion = 29
buildToolsVersion = "29.0.3"
}

//module build.gradle
...
android {
compileSdkVersion rootProject.ext.compileSdkVersion

}

ext扩展属性过多,可以通过依赖额外Gradle文件进行统一管理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//version.gradle
ext {
android = [
compileSdkVersion : 30,
versionCode : 1,
versionName : '1.0.0',
]
}

//Root build.gradle
apply from: this.file('version.gradle')

//Module build.gradle
android {
compileSdkVersion rootProject.ext.android.compileSdkVersion
...
}

可以将一些字符串常量、数字常量等放于额外Gradle文件进行管理

配置在gradle.properties文件中

属性只可以用key=value的形式

1
2
3
4
5
6
7
8
//gradle.properties
...
isHaveVersion=true

//build.gradle
if(rootProject.hasProperty("isHaveVersion") ? isHaveVersion.toBoolean() : false){
println("taskss")
}

基于gradle.properties设置的扩展属性,主要有以下方法进行操作。

hasProperty

是否存在指定属性

findProperty

获取指定属性值

setProperty

设置指定属性值

Project下FileAPI

获取及操作当前Project下文件

无法进行跨工程调用

路径获取

获取指定目录路径

getRootDir

获取Root Project本地路径

getBuildDir

获取当前Project build文件存放路径

getProjectDir

获取当前Project本地路径

1
2
3
4
5
6
//build.gradle
afterEvaluate {
println("rootDir is ${getRootDir().absolutePath}")
println("buildDir is ${getBuildDir().absolutePath}")
println("projectDir is ${getProjectDir().absolutePath}")
}

输出结果

1
2
3
rootDir is /Users/xx/Projects/GradlePluginDemo
buildDir is /Users/xx/Projects/GradlePluginDemo/app/build
projectDir is /Users/xx/Projects/GradlePluginDemo/app

文件操作

file/files

定位文件

输入内容是以当前Project目录作为基础的相对路径信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//Root build.gradle
def printFile(List<String> fileNames) {
if (!fileNames.isEmpty()) {
try {
if (fileNames.size() == 1) {
println(file(fileNames[0]).absolutePath)
} else {
println(files(fileNames[0], fileNames[1]).files)
}
} catch (GradleException e) {
e.printStackTrace()
}
}
}

//调用
def list = new ArrayList()
list.add("build.gradle") //Users/xx/Projects/GradlePluginDemo/build.gradle
printFile(list)

list.add("gradle.properties") //Users/xx/Projects/GradlePluginDemo/gradle.properties
printFile(list)

files返回FileCollection,内部是文件的集合

copy/delete/mkdir

拷贝文件

1
2
3
4
5
6
7
8
9
10
copy {
from file("build.gradle") //文件(夹)来源路径
into "src/" //文件(夹)拷贝目的路径
exclude {
// 排除不需要拷贝的文件
}
rename {
// 对拷贝过来的文件进行重命名
}
}
fileTree/zipTree/tarTree

遍历文件

1
2
3
4
5
fileTree("src") { FileTree fileTree ->
fileTree.visit { FileTreeElement fileTreeElement ->
println "The file is $fileTreeElement.file.name"
}
}

使用fileTree将指定目录转换为文件树的形式,后续就可以获取到每一个树节点(文件)进行操作。

Project生命周期API

监听build.gradle加载生成Project前后

beforeEvaluate

build.gradle加载生成Project

在当前build.gradle调用监听是无效的,可以监听子Project

afterEvaluate

build.gradle加载生成Project

此时可以获取到当前Project配置的所有数据

其他API

依赖配置相关API

buildscript

配置核心项目依赖

配置在Root build.gradle

1
2
3
4
5
6
7
8
9
10
11
12
//Root build.gradle
buildscript {
repositories {
google()
jcenter()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:4.1.3'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
repositories

配置项目依赖的仓库

1
2
3
4
5
repositories {
google()
jcenter()
mavenCentral()
}
dependencies

配置项目的依赖信息

1
2
3
4
5
6
7
8
9
10
dependencies{
//本地aar/jar依赖
implementation fileTree(dir: 'libs', include: ['*.jar,*.aar'])
//本地module依赖
api project(":vc_common")
//远程仓库依赖
implementation 'com.github.chrisbanes:PhotoView:1.3.0'{
exclude group:'com.android.support' //避免冲突,移除内部相关依赖
}
}

substitute 可在远程仓库依赖本地Module依赖之间切换。

implementationapi的区别?

  • implementation该依赖方式依赖的库不会传递,依赖只在当前Module中生效
  • api该依赖方式依赖的库会传递,其他Module依赖了当前Module时,也可以使用依赖的库

外部命令执行

exec/javaexec

可执行外部命令,通过配置不同的运行环境来支持多种命令。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//build.gradle
exec {
try {
executable 'java'
args "-version"
println "The command execute is success"
} catch (GradleException e) {
println "The command execute is failed"
}
}

//或
exec {
commandLine('java','-version')
}

参考资料

Project官方文档

Gradle核心揭秘


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!