基于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 project.getAllprojects().eachWithIndex{Project project , int index-> if (index == 0 ){ println("root Project is $project" ) } else { println("child Project is $project" ) } } 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 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 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 task clean(type: Delete) { delete rootProject.buildDir }
getAllTasks
获取当前Project下所有Task
,通过设置recursive
判断是否需要子Project
的Task
1 2 3 4 5 6 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 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 { String DEFAULT_BUILD_FILE = "build.gradle" ; String PATH_SEPARATOR = ":" ; 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 ext { compileSdkVersion = 29 buildToolsVersion = "29.0.3" } ... android { compileSdkVersion rootProject.ext.compileSdkVersion }
若ext
扩展属性过多,可以通过依赖额外Gradle文件
进行统一管理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 ext { android = [ compileSdkVersion : 30 , versionCode : 1 , versionName : '1.0.0' , ] } apply from: this .file('version.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 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 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" ) printFile(list) list.add("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 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{ implementation fileTree(dir: 'libs' , include: ['*.jar,*.aar' ]) api project(":vc_common" ) implementation 'com.github.chrisbanes:PhotoView:1.3.0' { exclude group: 'com.android.support' } }
substitute
可在远程仓库依赖
与本地Module依赖
之间切换。
implementation
与api
的区别?
implementation
:该依赖方式依赖的库不会传递,依赖只在当前Module中生效
api
:该依赖方式依赖的库会传递,其他Module依赖了当前Module时,也可以使用依赖的库
外部命令执行 exec/javaexec
可执行外部命令,通过配置不同的运行环境来支持多种命令。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 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核心揭秘