这是一篇Gradle 进阶文章,我假设你已经会 gradle task,自定义plugin 开发。我会带你从源码分析Gradle的整体过程。建议你参照文章 反复阅读源码。文章是基于Gradle 6.7版本
一、 启动Gradle
在构建一个任务的时候,经常是通过这个命令 ./gradlew assembleDebug (AS 的按键 打包,也是通过gradlew 命令完成的),先来看下这个脚本最后执行的命令:
# eval 会先把其中的变量进行解析
# set -- 设置到参数中 ,可通过 $@ 来获取到
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
# 执行命令,$JAVACMD 根据本地的java环境变量 来得到该值
exec "$JAVACMD" "$@"
命令内容如下:
java -Xdock:name=Gradle -Xdock:icon=/Users/android/media/gradle.icns -Dorg.gradle.appname=gradlew -classpath /Users/android/gradle/wrapper/gradle-wrapper.jar org.gradle.wrapper.GradleWrapperMain :app:assembleUatDebug
最终是执行了gradle-wrapper.jar 的GradleWrapperMain 类,它主要有两个功能:
- 下载指定版本的Gradle
- 启动Gradle流程
下图是GradleWrapperMain的main函数的断点截图:
-
获取 gradle-wrapper.properties文件的路径 ,在
WrapperExecutor.forWrapperPropertiesFile
解析出gradle-wrapper.properties的信息 -
获取gradleUserHome 的路径,可通过命令行指定,默认是系统当前用户目录下的.gradle
下载指定版本的Gradle
1、从gradle-wrapper.properties 获取下载Gradle的URL
2、获取存储路径
- distDir -> /Users/01407714/.gradle/wrapper/dists/gradle-6.7-all/cuy9mc7upwgwgeb72wkcrupxe
- localZipFile -> /Users/01407714/.gradle/wrapper/dists/gradle-6.7-all/cuy9mc7upwgwgeb72wkcrupxe/gradle-6.7-all.zip
wrapper/dists -> 在 gradle-wrapper.properties中进行配置
gradle-6.7-all 下载文件名
cuy9mc7upwgwgeb72wkcrupxe -> Url 变换后的md5值
如果没有下载过,会下载,到上述文件夹的 临时文件 gradle-6.7-all.zip.part
启动Gradle流程
DefaultBuildOperationExecutor $run (RunnableBuildOperation 或者 CallableBuildOperation)
DefaultBuildOperationRunner run ->execute -> 最终执行上面这两个参数的run
BootstrapMainStarter的start 函数
执行到 org.gradle.launcher.GradleMain 会执行到 DefaultGradleLauncher 类的executeTasks函数,Gradle 整体的五个大生命周期,都是从这里开始的,
下面就从这里开始分析
二、 Gradle 的五大流程
以下五大点都是从 org/gradle/initialization/DefaultGradleLauncher.java 类作为起点来分析
2.1 LoadSettings
private void prepareSettings() {
if (stage == null) {
buildListener.buildStarted(gradle);
settingsPreparer.prepareSettings(gradle);
stage = Stage.LoadSettings;
}
}
主要任务:
1、生命周期接口回调 buildListener.buildStarted(gradle);
2、 执行init.gradle
3、查找setting.gradle 文件位置
4、解析gradle.properties
5、解析setting.gradle文件
6、创建 projectState,用于下一阶段创建Project
2.1.1 、生命周期接口回调
buildListener.buildStarted(gradle);
这个生命周期回调时期很早,所以在dsl 或自定义的plugin、task中都不会被调用,它是gradle内部使用的
2.1.2 、执行init.gradle
调用链
-> BuildOperationFiringSettingPreparer.prepareSettings
-> LoadBuild.run
-> DefaultSettingPreparer.preparerSetting
-> InitScriptHandler.executeScripts 从参数从获取到脚本名,并读取出文件
-> DefaultInitScriptProcessor.process 执行脚本
2.1.3 、查找setting.gradle 文件位置
调用链
BuildOperationFiringSettingPreparer.prepareSettings
-> LoadBuild.run
-> DefaultSettingPreparer.preparerSetting
-> CompositeBuildSettingsLoader.findAndLoadSettings
-> ChildBuildRegisteringSettingsLoader.findAndLoadSettings
-> CommandLineIncludedBuildSettingsLoader.findAndLoadSettings
-> SettingsAttachingSettingsLoader.findAndLoadSettings
-> DefaultSettingsLoader.findAndLoadSettings
-> SettingsLocation settingsLocation = buildLayoutFactory.getLayoutFor(new BuildLayoutConfiguration(startParameter));
查找顺序:
1、启动参数中查找是否指定了setting 文件
2、当前目录下查找
3、当前目录的master 下查找
4、往上一层的目录下查找
5、往上一层的目录master下查找
2.1.4 、解析gradle.properties
调用链,接上一小节
-> DefaultSettingsLoader.findAndLoadSettings
-> loadGradlePropertiesFrom
-> DefaultGradlePropertiesController.loadGradlePropertiesFrom
-> NotLoaded.loadGradlePropertiesFrom
-> DefaultGradlePropertiesLoader.loadGradleProperties -> loadProperties
解析gradle.properties 中的值,已map形式保存,赋值给DefaultGradleProperties ,它作为变量,被引用的链路
ScriptEvaluatingSettingProcessor-> DefaultGradlePropertiesController ->State -> DefaultGradleProperties
BuildOperationSettingsProcessor 的代理会引用到ScriptEvaluatingSettingProcessor,下一小节的调用链,可以看到
2.1.5 、解析setting.gradle
调用链,接上一小节
-> DefaultSettingsLoader.findAndLoadSettings
-> SettingsInternal settings = findSettingsAndLoadIfAppropriate(gradle, startParameter, settingsLocation, gradle.getClassLoaderScope());
-> BuildOperationSettingsProcessor.process
-> RootBuildCacheControllerSettingProcessor.process
-> SettingEvaluatedCallbackFiringSettingProcessor.process
-> ScriptEvaluatingSettingProcessor. applySettingsScript 解析出setting.gradle文件,通过ScriptPluginFactorySelector 创建BuildOperationScriptPlugin
->BuildOperationScriptPlugin.apply 编译脚本并执行
@Override
public SettingsInternal process(GradleInternal gradle,
SettingsLocation settingsLocation,
ClassLoaderScope baseClassLoaderScope,
StartParameter startParameter) {
Timer settingsProcessingClock = Time.startTimer();
Map<String, String> properties = gradleProperties.mergeProperties(emptyMap());
TextResourceScriptSource settingsScript = new TextResourceScriptSource(textFileResourceLoader.loadFile("settings file", settingsLocation.getSettingsFile()));
//setting.gradle 文件的信息 保存在SettingsInternal对象,其中包含了gradle.properties的信息
//此时,setting.gradle的内容还没被的处理
SettingsInternal settings = settingsFactory.createSettings(gradle, settingsLocation.getSettingsDir(), settingsScript, properties, startParameter, baseClassLoaderScope);
gradle.getBuildListenerBroadcaster().beforeSettings(settings);
applySettingsScript(settingsScript, settings);
LOGGER.debug("Timing: Processing settings took: {}", settingsProcessingClock.getElapsed());
return settings;
}
private void applySettingsScript(TextResourceScriptSource settingsScript, final SettingsInternal settings) {
ScriptPlugin configurer = configurerFactory.create(settingsScript, settings.getBuildscript(), settings.getClassLoaderScope(), settings.getBaseClassLoaderScope(), true);
//在这里编译执行脚本,这个函数在后面处理build.gradle 的时候还会遇到,在那里进行分析
configurer.apply(settings);
}
gradle.properties的信息 保存在settings的如下storage位置:
执行完后,会继续执行DefaultSettingsLoader.findAndLoadSettings 的后续代码setDefaultProject(spec, settings);
设置默认Project,它是根据启动Gradle的命令中指定的 项目路径,来决定哪个module 被设置为默认的
2.1.6 、创建 projectState,用于下一阶段创建Project
根据setting.gradle其中的内容添加project
调用链
BuildOperationFiringSettingPreparer.prepareSettings
-> LoadBuild.run
-> DefaultSettingPreparer.preparerSetting
-> CompositeBuildSettingsLoader.findAndLoadSettings
-> ChildBuildRegisteringSettingsLoader.findAndLoadSettings
-> CommandLineIncludedBuildSettingsLoader.findAndLoadSettings
-> SettingsAttachingSettingsLoader.findAndLoadSettings
-> DefaultProjectStateRegistry.registerProjects(gradle.getServices().get(BuildState.class)); 到这里settings 已经解析出,工程的项目,项目名称,项目路径等等
-> addProject
一个DefaultProjectDescriptor descriptor ,代表一个module,循环调用addProject ,把这些module,按照path,id,comId,多维度保存起来
private void addProject(BuildState owner, DefaultProjectDescriptor descriptor) {
Path projectPath = descriptor.path();
Path identityPath = owner.getIdentityPathForProject(projectPath);
ProjectComponentIdentifier projectIdentifier = owner.getIdentifierForProject(projectPath);
ProjectStateImpl projectState = new ProjectStateImpl(owner, identityPath, projectPath, descriptor.getName(), projectIdentifier);
projectsByPath.put(identityPath, projectState);
projectsById.put(projectIdentifier, projectState);
projectsByCompId.put(Pair.of(owner.getBuildIdentifier(), projectPath), projectState);
}
2.2、Configure
在网上你肯定看到过,Gradle 分为配置阶段和执行阶段,配置阶段指的就是Configure
private void prepareProjects() {
if (stage == Stage.LoadSettings) {
projectsPreparer.prepareProjects(gradle);
stage = Stage.Configure;
}
}
主要任务:
1、为每个module 创建Project
2、Evaluate
3、处理build.gradle
4、apply Plugin
2.2.1 为每个module 创建Project
注意,这里的Project 和AS 中的Project 不是一个概念
调用链:
BuildOperationFiringProjectsPreparer.prepareProjects
-> ConfigureBuild.run
->BuildTreePreparingProjectsPreparer.prepareProjects ->buildLoader.load(gradle.getSettings(), gradle)
-> NotifyingBuildLoader.load
-> ProjectPropertySettingBuildLoader.load
-> InstantiatingBuildLoader.load -> createProject
-> ProjectFactory.createProject (根据2.1.5 的ProjectState 来创建)
->attachDefaultProject
下面来看一下,ProjectFactory.createProject 的函数
private void createProjects(GradleInternal gradle, ProjectDescriptor rootProjectDescriptor) {
ClassLoaderScope baseProjectClassLoaderScope = gradle.baseProjectClassLoaderScope();
ClassLoaderScope rootProjectClassLoaderScope = baseProjectClassLoaderScope.createChild("root-project");
//在这里创建Project,这个project 对应的build.gradle 是根路径的
ProjectInternal rootProject = projectFactory.createProject(gradle, rootProjectDescriptor, null, rootProjectClassLoaderScope, baseProjectClassLoaderScope);
//设置根project,
gradle.setRootProject(rootProject);
//递归创建,子project
createChildProjectsRecursively(gradle, rootProject, rootProjectDescriptor, rootProjectClassLoaderScope, baseProjectClassLoaderScope);
}
private void createChildProjectsRecursively(GradleInternal gradle, ProjectInternal parentProject, ProjectDescriptor parentProjectDescriptor, ClassLoaderScope parentProjectClassLoaderScope, ClassLoaderScope baseProjectClassLoaderScope) {
//循环创建Project ,他们是在setting.gradle中声明的module。
for (ProjectDescriptor childProjectDescriptor : parentProjectDescriptor.getChildren()) {
ClassLoaderScope childProjectClassLoaderScope = parentProjectClassLoaderScope.createChild("project-" + childProjectDescriptor.getName());
ProjectInternal childProject = projectFactory.createProject(gradle, childProjectDescriptor, parentProject, childProjectClassLoaderScope, baseProjectClassLoaderScope);
createChildProjectsRecursively(gradle, childProject, childProjectDescriptor, childProjectClassLoaderScope, baseProjectClassLoaderScope);
}
}
下面是创建Project 的代码
@Override
public ProjectInternal createProject(GradleInternal gradle, ProjectDescriptor projectDescriptor, @Nullable ProjectInternal parent, ClassLoaderScope selfClassLoaderScope, ClassLoaderScope baseClassLoaderScope) {
Path projectPath = ((DefaultProjectDescriptor) projectDescriptor).path();
ProjectState projectContainer = projectStateRegistry.stateFor(owner.getBuildIdentifier(), projectPath);
//根路径的build.gradle 或是module 下的build.gradle
File buildFile = projectDescriptor.getBuildFile();
TextResource resource = textFileResourceLoader.loadFile("build file", buildFile);
ScriptSource source = new TextResourceScriptSource(resource);
//创建project,你会看到很多地方都是使用instantiator.newInstance 来创建一个对象
DefaultProject project = instantiator.newInstance(DefaultProject.class,
projectDescriptor.getName(),
parent,
projectDescriptor.getProjectDir(),
buildFile,
source,
gradle,
projectContainer,
gradle.getServiceRegistryFactory(),
selfClassLoaderScope,
baseClassLoaderScope
);
//评估前,需要执行的代码,下一小节会介绍评估的流程
project.beforeEvaluate(p -> NameValidator.validate(project.getName(), "project name", DefaultProjectDescriptor.INVALID_NAME_IN_INCLUDE_HINT));
if (parent != null) {
parent.addChildProject(project);
}
//所有的project 都会被添加到projectRegistry
projectRegistry.addProject(project);
projectContainer.attachMutableModel(project);
return project;
}
在2.1.5中只是确定了哪个module是默认的,但是它对应的Project 还没有,这里创建Project后,接着会调用InstantiatingBuildLoader.load ->attachDefaultProject
把它加入到GradleInternal中的默认Project中
2.2.2 Evaluate
调用链:
-> DefaultProjectsPreparer.prepareProjects 通过GradleInternal 获取到ProjectInternal
-> TaskPathProjectEvaluator. configureHierarchy 遍历ProjectInternal 中的每个project,解析其中的build.gradle
-> DefaultProject.evaluate. 获取evaluator 默认是LifecycleProjectEvaluator
-> LifecycleProjectEvaluator.evaluate org/gradle/configuration/project/LifecycleProjectEvaluator.java
-> EvaluateProject.run
-> ConfigureActionsProjectEvaluator.evaluate
EvaluateProject的run函数
@Override
public void run(final BuildOperationContext context) {
project.getMutationState().applyToMutableState(p -> {
// Note: beforeEvaluate and afterEvaluate ops do not throw, instead mark state as failed
try {
//设置状态
state.toBeforeEvaluate();
//业务逻辑在NotifyBeforeEvaluate,执行project 的BeforeEvaluate中的代码
buildOperationExecutor.run(new NotifyBeforeEvaluate(project, state));
if (!state.hasFailure()) {
state.toEvaluate();
try {
//执行到 ConfigureActionsProjectEvaluator.evaluate
delegate.evaluate(project, state);
} catch (Exception e) {
addConfigurationFailure(project, state, e, context);
} finally {
state.toAfterEvaluate();
//业务逻辑在NotifyAfterEvaluate,执行project 的AfterEvaluate中的代码
buildOperationExecutor.run(new NotifyAfterEvaluate(project, state));
}
}
if (state.hasFailure()) {
state.rethrowFailure();
} else {
context.setResult(ConfigureProjectBuildOperationType.RESULT);
}
} finally {
state.configured();
}
});
}
ConfigureActionsProjectEvaluator.evaluate 中有3次循环,分别调用如下函数
-> ConfigureActionsProjectEvaluator.evaluate
->PluginsProjectConfigureActions.execute 第一次循环
最终会应用这两插件
->project.getPluginManager().apply("org.gradle.help-tasks");
-> project.getPluginManager().apply("org.gradle.build-init");
->BuildScriptPeocessor.execute 第二次循环
-> BuildOperationScriptPlugin.apply 编译脚本并执行,这个在下一小节分析
->DelayedConfigurationActions.execute 第三次循环
2.2.3 处理build.gradle
借助这个流程来分析一下,源码中编译脚本和运行的逻辑,还记得上面setting.gradle 文件吗?最后也要经过这个处理
-> BuildOperationScriptPlugin.apply
->DefaultScriptPluginFactory$ScriptPluginImpl.apply 首先 编译运行buildscript{},在编译运行其他部分
->DefaultScriptCompilerFactory.compile
->BuildScopeInMemoryCachingScriptClassCompiler.compile 在cachedCompiledScripts缓存中查找,如果找到,就直接返回了
->CrossBuildInMemoryCachingScriptClassCache.compile 根据内容生成缓存key,
->FileCacheBackedScriptClassCompiler.compile 根据脚本内容hash,classLoader hash 、dslId ,这三个参数生成文件夹名,例如 gjs5brs4utyodezxmxs4ugji,存储编译后的文件,锁文件等
->DefaultCacheRepository.open 获取缓存路径 例如 .gradle/caches/6.7/scripts/gjs5brs4utyodezxmxs4ugji
->DefaultCacheFactory.open.doOpen
->DefaultPeristenDirectoryStore.open
->DefaultCacheAccess.open
->FixedSharedModeCrossProcessCacheAccess -> open 这里根据锁文件,来判断是否需要编译
->DefaultPeristenDirectoryCache.initialize
->FileCacheBackedScriptClassCompiler.execute 在缓存路径下,创建classesDir、metadataDir两个文件夹
->CompileToCrossBuildCacheAction.execute
->BuildOperationBackedScriptCompilationHandler.compileToDir
->DefaultScriptCompilationHandler.compileToDir
compileScript 参数:待编译资源,classLoader,配置参数,metadataDir,dsl的其他参数(例如:路径、所属项目、类型、id等等)
->GroovyClassLoader.doParseClass 执行编译
编译完后,会在,每个闭包是一个类,紧接着会执行,该阶段不会执行action
@Override
public void apply(final Object target) {
DefaultServiceRegistry services = new DefaultServiceRegistry(scriptServices);
services.add(ScriptPluginFactory.class, scriptPluginFactory);
services.add(ClassLoaderScope.class, baseScope);
services.add(LoggingManagerInternal.class, loggingFactoryManager.create());
services.add(ScriptHandler.class, scriptHandler);
final ScriptTarget initialPassScriptTarget = initialPassTarget(target);
ScriptCompiler compiler = scriptCompilerFactory.createCompiler(scriptSource);
// Pass 1, extract plugin requests and plugin repositories and execute buildscript {}, ignoring (i.e. not even compiling) anything else
CompileOperation<?> initialOperation = compileOperationFactory.getPluginsBlockCompileOperation(initialPassScriptTarget);
Class<? extends BasicScript> scriptType = initialPassScriptTarget.getScriptClass();
ScriptRunner<? extends BasicScript, ?> initialRunner = compiler.compile(scriptType, initialOperation, baseScope, Actions.doNothing());
//执行编译后的class文件 的run函数
initialRunner.run(target, services);
//获取需要初始化的插件,例如这种引用 plugins { id 'com.android.application'}
PluginRequests initialPluginRequests = getInitialPluginRequests(initialRunner);
PluginRequests mergedPluginRequests = autoAppliedPluginHandler.mergeWithAutoAppliedPlugins(initialPluginRequests, target);
PluginManagerInternal pluginManager = topLevelScript ? initialPassScriptTarget.getPluginManager() : null;
//调用插件的apply函数,下一小节会分析
pluginRequestApplicator.applyPlugins(mergedPluginRequests, scriptHandler, pluginManager, targetScope);
// Pass 2, compile everything except buildscript {}, pluginManagement{}, and plugin requests, then run
final ScriptTarget scriptTarget = secondPassTarget(target);
scriptType = scriptTarget.getScriptClass();
CompileOperation<BuildScriptData> operation = compileOperationFactory.getScriptCompileOperation(scriptSource, scriptTarget);
final ScriptRunner<? extends BasicScript, BuildScriptData> runner = compiler.compile(scriptType, operation, targetScope, ClosureCreationInterceptingVerifier.INSTANCE);
if (scriptTarget.getSupportsMethodInheritance() && runner.getHasMethods()) {
scriptTarget.attachScript(runner.getScript());
}
if (!runner.getRunDoesSomething()) {
return;
}
//执行编译后的class文件 的run函数
Runnable buildScriptRunner = () -> runner.run(target, services);
boolean hasImperativeStatements = runner.getData().getHasImperativeStatements();
scriptTarget.addConfiguration(buildScriptRunner, !hasImperativeStatements);
}
来看一下,根目录下的build.gradle 的编译结果,buildscript 和其他dsl脚本 ,编译后的缓存位置,是不一样的
build.gradle 内容:
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
ext.kotlin_version = "1.5.0"
repositories {
google()
mavenCentral()
maven { url 'https://jitpack.io' }
}
dependencies {
classpath "com.android.tools.build:gradle:4.1.3"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
google()
mavenCentral()
jcenter() // Warning: this repository is going to shut down soon
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
task task1 {
println('configure task xuexuan')
doLast {
println('action task xuexuan')
}
}
buildscript 编译后的缓存路径:
buildscript 编译后的class,每个 build.gradle 脚本和其中的 buildscript,对应一个继承了 ProjectScript 的类。每个闭包,对应一个继承自 Closure 的类
build.gradle 编译后的缓存路径:
build.gradle 编译后的class
这里执行了 task1,但是没有执行其中的action(doLast),action在RunTasks 阶段执行
2.2.4 apply 流程
你肯定在build.gradle中看到这样的代码 apply ‘com.android.application’
,下面来分析一下它的流程,对你分析Android Gradle Plugin 有帮助。他是在build.gradle 编译后,run 后执行的
ProjectScript.apply build.gradle 被编译后,会生成一个继承了ProjectScript的类,执行其中的apply 函数就到这里了
-> AbstractPluginAware.apply
-> DefaultObjectConfigurationAction.execute ->
-> DefaultPluginManager.apply (通过plugin id 在DefaultPluginRegistry中的 idMappings 变量中,找到对应的PluginImplementation对象)
-> AddPluginBuildOperation (构造 中传入plugin的信息)
-> 对应plugin的 apply函数,会再次调用到 AbstractPluginAware.apply
-> 添加任务 到 taskcontainer,在 计算TaskGraph的时候,从这里取出任务
当前的this对象是project,例如:project: app
也可以这样引入gradle 插件
plugins {
id 'com.android.application'
id 'kotlin-android'
}
这种是在编译运行buildscript{} ,后执行的
接上一小节的流程
-> DefaultScriptPluginFactory.apply
-> DefaultPluginRequestApplicator.applyPlugins
-> DefaultPluginManager.apply -> doApply
-> AddPluginBuildOperation.run
-> DefaultPluginManager.addPlugin
->RuleBasePluginTarget.applyImperative
-> ImperativeOnlyPluginTarget.applyImperative
-> AppPlugin.apply
-> AbstractPluginAware.apply
三、TaskGraph
主要工作:
1、记录需要排除的task
2、添加默认的task,可选的
3、根据传入的task名称,计算依赖关系
3、 记录计算taskGraph的入口Task
4、 计算依赖关系
代码调用链:
DefaultGradleLauncher.prepareTaskExecution
-> BuildOperationFiringTaskExecutionPreparer.prepareTaskExecution
-> CalculateTaskGraph.populateTaskGraph
->DefaultTaskExecutionPreparer.perpareForTaskExecution (计算task的依赖关系,最终可通过getTaskGraph 获取结果)
DefaultTaskExecutionPreparer.perpareForTaskExecution 会调用到如下代码
DefaultTaskExecutionPreparer
private void configure(final List<BuildConfigurationAction> processingConfigurationActions, final GradleInternal gradle, final int index) {
//本节中的三个工作,就是processingConfigurationActions 中三个变量来实现的。
if (index >= processingConfigurationActions.size()) {
return;
}
// 每个工作的入口,在configure
processingConfigurationActions.get(index).configure(new BuildExecutionContext() {
@Override
public GradleInternal getGradle() {
return gradle;
}
@Override
public void proceed() {
//回调本函数,责任链模式
configure(processingConfigurationActions, gradle, index + 1);
}
});
}
3.1 记录需要排除的task
ExcludedTaskFilteringBuildConfigurationAction.configure
public void configure(BuildExecutionContext context) {
GradleInternal gradle = context.getGradle();
//从启动命令中,获取需要排除的任务名称
Set<String> excludedTaskNames = gradle.getStartParameter().getExcludedTaskNames();
if (!excludedTaskNames.isEmpty()) {
final Set<Spec<Task>> filters = new HashSet<Spec<Task>>();
for (String taskName : excludedTaskNames) {
filters.add(taskSelector.getFilter(taskName));
}
//加入到taskGraph
gradle.getTaskGraph().useFilter(Specs.intersect(filters));
}
//执行下一个
context.proceed();
}
3.2 添加默认的task,可选的
DefaultTasksBuildExecutionAction.configure
public void configure(BuildExecutionContext context) {
StartParameter startParameter = context.getGradle().getStartParameter();
//遍历参数中需要执行的命令,如果没有特殊指定,点击运行app,就只有assembleDebug
for (TaskExecutionRequest request : startParameter.getTaskRequests()) {
if (!request.getArgs().isEmpty()) {
context.proceed();
return;
}
}
// Gather the default tasks from this first group project
//在 2.2.1中添加的Default Project
ProjectInternal project = context.getGradle().getDefaultProject();
//so that we don't miss out default tasks
projectConfigurer.configure(project);
//获取默认task,通过 defaultTasks 指定的
List<String> defaultTasks = project.getDefaultTasks();
if (defaultTasks.size() == 0) {
// 如果在build.gradle 也没有指定默认task,就添加该任务
defaultTasks = Collections.singletonList(ProjectInternal.HELP_TASK);
LOGGER.info("No tasks specified. Using default task {}", GUtil.toString(defaultTasks));
} else {
LOGGER.info("No tasks specified. Using project default tasks {}", GUtil.toString(defaultTasks));
}
startParameter.setTaskNames(defaultTasks);
context.proceed();
}
3.3 记录计算taskGraph的入口Task
TaskNameResolvingBuildConfigurationAction.configure
@Override
public void configure(BuildExecutionContext context) {
GradleInternal gradle = context.getGradle();
TaskExecutionGraphInternal taskGraph = gradle.getTaskGraph();
List<TaskExecutionRequest> taskParameters = gradle.getStartParameter().getTaskRequests();
for (TaskExecutionRequest taskParameter : taskParameters) {
//找出task 对应的project
List<TaskSelector.TaskSelection> taskSelections = commandLineTaskParser.parseTasks(taskParameter);
//命令参数中,可能指定了多个Task
for (TaskSelector.TaskSelection taskSelection : taskSelections) {
LOGGER.info("Selected primary task '{}' from project {}", taskSelection.getTaskName(), taskSelection.getProjectPath());
//加入taskGraph 入口,后续会计算依赖关系
taskGraph.addEntryTasks(taskSelection.getTasks());
}
}
context.proceed();
}
3.4 计算依赖关系
这里的每个任务都是一个Node 类,单个任务 的前后依赖关系,保存在dependencyPredecessors、dependencySuccessors
DefaultGradleLauncher.prepareTaskExecution
-> BuildOperationFiringTaskExecutionPreparer.prepareTaskExecution
-> taskGraph.populate();
->DefaultTaskExecutionGraph.populated
-> DefaultTaskExecutionGraph.ensurePopulated
-> DefaultExecutionPlan.determineExecutionPlan 从EntryTasks 开始,取出它依赖的task 加入合适的位置,不断循环,直到task 没有依赖其他任务
最后在taskGraph中可以看到,allTask包含了所以到目标task,需要执行的task
四、 RunTasks
主要两个工作:
1、 --dry-run
2、执行action
从DefaultGradleLauncher 开始的调用链:
DefaultGradleLauncher.java -> runWork()
-> buildExecuter.execute
-> BuildOperationFiringBuildWorkerExecutor.execute -> ExecuteTask.run
-> DeprecateUndefindBuildWorkExecutor.execute
-> IncludeBuildLifecycleBuildWorkExecutor.execute
-> DefaultBuildWorkExecutor.execute 分别调用了DryRunBuildExecution 和 SelectedTaskExecutionAction
4.1 --dry-run
接上面的调用链
->DryRunBuildExecution.execute
public void execute(BuildExecutionContext context, Collection<? super Throwable> taskFailures) {
GradleInternal gradle = context.getGradle();
if (gradle.getStartParameter().isDryRun()) {
//如果是 dry run 只会打印task name ,不会真正去执行
for (Task task : gradle.getTaskGraph().getAllTasks()) {
textOutputFactory.create(DryRunBuildExecutionAction.class)
.append(((TaskInternal) task).getIdentityPath().getPath())
.append(" ")
.style(StyledTextOutput.Style.ProgressStatus)
.append("SKIPPED")
.println();
}
} else {
context.proceed();
}
}
4.2 、执行action
接上面的调用链
->SelectedTaskExecutionAction.execute
-> DefaultTaskExecutionGraph.execute
->executeWithServices
->defaultPlanExecutor.process
创建 TaskExecutorWorker 去执行 task
public void process(ExecutionPlan executionPlan, Collection<? super Throwable> failures, Action<Node> nodeExecutor) {
ManagedExecutor executor = executorFactory.create("Execution worker for '" + executionPlan.getDisplayName() + "'");
try {
WorkerLease parentWorkerLease = workerLeaseService.getCurrentWorkerLease();
//创建线程,去执行,默认4个线程
startAdditionalWorkers(executionPlan, nodeExecutor, executor, parentWorkerLease);
//在当前线程,也开启一个执行,
new ExecutorWorker(executionPlan, nodeExecutor, parentWorkerLease, cancellationToken, coordinationService).run();
awaitCompletion(executionPlan, failures);
} finally {
executor.stop();
}
}
ExecutorWorker 实现了run函数,其中调用到 BuildOperationAwareExecutionAction.execute,等待它返回后,执行下一个
->BuildOperationAwareExecutionAction.execute
任务执行前增加监听 taskListener.beforeExecute(task.getTaskIdentity()); taskExecutionListener.beforeExecute(task); ,相应的在执行后,也有两个回调
EventFiringTaskExecuter.execute
CatchExceptionTaskExecuter.execute 用 try catch 包裹后续流程
SkipOnlyIfTaskExecuter.execute 可以在这里判断task 是否为想要执行的,通过setOnlyIf 来设置判断条件
SkipTaskWithNoActionsExecuter.execute 跳过没有action的task
ResolveTaskExecutionModeExecuter.execute 处理任务执行的模式,例:RERUN_TASKS_ENABLED 是否使用缓存的task结果,
FinalizePropertiesTaskExecuter.execute
CleanupStaleOutputsExecuter.execute 清除陈旧的输出文件
ExecuteActionsTaskExecuter.execute 真正执行task,
下面来看看,ExecuteActionsTaskExecuter.execute
private void executeActions(TaskInternal task, @Nullable InputChangesInternal inputChanges) {
boolean hasTaskListener = listenerManager.hasListeners(TaskActionListener.class) || listenerManager.hasListeners(TaskExecutionListener.class);
Iterator<InputChangesAwareTaskAction> actions = new ArrayList<>(task.getTaskActions()).iterator();
while (actions.hasNext()) {
InputChangesAwareTaskAction action = actions.next();
task.getState().setDidWork(true);
task.getStandardOutputCapture().start();
boolean hasMoreWork = hasTaskListener || actions.hasNext();
try {
//这里去执行task 中的action
executeAction(action.getDisplayName(), task, action, inputChanges, hasMoreWork);
} catch (StopActionException e) {
// Ignore
LOGGER.debug("Action stopped by some action with message: {}", e.getMessage());
} catch (StopExecutionException e) {
LOGGER.info("Execution stopped by some action with message: {}", e.getMessage());
break;
} finally {
task.getStandardOutputCapture().stop();
}
}
}
action实现了execute接口, 被TaskActionWrapper 包裹,添加到AbstractTask中。
五、Finished
最后,设置一下状态,对失败的结果进行异常抛出
private void finishBuild(String action, @Nullable Throwable stageFailure) {
if (stage == Stage.Finished) {
return;
}
RuntimeException reportableFailure = stageFailure == null ? null : exceptionAnalyser.transform(stageFailure);
BuildResult buildResult = new BuildResult(action, gradle, reportableFailure);
List<Throwable> failures = new ArrayList<>();
//对所有根构建的子版本,调用finishBuild,如果有错,加入到failures
includedBuildControllers.finishBuild(failures);
try {
// 监听回调
buildListener.buildFinished(buildResult);
buildFinishedListener.buildFinished((GradleInternal) buildResult.getGradle());
} catch (Throwable t) {
failures.add(t);
}
//状态设置
stage = Stage.Finished;
//处理失败的
if (failures.isEmpty() && reportableFailure != null) {
throw reportableFailure;
}
if (!failures.isEmpty()) {
if (stageFailure instanceof MultipleBuildFailures) {
failures.addAll(0, ((MultipleBuildFailures) stageFailure).getCauses());
} else if (stageFailure != null) {
failures.add(0, stageFailure);
}
throw exceptionAnalyser.transform(new MultipleBuildFailures(failures));
}
}
至此,Gradle 的大致流程就分析完了,过程不是很细,但是对整体理解有一定的帮助,你有任何疑问都可以在评论区告诉我,
最后 请点赞支持一下 谢谢朋友们