-
概述
前面我们分析到DefaultGradleLauncher的doClassicBuildStages方法:
private void doClassicBuildStages(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(); } } } }
private final ProjectsPreparer projectsPreparer; private final BuildWorkExecutor buildExecuter; private final SettingsPreparer settingsPreparer; private final TaskExecutionPreparer taskExecutionPreparer; private void prepareSettings() { if (this.stage == null) { //buildListener主要是日志通知什么的辅助功能 this.buildListener.buildStarted(this.gradle); this.settingsPreparer.prepareSettings(this.gradle); this.stage = DefaultGradleLauncher.Stage.LoadSettings; } } private void prepareProjects() { if (this.stage == DefaultGradleLauncher.Stage.LoadSettings) { ClassLoaderScope baseProjectClassLoaderScope = this.buildSourceBuilder.buildAndCreateClassLoader(this.gradle); this.gradle.setBaseProjectClassLoaderScope(baseProjectClassLoaderScope); this.projectsPreparer.prepareProjects(this.gradle); this.stage = DefaultGradleLauncher.Stage.Configure; } } private void prepareTaskExecution() { if (this.stage == DefaultGradleLauncher.Stage.Configure) { this.taskExecutionPreparer.prepareForTaskExecution(this.gradle); this.stage = DefaultGradleLauncher.Stage.TaskGraph; } } private void runWork() { if (this.stage != DefaultGradleLauncher.Stage.TaskGraph) { throw new IllegalStateException("Cannot execute tasks: current stage = " + this.stage); } else { List<Throwable> taskFailures = new ArrayList(); this.buildExecuter.execute(this.gradle, taskFailures); if (!taskFailures.isEmpty()) { throw new MultipleBuildFailures(taskFailures); } else { this.stage = DefaultGradleLauncher.Stage.RunTasks; } } }
可以看到,依次会进行到四个状态:LoadSettings、Configure、TaskGraph、RunTasks,其实最后还有一个Finished状态。
可知的字段(IDE索引):this.gradle实现类是DefaultGradle。主要是SettingsPreparer、ProjectsPreparer、TaskExecutionPreparer、BuildWorkExecutor的实现类是什么,他们的prepareXxx方法做了什么。
下面逐个来分析。
-
prepareSettings
this.settingsPreparer的实现类是DefaultSettingsPreparer:
public void prepareSettings(GradleInternal gradle) { //InitScriptHandler(执行init-scripts) this.initScriptHandler.executeScripts(gradle); SettingsLoader settingsLoader = gradle.getParent() != null ? this.settingsLoaderFactory.forNestedBuild() : this.settingsLoaderFactory.forTopLevelBuild(); //以DefaultSettingsLoader为例来看 settingsLoader.findAndLoadSettings(gradle); }
public SettingsInternal findAndLoadSettings(GradleInternal gradle) { StartParameter startParameter = gradle.getStartParameter(); //buildLayoutFactory包含了项目目录信息,这里获取setting.gradle文件的所在目录 SettingsLocation settingsLocation = this.buildLayoutFactory.getLayoutFor(new BuildLayoutConfiguration(startParameter)); //给System的静态字段props设置包含系统、环境、命令行参数的所有属性 this.loadGradlePropertiesFrom(settingsLocation); SettingsInternal settings = this.findSettingsAndLoadIfAppropriate(gradle, startParameter, settingsLocation, gradle.getClassLoaderScope()); ProjectSpec spec = ProjectSpecs.forStartParameter(startParameter, settings); if (this.useEmptySettings(spec, settings, startParameter)) { settings = this.createEmptySettings(gradle, startParameter, settings.getClassLoaderScope()); } this.setDefaultProject(spec, settings); return settings; } private SettingsInternal findSettingsAndLoadIfAppropriate(GradleInternal gradle, StartParameter startParameter, SettingsLocation settingsLocation, ClassLoaderScope classLoaderScope) { //this.settingsProcessor是ScriptEvaluatingSettingsProcessor SettingsInternal settings = this.settingsProcessor.process(gradle, settingsLocation, classLoaderScope, startParameter); this.validate(settings); return settings; }
public SettingsInternal process(GradleInternal gradle, SettingsLocation settingsLocation, ClassLoaderScope baseClassLoaderScope, StartParameter startParameter) { Timer settingsProcessingClock = Time.startTimer(); Map<String, String> properties = this.gradleProperties.mergeProperties(Collections.emptyMap()); TextResourceScriptSource settingsScript = new TextResourceScriptSource(this.textFileResourceLoader.loadFile("settings file", settingsLocation.getSettingsFile())); SettingsInternal settings = this.settingsFactory.createSettings(gradle, settingsLocation.getSettingsDir(), settingsScript, properties, startParameter, baseClassLoaderScope); gradle.getBuildListenerBroadcaster().beforeSettings(settings); //解析脚本 this.applySettingsScript(settingsScript, settings); LOGGER.debug("Timing: Processing settings took: {}", settingsProcessingClock.getElapsed()); return settings; }
private void applySettingsScript(TextResourceScriptSource settingsScript, SettingsInternal settings) { ScriptPlugin configurer = this.configurerFactory.create(settingsScript, settings.getBuildscript(), settings.getClassLoaderScope(), settings.getBaseClassLoaderScope(), true); configurer.apply(settings); }
configurer是ScriptPluginImpl:
public void apply(Object target) { DefaultServiceRegistry services = new DefaultServiceRegistry(new ServiceRegistry[]{DefaultScriptPluginFactory.this.scriptServices}); services.add(ScriptPluginFactory.class, DefaultScriptPluginFactory.this.scriptPluginFactory); services.add(ClassLoaderScope.class, this.baseScope); services.add(LoggingManagerInternal.class, (LoggingManagerInternal)DefaultScriptPluginFactory.this.loggingFactoryManager.create()); services.add(ScriptHandler.class, this.scriptHandler); ScriptTarget initialPassScriptTarget = this.initialPassTarget(target); //createCompiler创建的是ScriptCompilerImpl ScriptCompiler compiler = DefaultScriptPluginFactory.this.scriptCompilerFactory.createCompiler(this.scriptSource); CompileOperation<?> initialOperation = DefaultScriptPluginFactory.this.compileOperationFactory.getPluginsBlockCompileOperation(initialPassScriptTarget); //标志着setting、project还是其他脚本 Class<? extends BasicScript> scriptType = initialPassScriptTarget.getScriptClass(); //得到ScriptRunnerImpl ScriptRunner<? extends BasicScript, ?> initialRunner = compiler.compile(scriptType, initialOperation, this.baseScope, Actions.doNothing()); //实际上调用了其内部字段this.script的run方法,this.script是BasicScript的实现类,这里是SettingsScript,此外还有ProjectScript、InitScript等 initialRunner.run(target, services); //调用this.script的getInitialPluginRequests PluginRequests initialPluginRequests = DefaultScriptPluginFactory.this.getInitialPluginRequests(initialRunner); //this.script是groovy脚本解析后生成的class,这里获取根据plugin{}等信息生成的插件类集合 PluginRequests mergedPluginRequests = DefaultScriptPluginFactory.this.autoAppliedPluginHandler.mergeWithAutoAppliedPlugins(initialPluginRequests, target); PluginManagerInternal pluginManager = this.topLevelScript ? initialPassScriptTarget.getPluginManager() : null; //调用所有注册插件的apply方法 DefaultScriptPluginFactory.this.pluginRequestApplicator.applyPlugins(mergedPluginRequests, this.scriptHandler, pluginManager, this.targetScope); ScriptTarget scriptTarget = this.secondPassTarget(target); scriptType = scriptTarget.getScriptClass(); CompileOperation<BuildScriptData> operation = DefaultScriptPluginFactory.this.compileOperationFactory.getScriptCompileOperation(this.scriptSource, scriptTarget); ScriptRunner<? extends BasicScript, BuildScriptData> runner = compiler.compile(scriptType, operation, this.targetScope, ClosureCreationInterceptingVerifier.INSTANCE); if (scriptTarget.getSupportsMethodInheritance() && runner.getHasMethods()) { scriptTarget.attachScript(runner.getScript()); } if (runner.getRunDoesSomething()) { Runnable buildScriptRunner = () -> { //调用ScriptRunnerImpl内部的this.script的run方法 runner.run(target, services); }; boolean hasImperativeStatements = ((BuildScriptData)runner.getData()).getHasImperativeStatements(); scriptTarget.addConfiguration(buildScriptRunner, !hasImperativeStatements); } }
initialPassTarget方法会根据需求产生三种不同的ScriptTarget:
private ScriptTarget initialPassTarget(Object target) { return this.wrap(target, true); } private ScriptTarget wrap(Object target, boolean isInitialPass) { if (target instanceof ProjectInternal && this.topLevelScript) { return new ProjectScriptTarget((ProjectInternal)target); } else if (target instanceof GradleInternal && this.topLevelScript) { return new InitScriptTarget((GradleInternal)target); } else if (target instanceof SettingsInternal && this.topLevelScript) { return (ScriptTarget)(isInitialPass ? new InitialPassSettingScriptTarget((SettingsInternal)target) : new SettingScriptTarget((SettingsInternal)target)); } else { return new DefaultScriptTarget(target); } }
getInitialPluginRequests方法如下:
private PluginRequests getInitialPluginRequests(ScriptRunner<? extends BasicScript, ?> initialRunner) { if (initialRunner.getRunDoesSomething()) { BasicScript script = (BasicScript)initialRunner.getScript(); if (script instanceof PluginsAwareScript) { return ((PluginsAwareScript)script).getPluginRequests(); } } return PluginRequests.EMPTY; }
initialRunner是ScriptRunnerImpl,它的getScript方法:
public T getScript() { if (this.script == null) { //获取类 Class<? extends T> scriptClass = this.compiledScript.loadClass(); //构造类对象 this.script = (Script)DefaultScriptRunnerFactory.this.instantiator.newInstance(scriptClass, new Object[0]); this.script.setScriptSource(this.source); this.script.setContextClassloader(this.contextClassLoader); DefaultScriptRunnerFactory.this.listener.onScriptClassLoaded(this.source, scriptClass); } return this.script; }
scriptClass是什么?this.compiledScript是ClassesDirCompiledScript,它的loadClass方法如下:
public Class<? extends T> loadClass() { if (this.scriptClass == null) { ... try { this.scope = this.prepareClassLoaderScope(); ClassLoader loader = this.scope.getLocalClassLoader(); this.scriptClass = loader.loadClass(this.source.getClassName()).asSubclass(this.scriptBaseClass); } ... } return this.scriptClass; }
可以看到最终的scriptClass就是根据this.source.getClassName()来获取的,根据前面的查找,已知this.source是TextResourceScriptSource,它的getClassName方法如下:
public String getClassName() { if (this.className == null) { this.className = this.initClassName(); } return this.className; } private String initClassName() { //这里会获取到settings.gradle文件的URI路径信息 URI sourceUri = this.getResource().getLocation().getURI(); if (sourceUri != null) { //解析获取类名 String path = sourceUri.toString(); return this.classNameFromPath(path); } else { return "script_" + HashUtil.createCompactMD5(this.resource.getText()); } } private String classNameFromPath(String path) { String name = StringUtils.substringBeforeLast(StringUtils.substringAfterLast(path, "/"), "."); StringBuilder className = new StringBuilder(name.length()); for(int i = 0; i < name.length(); ++i) { char ch = name.charAt(i); //判断每个字母是否符合Java有效标识符规则 className.append(Character.isJavaIdentifierPart(ch) ? ch : '_'); } //判断首字母是否符合Java有效标识符首字母规则 if (!Character.isJavaIdentifierStart(className.charAt(0))) { className.insert(0, '_'); } className.setLength(Math.min(className.length(), 30)); //对其编码 className.append('_'); className.append(HashUtil.createCompactMD5(path)); return className.toString(); }
可见,最后的ClassName是一个类似“settings_X43nbjb4234aerknb”这样的东西,这样的东西自然不是一个标准的可使用的类,所以推测一定在loadClass方法中做了什么特别的解析处理,经过查找loadClass的重写方法,在GroovyClassLoader(kotlin的话应该是其他专门的ClassLoader)中发现了可能有关联的实现:
public Class loadClass(String name, boolean lookupScriptFiles, boolean preferClassOverScript, boolean resolve) throws ClassNotFoundException, CompilationFailedException { ... URL source = this.resourceLoader.loadGroovySource(name); Class oldClass = cls; cls = null; cls = this.recompile(source, name, oldClass); ... return cls; } protected Class recompile(URL source, String className, Class oldClass) throws CompilationFailedException, IOException { ... //注意这里为什么className不再往下传递了? return this.parseClass(new GroovyCodeSource(new File(source.toURI()), this.sourceEncoding)); ... }
这里调用了parseClass方法,但是className没有往下传递,这是为什么?因为接下来就是解析settings.gradle文件了,而这个过程产生的类就和“settings”本身无关了。
parseClass方法最终调用到了GroovyClassLoader的doParseClass方法:
private Class doParseClass(GroovyCodeSource codeSource) { validate(codeSource); CompilationUnit unit = this.createCompilationUnit(this.config, codeSource.getCodeSource()); ... SourceUnit su = null; File file = codeSource.getFile(); if (file != null) { //将构造的SourceUnit放到CompilationUnit的this.queuedSources数组中 su = unit.addSource(file); } else { URL url = codeSource.getURL(); if (url != null) { su = unit.addSource(url); } else { su = unit.addSource(codeSource.getName(), codeSource.getScriptText()); } } ClassCollector collector = this.createCollector(unit, su); //设置内部的classgenCallback为collector unit.setClassgenCallclassgenCallback为back(collector); ... //最终这个方法会触发collector的createClass方法 unit.compile(goalPhase); Class answer = collector.generatedClass; String mainClass = su.getAST().getMainClassName(); Iterator var9 = collector.getLoadedClasses().iterator(); while(var9.hasNext()) { Object o = var9.next(); Class clazz = (Class)o; String clazzName = clazz.getName(); this.definePackageInternal(clazzName); this.setClassCacheEntry(clazz); if (clazzName.equals(mainClass)) { answer = clazz; } } return answer; }
CompilationUnit的compile方法如下:
public void compile(int throughPhase) throws CompilationFailedException { //从1开始,这里使用this.phase来控制执行的顺序,所有的SourceUnitOperation在添加时都会被添加到一个LinkedList,然后这个LinkedList会被添加到一个叫this.phaseOperations的数组,下标就是指定的phase,等到compile时会按照phase获取指定的LinkedList,然后遍历执行SourceUnitOperation的call方法 this.gotoPhase(1); //从1开始,到throughPhase结束 throughPhase = Math.min(throughPhase, 9); while(throughPhase >= this.phase && this.phase <= 9) { if (this.phase == 4) { this.doPhaseOperation(this.resolve); if (this.dequeued()) { continue; } } //遍历this.phaseOperations中的每一个SourceUnitOperation,执行doPhaseOperation方法 this.processPhaseOperations(this.phase); ... if (this.progressCallback != null) { this.progressCallback.call(this, this.phase); } this.completePhase(); this.applyToSourceUnits(this.mark); if (!this.dequeued()) { this.gotoPhase(this.phase + 1); if (this.phase == 7) { this.sortClasses(); } } } this.errorCollector.failIfErrors(); }
先看一下doPhaseOperation方法:
private void doPhaseOperation(Object operation) { if (operation instanceof PrimaryClassNodeOperation) { this.applyToPrimaryClassNodes((PrimaryClassNodeOperation)operation); } else if (operation instanceof SourceUnitOperation) { this.applyToSourceUnits((SourceUnitOperation)operation); } else { this.applyToGeneratedGroovyClasses((GroovyClassOperation)operation); } }
这里会针对三种不同的operation执行不同的方法,内部其实就是执行每个SourceUnitOperation的call方法。
那this.phaseOperations中的元素怎么来的?在CompilationUnit的构造方法中会调用addPhaseOperations方法:
private void addPhaseOperations() { this.addPhaseOperation((SourceUnitOperation)(new SourceUnitOperation() { public void call(SourceUnit source) throws CompilationFailedException { //这里会执行脚本的groovy规则解析,得到一个AST对象:this.ast //内部通过AntlrParserPlugin来操作 source.parse(); } }), 2); //this.convert中利用AST产生一个ModuleNode:this.output this.addPhaseOperation((SourceUnitOperation)this.convert, 3); this.addPhaseOperation((PrimaryClassNodeOperation)(new PrimaryClassNodeOperation() { public void call(SourceUnit source, GeneratorContext context, ClassNode classNode) throws CompilationFailedException { //枚举类处理 EnumVisitor ev = new EnumVisitor(CompilationUnit.this, source); ev.visitClass(classNode); } }), 3); //this.resolver去根据ast加载脚本中所有的类 this.addPhaseOperation((SourceUnitOperation)this.resolve, 4); //写入导包、注解、包、初始化代码块等信息 this.addPhaseOperation((PrimaryClassNodeOperation)this.staticImport, 4); this.addPhaseOperation((PrimaryClassNodeOperation)(new PrimaryClassNodeOperation() { public void call(SourceUnit source, GeneratorContext context, ClassNode classNode) throws CompilationFailedException { //内部类信息解析 InnerClassVisitor iv = new InnerClassVisitor(CompilationUnit.this, source); iv.visitClass(classNode); } }), 4); this.addPhaseOperation((PrimaryClassNodeOperation)(new PrimaryClassNodeOperation() { public void call(SourceUnit source, GeneratorContext context, ClassNode classNode) throws CompilationFailedException { if (!classNode.isSynthetic()) { //类本身的继承、接口等信息解析 GenericsVisitor genericsVisitor = new GenericsVisitor(source); genericsVisitor.visitClass(classNode); } } }), 4); this.addPhaseOperation((PrimaryClassNodeOperation)(new PrimaryClassNodeOperation() { public void call(SourceUnit source, GeneratorContext context, ClassNode classNode) throws CompilationFailedException { //拓展特性解析 TraitComposer.doExtendTraits(classNode, source, CompilationUnit.this); } }), 5); //日志或错误信息输出 this.addPhaseOperation((SourceUnitOperation)this.compileCompleteCheck, 5); //类内容信息解析,内部会调用ClassCollector的call方法 this.addPhaseOperation((PrimaryClassNodeOperation)this.classgen, 7); //this.output将解析好的类信息输出成class文件,放在指定位置 this.addPhaseOperation(this.output); this.addPhaseOperation((PrimaryClassNodeOperation)(new PrimaryClassNodeOperation() { public void call(SourceUnit source, GeneratorContext context, ClassNode classNode) throws CompilationFailedException { //注解信息解析 AnnotationCollectorTransform.ClassChanger actt = new AnnotationCollectorTransform.ClassChanger(); actt.transformClass(classNode); } }), 4); ASTTransformationVisitor.addPhaseOperations(this); this.addPhaseOperation((PrimaryClassNodeOperation)(new PrimaryClassNodeOperation() { public void call(SourceUnit source, GeneratorContext context, ClassNode classNode) throws CompilationFailedException { //静态成员信息 StaticVerifier sv = new StaticVerifier(); sv.visitClass(classNode, source); } }), 4); this.addPhaseOperation((PrimaryClassNodeOperation)(new PrimaryClassNodeOperation() { public void call(SourceUnit source, GeneratorContext context, ClassNode classNode) throws CompilationFailedException { //内部类成员信息 InnerClassCompletionVisitor iv = new InnerClassCompletionVisitor(CompilationUnit.this, source); iv.visitClass(classNode); } }), 5); this.addPhaseOperation((PrimaryClassNodeOperation)(new PrimaryClassNodeOperation() { public void call(SourceUnit source, GeneratorContext context, ClassNode classNode) throws CompilationFailedException { //枚举成员信息 EnumCompletionVisitor ecv = new EnumCompletionVisitor(CompilationUnit.this, source); ecv.visitClass(classNode); } }), 5); this.addPhaseOperation((PrimaryClassNodeOperation)(new PrimaryClassNodeOperation() { public void call(SourceUnit source, GeneratorContext context, ClassNode classNode) throws CompilationFailedException { //元数据信息 Object callback = classNode.getNodeMetaData(StaticCompilationMetadataKeys.DYNAMIC_OUTER_NODE_CALLBACK); if (callback instanceof PrimaryClassNodeOperation) { ((PrimaryClassNodeOperation)callback).call(source, context, classNode); classNode.removeNodeMetaData(StaticCompilationMetadataKeys.DYNAMIC_OUTER_NODE_CALLBACK); } } }), 6); }
按照phase的顺序依次执行,利用ASM等字节码工具,整套过程把groovy脚本转换成class文件。
-
prepareProjects
DefaultProjectsPreparer的prepareProjects方法如下:
public void prepareProjects(GradleInternal gradle) { this.maybeInformAboutIncubatingMode(gradle); //生成所有project的DefaultProject实例并保存起来 this.buildLoader.load(gradle.getSettings(), gradle); if (gradle.getParent() == null) { this.buildRegistry.beforeConfigureRootBuild(); } //开启所有project的configure if (gradle.getStartParameter().isConfigureOnDemand()) { this.projectConfigurer.configure(gradle.getRootProject()); } else { this.projectConfigurer.configureHierarchy(gradle.getRootProject()); (new ProjectsEvaluatedNotifier(this.buildOperationExecutor)).notify(gradle); } this.modelConfigurationListener.onConfigure(gradle); }
this.buildLoader是InstantiatingBuildLoader,它的load方法如下:
public void load(SettingsInternal settings, GradleInternal gradle) { this.createProjects(gradle, settings.getRootProject()); this.attachDefaultProject(gradle, settings.getDefaultProject()); } private void attachDefaultProject(GradleInternal gradle, ProjectDescriptor defaultProjectDescriptor) { ProjectInternal rootProject = gradle.getRootProject(); ProjectRegistry<ProjectInternal> projectRegistry = rootProject.getProjectRegistry(); String defaultProjectPath = defaultProjectDescriptor.getPath(); ProjectInternal defaultProject = (ProjectInternal)projectRegistry.getProject(defaultProjectPath); if (defaultProject == null) { throw new IllegalStateException("Did not find project with path " + defaultProjectPath); } else { gradle.setDefaultProject(defaultProject); } } private void createProjects(GradleInternal gradle, ProjectDescriptor rootProjectDescriptor) { ClassLoaderScope baseProjectClassLoaderScope = gradle.baseProjectClassLoaderScope(); ClassLoaderScope rootProjectClassLoaderScope = baseProjectClassLoaderScope.createChild("root-project"); ProjectInternal rootProject = this.projectFactory.createProject(gradle, rootProjectDescriptor, (ProjectInternal)null, rootProjectClassLoaderScope, baseProjectClassLoaderScope); gradle.setRootProject(rootProject); this.createChildProjectsRecursively(gradle, rootProject, rootProjectDescriptor, rootProjectClassLoaderScope, baseProjectClassLoaderScope); } private void createChildProjectsRecursively(GradleInternal gradle, ProjectInternal parentProject, ProjectDescriptor parentProjectDescriptor, ClassLoaderScope parentProjectClassLoaderScope, ClassLoaderScope baseProjectClassLoaderScope) { Iterator var6 = parentProjectDescriptor.getChildren().iterator(); while(var6.hasNext()) { ProjectDescriptor childProjectDescriptor = (ProjectDescriptor)var6.next(); ClassLoaderScope childProjectClassLoaderScope = parentProjectClassLoaderScope.createChild("project-" + childProjectDescriptor.getName()); ProjectInternal childProject = this.projectFactory.createProject(gradle, childProjectDescriptor, parentProject, childProjectClassLoaderScope, baseProjectClassLoaderScope); this.createChildProjectsRecursively(gradle, childProject, childProjectDescriptor, childProjectClassLoaderScope, baseProjectClassLoaderScope); } }
可见,这里会根据多项目配置从root-project开始迭代创建所有子项目的ProjectInternal对象,this.projectFactory是ProjectFactory,它的createProject方法如下:
public ProjectInternal createProject(GradleInternal gradle, ProjectDescriptor projectDescriptor, @Nullable ProjectInternal parent, ClassLoaderScope selfClassLoaderScope, ClassLoaderScope baseClassLoaderScope) { Path projectPath = ((DefaultProjectDescriptor)projectDescriptor).path(); ProjectState projectContainer = this.projectStateRegistry.stateFor(this.owner.getBuildIdentifier(), projectPath); File buildFile = projectDescriptor.getBuildFile(); TextResource resource = this.textFileResourceLoader.loadFile("build file", buildFile); ScriptSource source = new TextResourceScriptSource(resource); DefaultProject project = (DefaultProject)this.instantiator.newInstance(DefaultProject.class, new Object[]{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); } this.projectRegistry.addProject(project); projectContainer.attachMutableModel(project); return project; }
可见,对每个子项目都生成了一个DefaultProject对象,持有了对应的build.gradle脚本内容,并添加到this.projectRegistry(DefaultProjectRegistry)中。
接下来开始执行每个project的configure,this.projectConfigurer是TaskPathProjectEvaluator,它的configureHierarchy方法如下:public void configureHierarchy(ProjectInternal project) { this.configure(project); Iterator var2 = project.getSubprojects().iterator(); while(var2.hasNext()) { Project sub = (Project)var2.next(); this.configure((ProjectInternal)sub); } } public void configure(ProjectInternal project) { if (this.cancellationToken.isCancellationRequested()) { throw new BuildCancelledException(); } else { project.evaluate(); } }
可见,这里执行每个DefaultProject的evaluate方法:
public DefaultProject evaluate() { //this.getProjectEvaluator()这里得到的是ConfigureActionsProjectEvaluator this.getProjectEvaluator().evaluate(this, this.state); return this; }
ConfigureActionsProjectEvaluator的evaluate方法如下:
public void evaluate(ProjectInternal project, ProjectStateInternal state) { Iterator var3 = this.configureActions.iterator(); while(var3.hasNext()) { ProjectConfigureAction configureAction = (ProjectConfigureAction)var3.next(); configureAction.execute(project); } }
configureActions就是解析后的包含的各种内容项,比如BasePlugin、IdePlugin、JavaBasePlugin、ConfigAction等里面实现的匿名方法,这里会逐一执行。
-
prepareTaskExecution
DefaultTaskExecutionPreparer的prepareForTaskExecution方法如下:
public void prepareForTaskExecution(GradleInternal gradle) { this.buildConfigurationActionExecuter.select(gradle); TaskExecutionGraphInternal taskGraph = gradle.getTaskGraph(); taskGraph.populate(); this.includedBuildControllers.populateTaskGraphs(); if (gradle.getStartParameter().isConfigureOnDemand()) { (new ProjectsEvaluatedNotifier(this.buildOperationExecutor)).notify(gradle); } }
这里主要是将任务图中的被此次gradle执行命令include的task都加到DefaultIncludedBuildController的includedBuild(IncludedBuildState)中。
-
runWork
到了runWork阶段,最后也会执行一系列实现自Action的一系列回调,和configure阶段类似的,只不过这里是执行而不是配置。
-
总结
经过一系列繁琐的过程后,settings.gradle脚本中的信息转化为了class对象,在这个对象里涵盖了project和module任务等信息,ScriptPluginImpl的apply方法最后其实就是调用了这个动态生成的class对象的run方法,内部进行解析project、tasks等的逻辑,生成项目包含逻辑、任务依赖图,后面根据这些信息执行configure阶段,最后按照任务依赖顺序执行任务。
Gradle源码解读(三)
最后编辑于 :
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。
推荐阅读更多精彩内容
- 一、知识详解模块 1.dex/class深入讲解 2.jvm/dvm/art三个虚拟机的深入讲解 3.class ...
- 学习android的同学都知道android工程从使用android studio开发以后就使用了[gradle作...