Android-gradle

./gradlew xxx:aDebug的执行流程

不管是windows还是linux或者mac os,新建一个Android工程后,都会在根目录创建一个gradlew.bat和gradlew文件,gradlew.bat是给windows系统用的,而gradlew是给linux和mac os用的。查看这两个脚本文件的代码,其实就是执行一些系统命令,可以看gradlew文件的最后一行代码,执行了"exec '$JAVACMD' '$@'",也就是用JAVACMD命令执行了我们传入的参数,而参数就是xxx:aDebug。也可以再看一下前面的脚本逻辑,这个JAVACMD其实也只是拿到java执行命令,如果环境变量配置了JAVA_HOME,则云JAVA_HOME目录下找,否则就直接调用java命令。在执行exec前有一行

```

eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS

"\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\""

org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"

```

这个是设置java命令要执行的main类的,main类就是GradleWrapperMain,执行的是GradleWrapperMain的main方法。

在gradle.wrapper.jar中是可以找到GradleWrapperMain类的,其main方法也就是java的main方法,在里面解析了输入参数,并最后调用了WrapperExecutor的execute方法去执行BootstrapMainStarter类的start方法。而BootstrapMainStarter是在gradle.api.jar中,其start方法又去反射调用GradleMain的main方法。GradleMain的main方法最后调用了new ProcessBootstrap对象的run,传入参数是"org.gradle.launcher.Main",执行org.gradle.launcher.bootstrap.EntryPoint类的run方法。

构造流程——加载settings

构造流程从DefaultGradleLauncher.executeTasks方法开始

```

if (upTo == DefaultGradleLauncher.Stage.RunTasks &&

this.instantExecution.canExecuteInstantaneously()) {

this.doInstantExecution();

} else {

this.doClassicBuildStages(upTo);

}

```

这里有个if判断,传入的upTo是RunTasks,因此决定执行哪个就是canExecuteInstantaneously决定的了。这里的canExecuteInstantaneously应该是判断是否可以热构建,类似于Android Studio的热更新功能,一般来说是执行else里的doClassicBuildStates。

这里的doClassicBuildStages方法虽然比较简单,但其包含了build过程的所有子过程。

```

private void doClassicBuildStages(DefaultGradleLauncher.Stage upTo) {

if (this.stage == null) {

this.instantExecution.prepareForBuildLogicExecution();

}

this.prepareSettings();

if (upTo != DefaultGradleLauncher.Stage.LoadSettings) {

this.prepareProjects();

if (upTo != DefaultGradleLauncher.Stage.Configure) {

this.prepareTaskExecution();

if (upTo != DefaultGradleLauncher.Stage.TaskGraph) {

this.instantExecution.saveScheduledWork();

this.runWork();

}

}

}

}

```

首先是prepareSettings,也就是读取settings.gradle中的配置。执行了settingsPreparer对象的prepareSettings方法。prepareSettings使用的是DefaultSettingsPreparer,由于传入的gradle是构建module的,因此使用ChildBuildRegisteringSettingsLoader,但最终delegate都会指向DefaultSettingsLoader,也就是要看DefaultSettingsLoader的findAndLoadSettings方法。findAndLoadSettings方法中调用了findSettingsAndLoadIfAppropriate方法。首先获取了settings文件的dir和path,然后调用settingsProcessor.process方法生成一个SetingsInternal对象,查看SettingsInternal接口的结构,发现里面就是我们在settings.gradle文件中配置的参数,SettingsInternal接口的实现类是DefaultSettings,里面就全是我们熟悉的settings.gradle内容了。

settingsProcessor.process得到一个SettingsInternal对象后,马上就调用了validate方法,这个validate方法主要是为了对buildSrc目录做特殊判断,也就是说在settings.gradle中不能include一个叫buildSrc的module。

来到ScriptEvaluatingSettingsProcessor的process中来,通过settingsFactory.createSettings得到一个SettingsInternal对象后,马上调用ScriptEvaluatingSettingsProcessor的applySetingsScript方法,applySettingsScript方法中获取到了一个ScriptPlugin对象,并调用其apply方法,这应该就是如果加载settings.gradle中的配置并完成project的构建。继续来到ProjectPropertySettingBuildLoader的load方法,调用了内部loader的load方法,也就是InstantiatingBuildLoader的load方法。在这个load方法中创建了一个rootProject对象,并将这个rootProject对象设置为gradle的rootProejct,接着就调用addProjects创建所有子project并将子project添加到rootProject。InstantiatingBuildLoader的addProjects方法是个递归方法,说明从rootProject到子project其实是个树层结构,会有很多层。

configureBuild流程

DefaultGradleLauncher的doBuildStages,执行完loadSettings后,继续执行configureBuild方法。和loadSettings一样,configureBuild中也是使用了buildOperationExecutor去执行DefaultGradleLauncher.CalculateTaskGrapsh的run方法,在run方法中调用了DefaultGradleLauncher.this.buildConfigurer.config(DefaultGradleLauncher.this.gradle),这其实是执行的DefaultBuildConfigurer的configure方法。这时对gradle.getStartParameter().isConfigureOnDemand()做了判断,这个判断是config阶段是否需要按需config,这是一个config加速的优化配置项。一般不开的时候走TaskPathProjectEvaluator#configureHierarchy,继而调用其config方法,这时的project还是rootProject,configureHierarchy方法中还对project的所有子project调用了configure方法。来到TaskPathProjectEvaluator的configure方法,在其实直接就调用了project的evaluate方法,这里的Project是DefaultProject。DefaultProject的evaluate方法也很简单,直接就调用了getProjectEvaluator的evalute方法,这里getProjectEvaluator得到的对象是LifecycleProjectEvaluateor类型的,因此执行的是LifecycleProjectEvaluator的buildOperationExecutor.run(new LifecycleProjectEvaluator.EvaluateProject(project, state));

到这里已经执行到LifecycleProjectEvaluator#EvaluateProject的run方法。这个run方法中首先执行了LifecycleProjectEvaluator.NotifyBeforeEvaluate(EvaluateProject的run方法来通知真正的config要开始了,然后LifecycleProjectEvaluator的delegate对象的evaluate方法,LifecycleProjectEvaluator的delegate对象是ConfigureActionsProjectEvaluator类型的,跟LifecycleProjectEvaluator一样实现了ProjectEvaluator接口。ConfigureActionsProjectEvaluator中的evaluate方法主要是取出ProjectConfigureAction列表,执行其execute方法,其中ProjectConfigureAction接口的实现是BuildScriptProcessor,其execute方法中调用了ScriptPlugin的apply方法,而这里的ScriptPlugin的实现是BuildOperationScriptPlugin,这里是为了将我们写在gradle中的DSL给编译成class并去执行。

构建Task Graph

DefaultGradleLauncher的doBuildStages中执行完configureBuild之后再执行constructTaskGraph,这一步是为了构建出构建的任务图,这是为什么是图而不是树呢?是因为其实构建过程很多子过程是可以并行的,如果是树的话,就只能串行了,树从根节点到子节点,只有一条树可走,但图就可以走多条路,只要达到最终节点保证必走节点到达过就行,因为构建TaskGraph可以理解成一个拓扑排序过程。

看了gradle前面这边构建过程,其实套路也差不多,因此constructTaskGraph的执行过程也是执行了CalculateTaskGraph的run方法。首先就是执行了DefaultGradleLauncher的buildConfigurationActionExecuter对象的select方法,这个对象是DefaultBuildConfigurationActionExecuter类型的,在select方法中调用projectStateRegistry.withLenientState,这个lenient的意思是宽容宽大的,不是很理解这里要表达的是啥意思,继续往后看,反正大概意思就是当到达一定的构建状态时去执行传入的runnable就行。Runnable的run方法中执行了configure方法,而configure方法中执行了ExecutedTaskFilteringBuildConfigurationAction的configure方法,这里面是为了过滤掉一些不用的task。select方法中,还将DefaultBuildConfigurationActionExecutor的configurationActions添加到了list中去执行configure方法,这个configurationActions中就包含了若干Task,这些Task是在build.gradle的defaultTasks闭包中指定的。计算task依赖图的代码在TaskNameResolvingBuildConfigurationAction中,也是从select中调用过来的。这里的configure方法中会根据构建命令取出要执行的命令,通过我们使用gradle命令是可以是多命令的,例如./gradlew clean app:aDebug,这里其实是有clean和app:aDebug两个命令的,因此configure方法会提取出所有的命令,并将task取出,clean这个命令会对所有的project生效,而app:aDebug只是对app这个project生效。将得到的task添加到taskGraph中去,调用了DefaultTaskExecutionGraph的addEntryTasks方法,这个方法中最终调用了DefaultExecutionPlan的addEntryTasks方法,这里的addEntryTasks方法中就计算了每个tasks所依赖的其他task,然后依赖的task也添加到graph中来,最终构建成一个task的有向无环图。

所有的task node都找到后,回到CalculateTaskGraph的run方法中,继续执行taskGraph的populate方法,一路执行到DefaultExecutionPlan的dermineExecutionPlan方法,这里才是真正构建有向无环图的地方。最终生成的结果保存在executionQueue中

执行构建task

同样,DefaultGradleLauncher的doBuildStages方法中执行完constructTaskGraph后再执行runTasks方法,runTasks方法中也跟前面一样,用buildOperationExecutor对象执行其run方法,传入参数是DefaultGradleLauncher.ExecuteTasks内部类的对象,也就是执行ExecuteTasks的run方法。DefaultGradleLauncher.this.buildExecuter.execute(DefaultGradleLauncher.this.gradle, taskFailures)方法的执行调起了真正的构建过程,传入的一个Throwable的list是用来收集在构建过程中产生的异常,构建过程中要是有异常,最后就会抛一个MultipleBuildFailures的自定义异常。

execute方法中遍历executeAction列表执行BuildExecutionAction的execute方法。

DryRunBuildExecutionAction实现了BuildExecutionAction接口,判断如果gradle的参数isDryRun方法返回true则将gradle中储存的taskGraph的所有任务拿出来执行,否则执行context.process,这里的process方法会递归地调用DefaultBuildExecuter的execute方法。这里的isDryRun方法其实就是判断输入的gradle命令中有没有--dry-run

真正执行构建命令的是BuildExecutionAction的另一个实现类SelectedTaskExecutionAction,其execute方法中调用了taskGraph的execute方法。taskGraph就是DefaultTaskExecutionGraph,其execute方法调用了executeWithServices方法,在sexecuteWithService方法中调用了DefaultPlanExecutor的process方法。

```

public void process(ExecutionPlan executionPlan, Collection<? super Throwable> failures, Action<Node> nodeExecutor) {

ManagedExecutor executor = this.executorFactory.create("Execution worker for '" + executionPlan.getDisplayName() + "'");

try {

WorkerLease parentWorkerLease = this.workerLeaseService.getCurrentWorkerLease();

this.startAdditionalWorkers(executionPlan, nodeExecutor, executor, parentWorkerLease);

(new DefaultPlanExecutor.ExecutorWorker(executionPlan, nodeExecutor, parentWorkerLease, this.cancellationToken, this.coordinationService)).run();

this.awaitCompletion(executionPlan, failures);

} finally {

executor.stop();

}

}

```

startAdditionalWorkers方法开启了多线程来执行task,线程数默认为机器的处理器数。ExecutorWorker的run方法中最终会执行到nodeExecutor对象的execute方法,nodeExecutor是Action<Node>接口类型的,往回查,发现这个nodeExecutor是个DefaultTaskExecutionGraph.BuildOperationAwareExecutionAction类型的,其真正执行delegate的类型是DefaultTaskExecutionGraph.InvokeNodeExecutorsAction,执行的executors是DefaultTaskExecutionGraph的nodeExecutors列表,列表元素为NodeExecutor类型,其中有个实现类是WorkNodeExecutor,其execute方法就是将传入的Node强转为ActionNode,并执行其run方法。因此分析到这里发现gradle执行task其实就是提取出所有task的action并执行。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值