14. Gradle编译其他应用代码流程(三) - Load过程
继续上一篇 13. Gradle编译其他应用代码流程(二)。
这篇从InProcessBuildActionExecuter.execute开始这一篇的内容。
在正式内容前,首先要讲个gradle构建的流程,这个也是接下来内容的流程。
Load->Configure->Build
大家可以思考下,这3步都主要做了什么事。
另外,从执行流程的事件通知来看,它还分成下面5个通知事件:
buildStarted//开始编译settingsEvaluated//settings处理完毕projectsLoaded//项目loadedprojectsEvaluated//项目处理完毕buildFinished//编译结束
一.InProcessBuildActionExecuter.execute
文件路径:subprojects\launcher\src\main\java\org\gradle\launcher\exec\InProcessBuildActionExecuter.java方法:publicObjectexecute(BuildActionaction,BuildRequestContextbuildRequestContext,BuildActionParametersactionParameters,ServiceRegistrycontextServices){GradleLaunchergradleLauncher=gradleLauncherFactory.newInstance(action.getStartParameter(),buildRequestContext,contextServices);try{gradleLauncher.addStandardOutputListener(buildRequestContext.getOutputListener());gradleLauncher.addStandardErrorListener(buildRequestContext.getErrorListener());GradleBuildControllerbuildController=newGradleBuildController(gradleLauncher);buildActionRunner.run(action,buildController);System.out.println("SandybuildController.getResult():"+buildController.getResult());returnbuildController.getResult();}finally{gradleLauncher.stop();}}文件路径:subprojects\launcher\src\main\java\org\gradle\launcher\exec\InProcessBuildActionExecuter.java方法:publicGradleInternalrun(){try{System.out.println("SandyGradleInternalrunstate:"+state);return(GradleInternal)getLauncher().run().getGradle();}finally{state=State.Completed;}}文件路径:subprojects\launcher\src\main\java\org\gradle\launcher\exec\ChainingBuildActionRunner.java方法:@Overridepublicvoidrun(BuildActionaction,BuildControllerbuildController){System.out.println("SandyChainingBuildActionRunnerrunrunners.size:"+runners.size());for(BuildActionRunnerrunner:runners){System.out.println("runner:"+runner);runner.run(action,buildController);if(buildController.hasResult()){return;}}thrownewUnsupportedOperationException(String.format("Don'tknowhowtorunabuildactionoftype%s.",action.getClass().getSimpleName()));}文件路径:subprojects\launcher\src\main\java\org\gradle\tooling\internal\provider\ExecuteBuildActionRunner.java方法:publicvoidrun(BuildActionaction,BuildControllerbuildController){System.out.println("ExecuteBuildActionRunneraction:"+action+"buildController:"+buildController);if(actioninstanceofExecuteBuildAction){System.out.println("ExecuteBuildActionRunnerrun..");buildController.run();buildController.setResult(null);System.out.println("ExecuteBuildActionRunnerresult:"+"null");}}文件路径:subprojects\launcher\src\main\java\org\gradle\launcher\exec\GradleBuildController.java方法:publicGradleInternalrun(){try{System.out.println("SandyGradleInternalrunstate:"+state);return(GradleInternal)getLauncher().run().getGradle();}finally{state=State.Completed;}}
上面的步骤比较清晰明了,需要注意的是ChainingBuildActionRunner和ExecuteBuildActionRunner,其实他们都是同一个接口BuildActionRunner,所以这里又是喜闻乐见的装饰者模式。
publicclassChainingBuildActionRunnerimplementsBuildActionRunner{privatefinalList<?extendsBuildActionRunner>runners;publicChainingBuildActionRunner(List<?extendsBuildActionRunner>runners){this.runners=runners;}}publicclassExecuteBuildActionRunnerimplementsBuildActionRunner{}
最后来到ExecuteBuildActionRunner.run方法,它会调用GradleBuildController.run(),顾名思义,它是GradleBuild的控制器,所以马上就要接触到Gradle build步骤了;接下来会调用DefaultGradleLauncher.run()方法。
二. DefaultGradleLauncher
@OverridepublicBuildResultrun(){returndoBuild(Stage.Build);}privateBuildResultdoBuild(finalStageupTo){returnbuildOperationExecutor.run("Runbuild",newFactory<BuildResult>(){@OverridepublicBuildResultcreate(){Throwablefailure=null;try{System.out.println("buildListener:"+buildListener.getClass()+"gradle:"+gradle.getClass());buildListener.buildStarted(gradle);doBuildStages(upTo);}catch(Throwablet){failure=exceptionAnalyser.transform(t);}BuildResultbuildResult=newBuildResult(upTo.name(),gradle,failure);buildListener.buildFinished(buildResult);if(failure!=null){thrownewReportedException(failure);}returnbuildResult;}});}
首先来看buildListener.buildStarted(gradle); 这行代码的作用是通知gradle构建已经开始,那既然是通知,接收者是谁呢?
看buildListener赋值的地方:
文件路径:
subprojects\core\src\main\java\org\gradle\initialization\DefaultGradleLauncher.java
方法
publicDefaultGradleLauncher(GradleInternalgradle,InitScriptHandlerinitScriptHandler,SettingsLoadersettingsLoader,BuildConfigurerbuildConfigurer,ExceptionAnalyserexceptionAnalyser,LoggingManagerInternalloggingManager,BuildListenerbuildListener,ModelConfigurationListenermodelConfigurationListener,BuildCompletionListenerbuildCompletionListener,BuildOperationExecutoroperationExecutor,BuildConfigurationActionExecuterbuildConfigurationActionExecuter,BuildExecuterbuildExecuter,BuildScopeServicesbuildServices){...this.buildListener=buildListener;...}
继续看调动的地方
文件路径:
subprojects\core\src\main\java\org\gradle\initialization\DefaultGradleLauncherFactory.java
方法:
returnnewDefaultGradleLauncher(...gradle.getBuildListenerBroadcaster(),...);
//文件路径:
subprojects\core\src\main\java\org\gradle\invocation\DefaultGradle.java
publicBuildListenergetBuildListenerBroadcaster(){returnbuildListenerBroadcast.getSource();}publicDefaultGradle(Gradleparent,StartParameterstartParameter,ServiceRegistryFactoryparentRegistry){...buildListenerBroadcast=getListenerManager().createAnonymousBroadcaster(BuildListener.class);projectEvaluationListenerBroadcast=getListenerManager().createAnonymousBroadcaster(ProjectEvaluationListener.class);buildListenerBroadcast.add(newBuildAdapter(){@OverridepublicvoidbuildStarted(Gradlegradle){super.buildStarted(gradle);Exceptionex=newException("SandybuildStarted");ex.printStackTrace();System.out.println("buildListenerBroadcastsandybuildStarted");}@OverridepublicvoidsettingsEvaluated(Settingssettings){super.settingsEvaluated(settings);Exceptionex=newException("SandysettingsEvaluated");ex.printStackTrace();System.out.println("buildListenerBroadcastsandysettingsEvaluated");}@OverridepublicvoidprojectsEvaluated(Gradlegradle){super.projectsEvaluated(gradle);System.out.println("buildListenerBroadcastsandyprojectsEvaluated");}@OverridepublicvoidbuildFinished(BuildResultresult){super.buildFinished(result);System.out.println("buildListenerBroadcastsandybuildFinished");}@OverridepublicvoidprojectsLoaded(Gradlegradle){System.out.println("buildListenerBroadcastsandyprojectsLoaded");rootProjectActions.execute(rootProject);rootProjectActions=null;}});}
嗯,也就是接受者是在DefaultGradle里面,也就是说通知gradle build已经开始,接下来看doBuildStages(Stage.Build)方法,这个方法很重要,gradle build的主要流程都在这里面。
privatevoiddoBuildStages(StageupTo){if(stage==Stage.Build){thrownewIllegalStateException("CannotbuildwithGradleLaunchermultipletimes");}if(stage==null){//EvaluateinitscriptsinitScriptHandler.executeScripts(gradle);//Build`buildSrc`,loadsettings.gradle,andconstructcomposite(ifappropriate)settings=settingsLoader.findAndLoadSettings(gradle);stage=Stage.Load;}if(upTo==Stage.Load){return;}if(stage==Stage.Load){//ConfigurebuildbuildOperationExecutor.run("Configurebuild",newRunnable(){@Overridepublicvoidrun(){buildConfigurer.configure(gradle);if(!gradle.getStartParameter().isConfigureOnDemand()){buildListener.projectsEvaluated(gradle);}modelConfigurationListener.onConfigure(gradle);}});stage=Stage.Configure;}if(upTo==Stage.Configure){return;}//Afterthispoint,theGradleLaunchercannotbereusedstage=Stage.Build;//PopulatetaskgraphbuildOperationExecutor.run("Calculatetaskgraph",newRunnable(){@Overridepublicvoidrun(){buildConfigurationActionExecuter.select(gradle);if(gradle.getStartParameter().isConfigureOnDemand()){buildListener.projectsEvaluated(gradle);}}});//ExecutebuildbuildOperationExecutor.run("Runtasks",newRunnable(){@Overridepublicvoidrun(){buildExecuter.execute(gradle);}});}
还记得最开始说过的gradle构建分成3个步骤吗?Load-> Configure->Build
那这个方法doBuildStages可以很清楚的看到这个流程,大家看下上面的代码即可明白,那接下来我们一步步分析这个过程。
三. Load.executeScripts 初始化脚本
if(stage==null){//EvaluateinitscriptsinitScriptHandler.executeScripts(gradle);//Build`buildSrc`,loadsettings.gradle,andconstructcomposite(ifappropriate)settings=settingsLoader.findAndLoadSettings(gradle);stage=Stage.Load;}
1. 首先来看第一行
initScriptHandler.executeScripts(gradle);
// Evaluate init scripts 看解释是统计初始化脚本,那具体是干什么呢?
文件路径:
subprojects\core\src\main\java\org\gradle\initialization\InitScriptHandler.java
/***Findsandexecutesallinitscriptsforagivenbuild.*/publicclassInitScriptHandler{...publicvoidexecuteScripts(finalGradleInternalgradle){System.out.println("executeScripts");finalList<File>initScripts=gradle.getStartParameter().getAllInitScripts();if(initScripts.isEmpty()){return;}BuildOperationDetailsoperationDetails=BuildOperationDetails.displayName("Runinitscripts").progressDisplayName("initscripts").build();buildOperationExecutor.run(operationDetails,newRunnable(){@Overridepublicvoidrun(){for(Filescript:initScripts){System.out.println("InitScriptHandlerrunprocessor"+processor);processor.process(newUriScriptSource("initializationscript",script),gradle);}}});}}
从类InitScriptHandler的注释就知道,这个类的作用是找到并且执行初始化脚本,那我们接下来看看:
a. 它说的初始化脚本指的是什么?
b. 怎么执行初始化脚本的?
2. 首先来看getAllInitScripts是在干什么:
subprojects\core\src\main\java\org\gradle\StartParameter.java
publicList<File>getAllInitScripts(){CompositeInitScriptFinderinitScriptFinder=newCompositeInitScriptFinder(newUserHomeInitScriptFinder(getGradleUserHomeDir()),newDistributionInitScriptFinder(gradleHomeDir));List<File>scripts=newArrayList<File>(getInitScripts());initScriptFinder.findScripts(scripts);returnCollections.unmodifiableList(scripts);}
subprojects\core\src\main\java\org\gradle\initialization\UserHomeInitScriptFinder.java
publicvoidfindScripts(Collection<File>scripts){FileuserInitScript=newFile(userHomeDir,"init.gradle");if(userInitScript.isFile()){scripts.add(userInitScript);}findScriptsInDir(newFile(userHomeDir,"init.d"),scripts);}
subprojects\core\src\main\java\org\gradle\initialization\DistributionInitScriptFinder.java
publicvoidfindScripts(Collection<File>scripts){if(gradleHome==null){return;}findScriptsInDir(newFile(gradleHome,"init.d"),scripts);}
3个作用:
a. 尝试找到环境变量'GRADLE_USER_HOME'目录下的init.gradle文件,并加入列表。
如果没有配置环境变量'GRADLE_USER_HOME',那么目录就是'C:\Users\xxx(你的用户名)\.gradle'
b. 找到环境变量'GRADLE_USER_HOME'下面init.d目录下的 *.gradle配置文件,并加入列表。
c. 找到gradle home目录下init.d目录的 *.gradle配置文件,并加入列表。
我的gradle_user_home和gradle_home分别是:
gradleUserHomeDir=D:\gradle_jar_cachegradleHome=E:\work_space\gradle-source-from-csdn\gradle-3.1\build\distributions\gradle-3.1-snapshot-1
其实如果大家去看下gradle home目录的init.d目录,你会发现里面有个readme.txt文件,里面有这样的描述:
Youcanadd.gradleinitscriptstothisdirectory.Eachoneisexecutedatthestartofthebuild.
那我们的Gradle 源代码流程分析也验证了这句话。
3. 然后来看看processor.process在干什么
for(Filescript:initScripts){processor.process(newUriScriptSource("initializationscript",script),gradle);}
首先initScripts是指上面我们统计3个目录下得到的脚本文件集合,那这里就是挨个执行它们。
那UriScriptSource是用来解析传入的script文件,把它的内容读出来。
那继续看process方法
文件路径:
subprojects\core\src\main\java\org\gradle\configuration\DefaultInitScriptProcessor.java
/***Processes(andruns)aninitscriptforaspecifiedbuild.Handlesdefining*theclasspathbasedontheinitscript{}configurationclosure.*/publicclassDefaultInitScriptProcessorimplementsInitScriptProcessor{...publicvoidprocess(finalScriptSourceinitScript,GradleInternalgradle){....configurer.apply(gradle);}}
文件路径:
subprojects\core\src\main\java\org\gradle\configuration\DefaultScriptPluginFactory.java
publicvoidapply(finalObjecttarget){System.out.println("ScriptPluginImplapply1");...//Pass1,extractpluginrequestsandpluginrepositoriesandexecutebuildscript{},ignoring(i.e.notevencompiling)anythingelseClass<?extendsBasicScript>scriptType=initialPassScriptTarget.getScriptClass();InitialPassStatementTransformerinitialPassStatementTransformer=newInitialPassStatementTransformer(scriptSource,initialPassScriptTarget,documentationRegistry);SubsetScriptTransformerinitialTransformer=newSubsetScriptTransformer(initialPassStatementTransformer);Stringid=INTERNER.intern("cp_"+initialPassScriptTarget.getId());CompileOperation<PluginRequests>initialOperation=newFactoryBackedCompileOperation<PluginRequests>(id,initialTransformer,initialPassStatementTransformer,pluginRequestsSerializer);ScriptRunner<?extendsBasicScript,PluginRequests>initialRunner=compiler.compile(scriptType,initialOperation,baseScope.getExportClassLoader(),Actions.doNothing());initialRunner.run(target,services);PluginRequestspluginRequests=initialRunner.getData();PluginManagerInternalpluginManager=initialPassScriptTarget.getPluginManager();System.out.println("ScriptPluginImplapplyisempty:"+pluginRequests.isEmpty());pluginRequestApplicator.applyPlugins(pluginRequests,scriptHandler,pluginManager,targetScope);System.out.println("ScriptPluginImplapply4");//Pass2,compileeverythingexceptbuildscript{},pluginRepositories{},andpluginrequests,thenrunfinalScriptTargetscriptTarget=secondPassTarget(target);scriptType=scriptTarget.getScriptClass();BuildScriptTransformerbuildScriptTransformer=newBuildScriptTransformer(scriptSource,scriptTarget);StringoperationId=scriptTarget.getId();CompileOperation<BuildScriptData>operation=newFactoryBackedCompileOperation<BuildScriptData>(operationId,buildScriptTransformer,buildScriptTransformer,buildScriptDataSerializer);finalScriptRunner<?extendsBasicScript,BuildScriptData>runner=compiler.compile(scriptType,operation,targetScope.getLocalClassLoader(),ClosureCreationInterceptingVerifier.INSTANCE);if(scriptTarget.getSupportsMethodInheritance()&&runner.getHasMethods()){System.out.println("ScriptPluginImplapply5");scriptTarget.attachScript(runner.getScript());}System.out.println("ScriptPluginImplapply6");if(!runner.getRunDoesSomething()){System.out.println("ScriptPluginImplapply7");return;}RunnablebuildScriptRunner=newRunnable(){publicvoidrun(){System.out.println("ScriptPluginImplapply8");runner.run(target,services);}};System.out.println("ScriptPluginImplapply9");booleanhasImperativeStatements=runner.getData().getHasImperativeStatements();scriptTarget.addConfiguration(buildScriptRunner,!hasImperativeStatements);}
执行流程:
a. 在DefaultScriptPluginFactory的apply里面主要有两步 pass1/ pass2
在pass1的时候,处理的文件是
'D:\gradle_jar_cache\caches\3.1-snapshot-1\scripts-remapped\settings_brbxf8awmquo5r6nxrgcmg7fq\iaw3k0vmpedkxsp2gv9xvnom\cp_settingsd7eae713beda1bd9e69f8461da734880\metadata\metadata.bin'
b. 在pass2的时候,处理初始化脚本,如果脚本文件里面有配置,则会到走到'ScriptPluginImpl apply 8' 加载这个脚本的属性;
如果脚本里面有配置,只是一个空文件,则从'ScriptPluginImpl apply 7'返回。
总结下这个步骤的内容:
a. 加载gradle_user_home下面init.gradle和init.d/目录下 *.gradle以及gradle home 目录下的init.d/目录下的 *.gradle文件
b. 如果有这些文件,而且内容不为空,那么将会加载它们配置的属性。
比较重要也很令人费解是这行代码:
scriptCompilerFactory.createCompiler(scriptSource);
这行代码粗看没有什么,但是仔细分析后其实大有乾坤!它是在为下一行
initialRunner.run(target,services);
生成可以加载的Java类,最终调用DefaultScriptCompilationHandler.compileToDir来生成类。 生成的类路径如下:
D:\gradle_jar_cache\caches\3.1-snapshot-1\scripts\df5frxe005h8vnbjcuzkr2g0s\cp_settings\cp_settingsd7eae713beda1bd9e69f8461da734880
执行堆栈如下:
java.lang.Exception:Sandycompiletodiratorg.gradle.groovy.scripts.internal.DefaultScriptCompilationHandler.compileToDir(DefaultScriptCompilationHandler.java:97)atorg.gradle.groovy.scripts.internal.FileCacheBackedScriptClassCompiler$CompileToCrossBuildCacheAction.execute(FileCacheBackedScriptClassCompiler.java:160)atorg.gradle.groovy.scripts.internal.FileCacheBackedScriptClassCompiler$CompileToCrossBuildCacheAction.execute(FileCacheBackedScriptClassCompiler.java:141)atorg.gradle.groovy.scripts.internal.FileCacheBackedScriptClassCompiler$Progre***eportingInitializer.execute(FileCacheBackedScriptClassCompiler.java:185)atorg.gradle.groovy.scripts.internal.FileCacheBackedScriptClassCompiler$Progre***eportingInitializer.execute(FileCacheBackedScriptClassCompiler.java:164)atorg.gradle.cache.internal.DefaultPersistentDirectoryCache$Initializer.initialize(DefaultPersistentDirectoryCache.java:100)atorg.gradle.cache.internal.DefaultCacheAccess$2.run(DefaultCacheAccess.java:116)atorg.gradle.cache.internal.DefaultFileLockManager$DefaultFileLock.doWriteAction(DefaultFileLockManager.java:179)atorg.gradle.cache.internal.DefaultFileLockManager$DefaultFileLock.writeFile(DefaultFileLockManager.java:169)atorg.gradle.cache.internal.DefaultCacheAccess.open(DefaultCacheAccess.java:113)atorg.gradle.cache.internal.DefaultPersistentDirectoryStore.open(DefaultPersistentDirectoryStore.java:47)atorg.gradle.cache.internal.DefaultPersistentDirectoryStore.open(DefaultPersistentDirectoryStore.java:28)atorg.gradle.cache.internal.DefaultCacheFactory.doOpen(DefaultCacheFactory.java:83)atorg.gradle.cache.internal.DefaultCacheFactory.open(DefaultCacheFactory.java:51)atorg.gradle.cache.internal.DefaultCacheRepository$PersistentCacheBuilder.doOpen(DefaultCacheRepository.java:147)atorg.gradle.cache.internal.DefaultCacheRepository$AbstractCacheBuilder.open(DefaultCacheRepository.java:121)atorg.gradle.groovy.scripts.internal.FileCacheBackedScriptClassCompiler$RemapBuildScriptsAction.execute(FileCacheBackedScriptClassCompiler.java:365)atorg.gradle.groovy.scripts.internal.FileCacheBackedScriptClassCompiler$RemapBuildScriptsAction.execute(FileCacheBackedScriptClassCompiler.java:333)atorg.gradle.groovy.scripts.internal.FileCacheBackedScriptClassCompiler$Progre***eportingInitializer.execute(FileCacheBackedScriptClassCompiler.java:185)atorg.gradle.groovy.scripts.internal.FileCacheBackedScriptClassCompiler$Progre***eportingInitializer.execute(FileCacheBackedScriptClassCompiler.java:164)atorg.gradle.cache.internal.DefaultPersistentDirectoryCache$Initializer.initialize(DefaultPersistentDirectoryCache.java:100)atorg.gradle.cache.internal.DefaultCacheAccess$2.run(DefaultCacheAccess.java:116)atorg.gradle.cache.internal.DefaultFileLockManager$DefaultFileLock.doWriteAction(DefaultFileLockManager.java:179)atorg.gradle.cache.internal.DefaultFileLockManager$DefaultFileLock.writeFile(DefaultFileLockManager.java:169)atorg.gradle.cache.internal.DefaultCacheAccess.open(DefaultCacheAccess.java:113)atorg.gradle.cache.internal.DefaultPersistentDirectoryStore.open(DefaultPersistentDirectoryStore.java:47)atorg.gradle.cache.internal.DefaultPersistentDirectoryStore.open(DefaultPersistentDirectoryStore.java:28)atorg.gradle.cache.internal.DefaultCacheFactory.doOpen(DefaultCacheFactory.java:83)atorg.gradle.cache.internal.DefaultCacheFactory.open(DefaultCacheFactory.java:51)atorg.gradle.cache.internal.DefaultCacheRepository$PersistentCacheBuilder.doOpen(DefaultCacheRepository.java:147)atorg.gradle.cache.internal.DefaultCacheRepository$AbstractCacheBuilder.open(DefaultCacheRepository.java:121)atorg.gradle.groovy.scripts.internal.FileCacheBackedScriptClassCompiler.compile(FileCacheBackedScriptClassCompiler.java:111)atorg.gradle.groovy.scripts.internal.CrossBuildInMemoryCachingScriptClassCache.getOrCompile(CrossBuildInMemoryCachingScriptClassCache.java:46)atorg.gradle.groovy.scripts.internal.BuildScopeInMemoryCachingScriptClassCompiler.compile(BuildScopeInMemoryCachingScriptClassCompiler.java:48)atorg.gradle.groovy.scripts.DefaultScriptCompilerFactory$ScriptCompilerImpl.compile(DefaultScriptCompilerFactory.java:50)atorg.gradle.configuration.DefaultScriptPluginFactory$ScriptPluginImpl.apply(DefaultScriptPluginFactory.java:154)atorg.gradle.configuration.project.BuildScriptProcessor.execute(BuildScriptProcessor.java:40)atorg.gradle.configuration.project.BuildScriptProcessor.execute(BuildScriptProcessor.java:25)atorg.gradle.configuration.project.ConfigureActionsProjectEvaluator.evaluate(ConfigureActionsProjectEvaluator.java:34)atorg.gradle.configuration.project.LifecycleProjectEvaluator.evaluate(LifecycleProjectEvaluator.java:55)atorg.gradle.api.internal.project.DefaultProject.evaluate(DefaultProject.java:573)atorg.gradle.api.internal.project.DefaultProject.evaluate(DefaultProject.java:125)atorg.gradle.execution.TaskPathProjectEvaluator.configureHierarchy(TaskPathProjectEvaluator.java:42)atorg.gradle.configuration.DefaultBuildConfigurer.configure(DefaultBuildConfigurer.java:38)atorg.gradle.initialization.DefaultGradleLauncher$2.run(DefaultGradleLauncher.java:154)atorg.gradle.internal.Factories$1.create(Factories.java:22)atorg.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:91)atorg.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:53)atorg.gradle.initialization.DefaultGradleLauncher.doBuildStages(DefaultGradleLauncher.java:151)atorg.gradle.initialization.DefaultGradleLauncher.access$200(DefaultGradleLauncher.java:33)atorg.gradle.initialization.DefaultGradleLauncher$1.create(DefaultGradleLauncher.java:114)atorg.gradle.initialization.DefaultGradleLauncher$1.create(DefaultGradleLauncher.java:106)atorg.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:91)atorg.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:63)atorg.gradle.initialization.DefaultGradleLauncher.doBuild(DefaultGradleLauncher.java:106)atorg.gradle.initialization.DefaultGradleLauncher.run(DefaultGradleLauncher.java:92)atorg.gradle.launcher.exec.GradleBuildController.run(GradleBuildController.java:67)atorg.gradle.tooling.internal.provider.ExecuteBuildActionRunner.run(ExecuteBuildActionRunner.java:31)atorg.gradle.launcher.exec.ChainingBuildActionRunner.run(ChainingBuildActionRunner.java:43)atorg.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:42)atorg.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:26)atorg.gradle.tooling.internal.provider.ContinuousBuildActionExecuter.execute(ContinuousBuildActionExecuter.java:79)atorg.gradle.tooling.internal.provider.ContinuousBuildActionExecuter.execute(ContinuousBuildActionExecuter.java:51)atorg.gradle.launcher.cli.RunBuildAction.run(RunBuildAction.java:54)atorg.gradle.internal.Actions$RunnableActionAdapter.execute(Actions.java:173)atorg.gradle.launcher.cli.CommandLineActionFactory$ParseAndBuildAction.execute(CommandLineActionFactory.java:250)atorg.gradle.launcher.cli.CommandLineActionFactory$ParseAndBuildAction.execute(CommandLineActionFactory.java:217)atorg.gradle.launcher.cli.JavaRuntimeValidationAction.execute(JavaRuntimeValidationAction.java:33)atorg.gradle.launcher.cli.JavaRuntimeValidationAction.execute(JavaRuntimeValidationAction.java:24)atorg.gradle.launcher.cli.ExceptionReportingAction.execute(ExceptionReportingAction.java:33)atorg.gradle.launcher.cli.ExceptionReportingAction.execute(ExceptionReportingAction.java:22)atorg.gradle.launcher.cli.CommandLineActionFactory$WithLogging.execute(CommandLineActionFactory.java:210)atorg.gradle.launcher.cli.CommandLineActionFactory$WithLogging.execute(CommandLineActionFactory.java:174)atorg.gradle.launcher.Main.doAction(Main.java:33)atorg.gradle.launcher.bootstrap.EntryPoint.run(EntryPoint.java:45)atsun.reflect.NativeMethodAccessorImpl.invoke0(NativeMethod)atsun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)atsun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)atjava.lang.reflect.Method.invoke(Method.java:483)atorg.gradle.launcher.bootstrap.ProcessBootstrap.runNoExit(ProcessBootstrap.java:60)atorg.gradle.launcher.bootstrap.ProcessBootstrap.run(ProcessBootstrap.java:37)atorg.gradle.launcher.GradleMain.main(GradleMain.java:24)
接下来,继续往下面看Load步骤的第二个步骤findAndLoadSettings.
//Build`buildSrc`,loadsettings.gradle,andconstructcomposite(ifappropriate)settings=settingsLoader.findAndLoadSettings(gradle);
四. Load.findAndLoadSettings
settings = settingsLoader.findAndLoadSettings(gradle);
首先settingsLoader使用了装饰者模式,从外到内包装顺序是:
publicclassNotifyingSettingsLoaderimplementsSettingsLoader{privatefinalSettingsLoadersettingsLoader;...@OverridepublicSettingsInternalfindAndLoadSettings(GradleInternalgradle){SettingsInternalsettings=settingsLoader.findAndLoadSettings(gradle);gradle.getBuildListenerBroadcaster().settingsEvaluated(settings);buildLoader.load(settings.getRootProject(),settings.getDefaultProject(),gradle,settings.getRootClassLoaderScope());gradle.getBuildListenerBroadcaster().projectsLoaded(gradle);returnsettings;}}publicclassCompositeBuildSettingsLoaderimplementsSettingsLoader{privatefinalSettingsLoaderdelegate;...@OverridepublicSettingsInternalfindAndLoadSettings(GradleInternalgradle){SettingsInternalsettings=delegate.findAndLoadSettings(gradle);...}}/***Handleslocatingandprocessingsetting.gradlefiles.AlsodealswiththebuildSrcmodule,sincethatmodulesis*foundaftersettingsislocated,butneedstobebuiltbeforesettingsisprocessed.*/publicclassDefaultSettingsLoaderimplementsSettingsLoader{...@OverridepublicSettingsInternalfindAndLoadSettings(GradleInternalgradle){...SettingsInternalsettings=findSettingsAndLoadIfAppropriate(gradle,startParameter);...ProjectSpecspec=ProjectSpecs.forStartParameter(startParameter,settings);System.out.println("spec:"+spec);if(spec.containsProject(settings.getProjectRegistry())){System.out.println("spec.containsProject");setDefaultProject(spec,settings);returnsettings;}//TryagainwithemptysettingsStartParameternoSearchParameter=startParameter.newInstance();noSearchParameter.useEmptySettings();settings=findSettingsAndLoadIfAppropriate(gradle,noSearchParameter);//Setexplicitbuildfile,ifrequiredif(noSearchParameter.getBuildFile()!=null){ProjectDescriptorrootProject=settings.getRootProject();rootProject.setBuildFileName(noSearchParameter.getBuildFile().getName());}setDefaultProject(spec,settings);returnsettings;}
NotifyingSettingsLoader首先会根据装饰者模式逐个的调用进去,所以DefaultSettingsLoader.findAndLoadSettings方法,然后在回头看NotifyingSettingsLoader.findAndLoadSettings的其他代码。
DefaultSettingsLoader根据注释,它是要处理项目目录下的setting.gradle文件,同时处理buildSrc模块,这个好像一般项目没有。
所以,可以先看DefaultSettingsLoader.findAndLoadSettings方法。
1.DefaultSettingsLoader
文件路径:
subprojects\core\src\main\java\org\gradle\initialization\DefaultSettingsLoader.java
@OverridepublicSettingsInternalfindAndLoadSettings(GradleInternalgradle){StartParameterstartParameter=gradle.getStartParameter();System.out.println("DefaultSettingsLoader.findAndLoadSettingsstartParameter:"+startParameter+"gradle:"+gradle);SettingsInternalsettings=findSettingsAndLoadIfAppropriate(gradle,startParameter);System.out.println("settings:"+settings);ProjectSpecspec=ProjectSpecs.forStartParameter(startParameter,settings);System.out.println("spec:"+spec);if(spec.containsProject(settings.getProjectRegistry())){System.out.println("spec.containsProject");setDefaultProject(spec,settings);returnsettings;}//TryagainwithemptysettingsStartParameternoSearchParameter=startParameter.newInstance();noSearchParameter.useEmptySettings();settings=findSettingsAndLoadIfAppropriate(gradle,noSearchParameter);//Setexplicitbuildfile,ifrequiredif(noSearchParameter.getBuildFile()!=null){ProjectDescriptorrootProject=settings.getRootProject();rootProject.setBuildFileName(noSearchParameter.getBuildFile().getName());}setDefaultProject(spec,settings);returnsettings;}privateSettingsInternalfindSettingsAndLoadIfAppropriate(GradleInternalgradle,...returnsettingsProcessor.process(gradle,settingsLocation,buildSourceClassLoader,startParameter);}2.首先看findSettingsAndLoadIfAppropriate这个方法。看名字应该是寻找Settings并尝试加载它。它调用的是settingsProcessor.process这个settingsProcessor又使用了装饰者模式,共有3个类。publicclassNotifyingSettingsProcessorimplementsSettingsProcessor{}publicclassPropertiesLoadingSettingsProcessorimplementsSettingsProcessor{publicSettingsInternalprocess(GradleInternalgradle,SettingsLocationsettingsLocation,ClassLoaderScopebaseClassLoaderScope,StartParameterstartParameter){System.out.println("PropertiesLoadingSettingsProcessorrun");propertiesLoader.loadProperties(settingsLocation.getSettingsDir());returnprocessor.process(gradle,settingsLocation,baseClassLoaderScope,startParameter);}}publicclassScriptEvaluatingSettingsProcessorimplementsSettingsProcessor{publicSettingsInternalprocess(GradleInternalgradle,SettingsLocationsettingsLocation,ClassLoaderScopebaseClassLoaderScope,StartParameterstartParameter){System.out.println("ScriptProcessprocess");ClocksettingsProcessingClock=newClock();Map<String,String>properties=propertiesLoader.mergeProperties(Collections.<String,String>emptyMap());SettingsInternalsettings=settingsFactory.createSettings(gradle,settingsLocation.getSettingsDir(),settingsLocation.getSettingsScriptSource(),properties,startParameter,baseClassLoaderScope);applySettingsScript(settingsLocation,settings);LOGGER.debug("Timing:Processingsettingstook:{}",settingsProcessingClock.getTime());returnsettings;}}
真的,gradle源代码使用了很多装饰者模式。
3. 首先看看PropertiesLoadingSettingsProcessor.process方法
文件路径:subprojects\core\src\main\java\org\gradle\initialization\PropertiesLoadingSettingsProcessor.java
publicclassPropertiesLoadingSettingsProcessorimplementsSettingsProcessor{...publicSettingsInternalprocess(GradleInternalgradle,SettingsLocationsettingsLocation,ClassLoaderScopebaseClassLoaderScope,StartParameterstartParameter){System.out.println("PropertiesLoadingSettingsProcessorrun");propertiesLoader.loadProperties(settingsLocation.getSettingsDir());returnprocessor.process(gradle,settingsLocation,baseClassLoaderScope,startParameter);}}
文件路径:
subprojects\core\src\main\java\org\gradle\initialization\DefaultGradlePropertiesLoader.java
publicstaticfinalStringSYSTEM_PROP_PREFIX="systemProp";StringENV_PROJECT_PROPERTIES_PREFIX="ORG_GRADLE_PROJECT_";StringSYSTEM_PROJECT_PROPERTIES_PREFIX="org.gradle.project.";publicvoidloadProperties(FilesettingsDir){loadProperties(settingsDir,startParameter,getAllSystemProperties(),getAllEnvProperties());}voidloadProperties(FilesettingsDir,StartParameterstartParameter,Map<String,String>systemProperties,Map<String,String>envProperties){defaultProperties.clear();overrideProperties.clear();addGradleProperties(defaultProperties,newFile(settingsDir,Project.GRADLE_PROPERTIES));addGradleProperties(overrideProperties,newFile(startParameter.getGradleUserHomeDir(),Project.GRADLE_PROPERTIES));setSystemProperties(startParameter.getSystemPropertiesArgs());overrideProperties.putAll(getEnvProjectProperties(envProperties));overrideProperties.putAll(getSystemProjectProperties(systemProperties));for(Stringkey:systemProperties.keySet()){System.out.println("systemproperties,key:"+key+"value:"+systemProperties.get(key));}for(Stringkey:envProperties.keySet()){System.out.println("envproperties,key:"+key+"value:"+envProperties.get(key));}overrideProperties.putAll(startParameter.getProjectProperties());}privatevoidsetSystemProperties(Map<String,String>properties){addSystemPropertiesFromGradleProperties(defaultProperties);addSystemPropertiesFromGradleProperties(overrideProperties);System.getProperties().putAll(properties);}privatevoidaddSystemPropertiesFromGradleProperties(Map<String,String>properties){for(Stringkey:properties.keySet()){if(key.startsWith(Project.SYSTEM_PROP_PREFIX+'.')){System.setProperty(key.substring((Project.SYSTEM_PROP_PREFIX+'.').length()),properties.get(key));}}}
在loadProperties方法里面,它首先调用addGradleProperties方法分别把
a. 项目路径下面的gradle.properties
b. gradle_user_home路径下面的gradle.properties
两个文件分别读取到defaultProperties和overrideProperties两个map中。
比如,像这种属性:
org.gradle.jvmargs=-Xmx1536m#Whenconfigured,Gradlewillruninincubatingparallelmode.#Thisoptionshouldonlybeusedwithdecoupledprojects.Moredetails,visit#http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects#org.gradle.parallel=true
然后调用addSystemProperties方法把项目目录和gradle_user_home目录gradle.properties两个文件里面'systemProp'开头的属性设置到系统属性里面;同时把读取到的系统属性也设置进去。
再然后调用overrideProperties.putAll把环境变量中'ORG_GRADLE_PROJECT_'和系统属性中'org.gradle.project.'开头的变量,存放到overrideProperties map集合中。
最后,把projectProperties属性加入到overrideProperties map集合中。
4. 继续看ScriptEvaluatingSettingsProcessor.process
因为是装饰者模式,所以在调用完PropertiesLoadingSettingsProcessor.process之后,就会继续调用它里面包装的ScriptEvaluatingSettingsProcessor.process,代码如下:
文件路径:subprojects\core\src\main\java\org\gradle\initialization\ScriptEvaluatingSettingsProcessor.java
publicclassScriptEvaluatingSettingsProcessorimplementsSettingsProcessor{...publicSettingsInternalprocess(GradleInternalgradle,SettingsLocationsettingsLocation,ClassLoaderScopebaseClassLoaderScope,StartParameterstartParameter){...Map<String,String>properties=propertiesLoader.mergeProperties(Collections.<String,String>emptyMap());SettingsInternalsettings=settingsFactory.createSettings(gradle,settingsLocation.getSettingsDir(),settingsLocation.getSettingsScriptSource(),properties,startParameter,baseClassLoaderScope);applySettingsScript(settingsLocation,settings);...}...//文件路径:subprojects\core\src\main\java\org\gradle\initialization\DefaultGradlePropertiesLoader.javapublicMap<String,String>mergeProperties(Map<String,String>properties){Map<String,String>result=newHashMap<String,String>();result.putAll(defaultProperties);result.putAll(properties);result.putAll(overrideProperties);returnresult;}privatevoidapplySettingsScript(SettingsLocationsettingsLocation,finalSettingsInternalsettings){ScriptSourcesettingsScriptSource=settingsLocation.getSettingsScriptSource();ClassLoaderScopesettingsClassLoaderScope=settings.getClassLoaderScope();ScriptHandlerscriptHandler=scriptHandlerFactory.create(settingsScriptSource,settingsClassLoaderScope);ScriptPluginconfigurer=configurerFactory.create(settingsScriptSource,scriptHandler,settingsClassLoaderScope,settings.getRootClassLoaderScope(),true);System.out.println("applySettingsScriptconfigurer:"+configurer);configurer.apply(settings);}}
首先呢,把上一步加载好的属性都merge在一起,放到properties里面。
然后调用configurer.apply(settings)设置项目目录下settings.gradle文件属性
那DefaultSettingsLoader.findAndLoadSettings就基本结束了,回过头去看看NotifyingSettingsLoader.findAndLoadSettings的剩余部分代码。
5. 继续看NotifyingSettingsLoader.
publicclassNotifyingSettingsLoaderimplementsSettingsLoader{...@OverridepublicSettingsInternalfindAndLoadSettings(GradleInternalgradle){SettingsInternalsettings=settingsLoader.findAndLoadSettings(gradle);...gradle.getBuildListenerBroadcaster().settingsEvaluated(settings);buildLoader.load(settings.getRootProject(),settings.getDefaultProject(),gradle,settings.getRootClassLoaderScope());gradle.getBuildListenerBroadcaster().projectsLoaded(gradle);returnsettings;}}
首先发送一个事件通知settingsEvaulated,就是settings配置文件处理完毕。
然后调用buildLoader.load(xxx)
buildLoader又是使用了一个装饰者模式!从外到内包装如下:
publicclassProjectPropertySettingBuildLoaderimplementsBuildLoader{...publicvoidload(ProjectDescriptorrootProjectDescriptor,ProjectDescriptordefaultProject,GradleInternalgradle,ClassLoaderScopeclassLoaderScope){buildLoader.load(rootProjectDescriptor,defaultProject,gradle,classLoaderScope);setProjectProperties(gradle.getRootProject(),newCachingPropertyApplicator());}}publicclassInstantiatingBuildLoaderimplementsBuildLoader{privatefinalIProjectFactoryprojectFactory;publicInstantiatingBuildLoader(IProjectFactoryprojectFactory){this.projectFactory=projectFactory;}/***Createsthe{@linkorg.gradle.api.internal.GradleInternal}and{@linkProjectInternal}instancesforthegivenrootproject,readyfortheprojectstobeconfigured.*/publicvoidload(ProjectDescriptorrootProjectDescriptor,ProjectDescriptordefaultProject,GradleInternalgradle,ClassLoaderScopebaseClassLoaderScope){createProjects(rootProjectDescriptor,gradle,baseClassLoaderScope);attachDefaultProject(defaultProject,gradle);}privatevoidattachDefaultProject(ProjectDescriptordefaultProject,GradleInternalgradle){gradle.setDefaultProject(gradle.getRootProject().getProjectRegistry().getProject(defaultProject.getPath()));}privatevoidcreateProjects(ProjectDescriptorrootProjectDescriptor,GradleInternalgradle,ClassLoaderScopebaseClassLoaderScope){ProjectInternalrootProject=projectFactory.createProject(rootProjectDescriptor,null,gradle,baseClassLoaderScope.createChild("root-project"),baseClassLoaderScope);System.out.println("createproject,rootProject:"+rootProject);gradle.setRootProject(rootProject);addProjects(rootProject,rootProjectDescriptor,gradle,baseClassLoaderScope);}}
那上面这段代码的作用就是配置gradle project层级关系,比如上层是项目根目录,也就是rootProject。
然后试各个模块,包括主模块app
日志如下:
createProjectbuildFile:E:\work_space\Android-Prototype\build.gradleparent:nullcreateProjectbuildFile:E:\work_space\Android-Prototype\app\build.gradleparent:rootproject'Android-Prototype'createProjectbuildFile:E:\work_space\Android-Prototype\pushsdk\build.gradleparent:rootproject'Android-Prototype'createProjectbuildFile:E:\work_space\Android-Prototype\moduletest\build.gradleparent:rootproject'Android-Prototype'
然后发送project loaded通知。
gradle.getBuildListenerBroadcaster().projectsLoaded(gradle);
至此,Load步骤结束!
if(stage==null){//EvaluateinitscriptsinitScriptHandler.executeScripts(gradle);//Build`buildSrc`,loadsettings.gradle,andconstructcomposite(ifappropriate)settings=settingsLoader.findAndLoadSettings(gradle);stage=Stage.Load;}
下一篇文章来继续Configure过程。
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。