Gradle浅析之生命周期

493 阅读11分钟

我们在日常开发中,无论是使用图形构建按钮还是使用命令开启构建任务,其会经历设置,陪着,构建任务依赖图,最终执行我们输入的任务。但是其内部如何进行这一系列过程的,今天我们就分析Android中输入 ./gradlew assembleBuild后, gradle的生命周期原理。 ​

Gradle命令入口

在我们每一个android下面都有一个 gradlew.bat脚本文件,其为我们执行 ./gradlew命令的入口。其最终会执行下面的命令

@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*

其最终会调用GradleWrapperMain类,调用其main方法,其为gradle源码中的类。也是我们执行gradlew命令的入口。到这里我们要继续看起源码,必须下载对应的gradle源码。

Gradle源码

我们可以从github下载对应的源码,我这里分析的源码下载的是7.3的。下载下来用Intellij idead编译需要一段时间,后续开启缓存模式构建就快了。 ​

Gradle下载

接下来我们准备好源码,进入GradleMain看起源码。我们开发中知道,如果第一次构建项目其会更加我们项目下的gradle目录下的wrapper.properties进行下载对应的版本,如果本地有其就不会下载,今天我们就探究一下其原理。 ​

  • wrapper.properties配置
distributionBase=GRADLE_USER_HOME
distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip
distributionPath=wrapper/dists
zipStorePath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME

GradleWrapperMain

读取wrapper的配置

  • 其首先从我们目录下gradle的配置文件读取配置信息,即上面列出的
  • 然后创建WrapperExeucter
  • 接着执行其ececute,其会传入Install和BootstrapMainStarter
public static void main(String[] args) {
   File wrapperJar = wrapperJar();
   File propertiesFile = wrapperProperties(wrapperJar);
   .... 
   WrapperExecutor wrapperExecutor = WrapperExecutor.forWrapperPropertiesFile(propertiesFile);
   wrapperExecutor.execute(
                args,
                new Install(logger, new Download(logger, "gradlew", UNKNOWN_VERSION), new PathAssembler(gradleUserHome, rootDir)),
                new BootstrapMainStarter());    
        
}

WrapperExecuter

其executer方法,内部会首先调用Install对应的方法,去判断是否需要下载Gradle,然后调用bootstrapMainStarter的启动方法

public void execute(String[] args, Install install, BootstrapMainStarter bootstrapMainStarter) throws Exception {
        File gradleHome = install.createDist(config);
        bootstrapMainStarter.start(args, gradleHome);
    }

Install配置Gradle

其createDist方法,就是根据配置里的信息去下载对应版本的gradle,如果本地存在,则直接加载缓存。

public File createDist(final WrapperConfiguration configuration)  {
        //下载地址
final URI distributionUrl = configuration.getDistribution();
       // 文件256校验码
final String distributionSha256Sum = configuration.getDistributionSha256Sum();

        //本地对应的配置 
final PathAssembler.LocalDistribution localDistribution = pathAssembler.
    getDistribution(configuration);
final File distDir = localDistribution.getDistributionDir();
final File localZipFile = localDistribution.getZipFile();

...
//是否需要下载,本地文件是否存在    
boolean needsDownload = !localZipFile.isFile();
                URI safeDistributionUrl = Download.safeUri(distributionUrl);

if (needsDownload) {
  File tmpZipFile = new File(localZipFile.getParentFile(), 
                   localZipFile.getName() + ".part");
  tmpZipFile.delete();
  logger.log("Downloading " + safeDistributionUrl);
  //开始下载
  download.download(distributionUrl, tmpZipFile);
  tmpZipFile.renameTo(localZipFile);
} 
...
//校验文件是否下载正确
verifyDownloadChecksum(configuration.getDistribution().toString(), 
                       localZipFile, distributionSha256Sum);    
//解压
unzip(localZipFile, distDir);
   
    
    
}   
    
    
    

经过上面的步骤,就按照gradle目录下的配置,下载好对应的gradle版本包,即我们后面整体gradle执行代码。

BootstrapMainStarter开启任务

其start方法,开始gradle的构建流程,其调用流程比较复杂,不同版本代码逻辑有些不同。具体过程不是我们本文的重点,我简单梳理了一个大致调用流程,感兴趣的可以作为参看查看其源码。其最终会调用VintageBuildModelController的doBuildState。

流程图

Gradle 生命周期.jpg 接下来我们分析其生命周期的每个阶段做了什么。

Gradle生命周期

查看对应VintageBuildModelController类State,其主要有四个阶段。

生命周期阶段

private enum Stage implements StateTransitionController.State {
        Created, 
        LoadSettings, 
        Configure, 
        ScheduleTasks, 
        TaskGraph
    }

�其doBuilldState会根据对应要执行到的阶段,依次调用对应的方法。下面我们依次分析。

LoadSettings

进入doBuildStages会根据传递的状态执行到对应的状态

private void doBuildStages(Stage upTo) {
        prepareSettings();
        if (upTo == Stage.LoadSettings) {
            return;
        }
        prepareProjects();
        if (upTo == Stage.Configure) {
            return;
        }
        prepareTaskGraph();
        if (upTo == Stage.ScheduleTasks) {
            return;
        }
        prepareTaskExecution();
    }

最终执行的为prepareTaskExecution。最初执行的为prepareSetting,对应的周期阶段为LoadtingSetting.

SettingPreparer开启LoadSetting

preparesetting方法内部调用SettingPrepare的preparesetting方法,开始任务,同时执行前,将Stage设置为LoadSetting。

private void prepareSettings() {
    controller.transitionIfNotPreviously(Stage.Created, Stage.LoadSettings, 
     () -> settingsPreparer.prepareSettings(gradle));
    }

其对应的实现类为DefaultSettingsPreparer,其具体流程如下

  • 判断是否为RootBuild,如果是,从顶层开始,否则从内部开始
  • 然后查找对应的Setting.gradle并加载
  @Override
    public void prepareSettings(GradleInternal gradle) {
        SettingsLoader settingsLoader = gradle.isRootBuild() ? 
            settingsLoaderFactory.forTopLevelBuild() : 
        settingsLoaderFactory.forNestedBuild();
        settingsLoader.findAndLoadSettings(gradle);
    }

我们以RootBuild为例分析,其调用forTopLenvelBuild方法,返回对应的SettingLoader,其类似其他代码,通过逐级代理,预处理任务,最终的SettingLoader为DefaultSettingsLoader�

public SettingsLoader forTopLevelBuild() {
        return new GradlePropertiesHandlingSettingsLoader(
            new InitScriptHandlingSettingsLoader(
                new CompositeBuildSettingsLoader(
                    new ChildBuildRegisteringSettingsLoader(
                        new CommandLineIncludedBuildSettingsLoader(
                            defaultSettingsLoader()
                        ),
                        buildRegistry,
                        buildIncluder),
                    buildRegistry),
                initScriptHandler),
            buildLayoutFactory,
            gradlePropertiesController
        );
    }

DefalutSeetingLoader查找处理_setting.gradle_

�其类注释说明其功能,定位和处理setting.gradle文件,读取里面配置的Module. 上面最后会调用findAndLoadSettings,我们查看源码,探究其如何定位和处理对应的文件

public SettingsInternal findAndLoadSettings(GradleInternal gradle) {
        StartParameter startParameter = gradle.getStartParameter();
        //获取构建项目下setting文件或目录
        SettingsLocation settingsLocation = buildLayoutFactory.getLayoutFor(new BuildLayoutConfiguration(startParameter));
        //根据查找的文件,加载读取内容
        SettingsInternal settings = findSettingsAndLoadIfAppropriate(gradle, startParameter, settingsLocation, gradle.getClassLoaderScope());
        ProjectSpec spec = ProjectSpecs.forStartParameter(startParameter, settings);
        if (useEmptySettings(spec, settings, startParameter)) {
            settings = createEmptySettings(gradle, startParameter, settings.getClassLoaderScope());
        }
        //根据setting项目描述配置rootProjet相关信息 
        setDefaultProject(spec, settings);
        return settings;
    }
定位setting文件

其首先获取我们项目整体目录,然后在其目录下获取setting.gradle文件

  • 构建项目是否使用空setting结构,如是则直接返回空
  • 获取目录下setting文件
  • 如果存在检测是否为文件,否则抛出异常
  • 如果存在则返回对应的Buildlayout

BuildLayout会保护具体文件的地址信息

public BuildLayout getLayoutFor(BuildLayoutConfiguration configuration) {
        if (configuration.isUseEmptySettings()) {
            return buildLayoutFrom(configuration, null);
        }
        File explicitSettingsFile = configuration.getSettingsFile();
        if (explicitSettingsFile != null) {
            if (!explicitSettingsFile.isFile()) {
                throw new MissingResourceException(explicitSettingsFile.toURI(), String.format("Could not read settings file '%s' as it does not exist.", explicitSettingsFile.getAbsolutePath()));
            }
            return buildLayoutFrom(configuration, explicitSettingsFile);
        }

        return getLayoutFor(configuration.getCurrentDir(), configuration.isSearchUpwards());
    }
public BuildLayout(File rootDirectory, File settingsDir, @Nullable File settingsFile, ScriptFileResolver scriptFileResolver) {
        super(settingsDir, settingsFile);
        this.rootDirectory = rootDirectory;
        this.scriptFileResolver = scriptFileResolver;
    }

加载setting.gradle文件

其通过SettingProcessor处理对应的文件,然后返回SettingInternal类

/**
     * Finds the settings.gradle for the given startParameter, and loads it if contains the project selected by the
     * startParameter, or if the startParameter explicitly specifies a settings script.  If the settings file is not
     * loaded (executed), then a null is returned.
     */ 
private SettingsInternal findSettingsAndLoadIfAppropriate(
        GradleInternal gradle,
        StartParameter startParameter,
        SettingsLocation settingsLocation,
        ClassLoaderScope classLoaderScope
    ) {
        SettingsInternal settings = settingsProcessor.process(gradle, settingsLocation, classLoaderScope, startParameter);
        validate(settings);
        return settings;
    }

SettingInternal具体实现类为DefalutSetting,其中settingsProcessor有多个实现类,类似上面的处理,其也是逐级嵌套,最终的为**ScriptEvaluatingSettingsProcessor,**我们看起代码 �发现其会加载对应文件里的内容,然后创建SettingsInternal

public SettingsInternal process(GradleInternal gradle,
                                    SettingsLocation settingsLocation,
                                    ClassLoaderScope baseClassLoaderScope,
                                    StartParameter startParameter) {
        //统计时间配置
        Timer settingsProcessingClock = Time.startTimer();
        //解析gradleProperties文件的配置信息
        Map<String, String> properties = gradleProperties.mergeProperties(emptyMap());
        //解析里面的内容,并加载
        TextResourceScriptSource settingsScript = new TextResourceScriptSource(textFileResourceLoader.loadFile("settings file", settingsLocation.getSettingsFile()));
        //创建SettingInternal
        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;
    }
创建Settinginternal
public SettingsInternal createSettings(...){
    
ClassLoaderScope classLoaderScope = baseClassLoaderScope.createChild("settings[" + gradle.getIdentityPath() + "]");
        ScriptHandlerInternal settingsScriptHandler = scriptHandlerFactory.create(settingsScript, classLoaderScope);
        DefaultSettings settings = instantiator.newInstance(DefaultSettings.class,
            serviceRegistryFactory,
            gradle,
            classLoaderScope,
            baseClassLoaderScope,
            settingsScriptHandler,
            settingsDir,
            settingsScript,
            startParameter
        );
        DynamicObject dynamicObject = ((DynamicObjectAware) settings).getAsDynamicObject();
        ((ExtensibleDynamicObject) dynamicObject).addProperties(gradleProperties);
        return settings;

}

总结

到这里LoadSetting就结束了,其主要做了以下工作

  • 查找setting文件
  • 加载解析gradle.properties文件
  • 解析setting文件内容,并创建对应的类:DefalutSetting

Configure

项目配置阶段入口方法为 prepareProjects,与LoadSetting类似,其也有对应的Prepare处理,其为ProjectPrepare

private void prepareProjects() {
controller.transitionIfNotPreviously(Stage.LoadSettings, Stage.Configure, 
 () -> projectsPreparer.prepareProjects(gradle));
 }

ProjectsPreparer

其方法传入的参数GradleInternal,包含了上一阶段处理完的settings 对象配置,即DefalutSetting. 其对应的实现类为DefalutProjectsPreparer.同样与LoadSetting类似,其也判断是否为RootBuild,同时其也会判断是否配置的后台

 if (buildModelParameters.isConfigureOnDemand() && gradle.isRootBuild()) {
            projectConfigurer.configure(gradle.getRootProject());
        } else {
            projectConfigurer.configureHierarchy(gradle.getRootProject());
            new ProjectsEvaluatedNotifier(buildOperationExecutor).notify(gradle);
        }

无论何种情况,都有ProjectConfigurer处理

TaskPathProjectEvaluator处理Project

ProjectConfigurer的实现类为TaskPathProjectEvaluator。两个方法的区别时,configureHierarchyFully会先配置自己,然后依次遍历配置每一个项目,最终入口都是config.因此我们就直接分析config。

@Override
    public void configureHierarchy(ProjectInternal project) {
        configure(project);
        for (Project sub : project.getSubprojects()) {
            configure((ProjectInternal) sub);
        }
    }

 @Override
 public void configure(ProjectInternal project) {
        if (cancellationToken.isCancellationRequested()) {
            throw new BuildCancelledException();
        }
        // Need to configure intermediate parent projects for configure-on-demand
        ProjectInternal parentProject = project.getParent();
        if (parentProject != null) {
            configure(parentProject);
        }
        project.getOwner().ensureConfigured();
    }

最终调用eensureConfigured,通过层层导演,最终会调用ProjectConfigureAction的execute方法

//in class ConfigureActionsProjectEvaluator
@Override
    public void evaluate(ProjectInternal project, ProjectStateInternal state) {
        for (ProjectConfigureAction configureAction : configureActions) {
            configureAction.execute(project);
        }
    }

ProjectConfigureAction的实现类有多个,我们看该类注释

/**
 * Can be implemented by plugins to auto-configure each project.
 *
 * <p>Implementations are discovered using the JAR service locator mechanism (see {@link org.gradle.internal.service.ServiceLocator}).
 * Each action is invoked for each project that is to be configured, before the project has been configured. Actions are executed
 * in an arbitrary order.
 */
public interface ProjectConfigureAction extends Action<ProjectInternal> {
}

其可被对应的插件实现,去配置每一个项目,这样结合我们在开发android项目都会使用插件,这样当执行到此阶段,即会自动配置,因此我们直接看对应的实现,即PluginsProjectConfigureActions

PluginsProjectConfigureActions自动配置每个Project

 @Override
    public void execute(ProjectInternal project) {
        for (Action<ProjectInternal> action : actions) {
            action.execute(project);
        }
    }

到这里配置阶段结束,具体的配置有具体的插件实现,其会在此阶段配置好自己。我们WrapperPluginAutoApplyAction为例,其最终会调用我们对应插件的apply方法。

public void execute(ProjectInternal project) {
        project.getPluginManager().apply("org.gradle.wrapper");
    }

这里配置的是wrapper这个插件。我们查看给方法注释

/**
    * Applies the plugin with the given ID. Does nothing if 
    * the plugin has already been applied.
    * <p>
    * Plugins in the {@code "org.gradle"} namespace can be applied 
    *directly via name.
    * That is, the following two lines are equivalent…
    * <pre class='autoTested'>
    * pluginManager.apply "org.gradle.java"
    * pluginManager.apply "java"
    * </pre>
    *
    * @param pluginId the ID of the plugin to apply
    * @since 2.3
    */
    void apply(String pluginId);


总结

该阶段主要会默认配置org.gradle下的Project,然后调用具体每个插件的实现,配置每个插件。

TaskGraph

接下来是task有向图的构建,其在上一阶段的基础上,配置每个task的依赖关系。

ScheduleTasks

分析任务图的构建我们需要回到流程图分析那里,其调用VintageBuildController.doBuildStage的发起点是在DefaultTreeWorkPrepare.这里其分成了多个阶段,即其首先调用doBuildStage达到_TaskSchedule_ �阶段,然后调用populateTaskGraph真正的构建任务图**。**我们看起代码

    
    // in the  DefaultTreeWorkPrepare
    @Override
    public void scheduleRequestedTasks() {
        //该方法到达TaskSchedule
        buildController.prepareToScheduleTasks();
        //完成真正task有向图构建
        includedBuildTaskGraph.prepareTaskGraph(() -> {
        //处理初步任务有向图    
        buildController.scheduleRequestedTasks();
        //填充任务图    
        includedBuildTaskGraph.populateTaskGraphs();
        //结束构建,根据输入发起任务
        buildController.finalizeWorkGraph(true);
        });
    }
prepareTaskGraph

doBuildStages内部,在执行完配置后,进入下一个阶段,调用该方法,将其Stage转移到ScheduTasks,我们查看源码看起做了什么工作 其通过TaskGraphPrepares的prepareForTaskScheduling开启处理

private void prepareTaskGraph() {
   controller.transitionIfNotPreviously(Stage.Configure, Stage.ScheduleTasks, 
   () -> taskGraphPreparer.prepareForTaskScheduling(gradle));
}

TaskGraphPrepares有两个实现类,类似上面的处理也是逐级嵌套依次处理。其分别是:

  • DefaultTaskSchedulingPreparer
  • �ExcludedTaskFilteringProjectsPreparer

其中 DefaultTaskSchedulingPreparer存在delegate,因此其不是不最终的调用而是ExcludedTaskFilteringProjectsPreparer

    //DefaultTaskSchedulingPreparer
    @Override
    public void prepareForTaskScheduling(GradleInternal gradle) {
        // Make root build substitutions available
        if (gradle.isRootBuild()) {
            buildStateRegistry.afterConfigureRootBuild();
        }

        delegate.prepareForTaskScheduling(gradle);
    }
   // ExcludedTaskFilteringProjectsPreparer
    @Override
    public void prepareForTaskScheduling(GradleInternal gradle) {
        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));
            }
            gradle.getTaskGraph().useFilter(Specs.intersect(filters));
        }
    }

查看代码我们知道,这里主要做了两部分工作

  1. DefaultTaskSchedulingPreparer通知项目配置完成
  2. 将不需要添加到依赖图的任务排除

prepareTaskGraph

IncludedBuildTaskGraph在VintageBuildController.doBuildStage到达ScheduleTask后,完成前期工作后开始构建任务图,其实现类为DefalutIncludedBuildTaskGraph

/**
* Does the work to schedule tasks and prepare the task graphs for execution.
*/
void prepareTaskGraph(Runnable action){
    withState(() -> {
      expectInState(State.NotPrepared);
      state = State.QueuingTasks;
      buildOperationExecutor.run(new RunnableBuildOperation() {
        @Override
        public void run(BuildOperationContext context) {
           action.run();
           context.setResult(new CalculateTreeTaskGraphBuildOperationType.Result() {
          });
                }

          @Override
          public BuildOperationDescriptor.Builder description() {
            return BuildOperationDescriptor
                .displayName("Calculate build tree task graph")
             .details(new CalculateTreeTaskGraphBuildOperationType.Details() {
              });
                }
            });
            expectInState(State.Populated);
            state = State.ReadyToRun;
            return       
         
    }

该方法是通过CalculateTreeTaskGraphBuildOperationType告知我们做了什么,同时保存结果。其真正的工作是action.run,其实际调用的就是里面包裹的方法

/**
 * Computing the task graph for the build tree based on the inputs 
 * and build configuration.
 */
public final class CalculateTreeTaskGraphBuildOperationTyp    
includedBuildTaskGraph.prepareTaskGraph(() -> {
            buildController.scheduleRequestedTasks();
            includedBuildTaskGraph.populateTaskGraphs();
            buildController.finalizeWorkGraph(true);
        })

TaskExecution

其主要为task的执行配置Gradle对象,其是通过TaskExecutionPreparer的prepareForTaskExecution发起

/**
 * Responsible for preparing `Gradle` instances for task execution. The result is passed to a {@link org.gradle.execution.BuildWorkExecutor} for execution. Prior to preparing for task execution, the `Gradle` instance has its projects configured by a {@link org.gradle.configuration.ProjectsPreparer}.
 *
 * <p>This includes resolving the entry tasks and calculating the task graph.</p>
 */
public interface TaskExecutionPreparer {
    void prepareForTaskExecution(GradleInternal gradle);
}

�查看类注释,其主要解决Task入口,和任务图计算,其实现类为DefaultTaskExecutionPreparer,

@Override
    public void prepareForTaskExecution(GradleInternal gradle) {
        buildConfigurationActionExecuter.select(gradle);

        if (buildModelParameters.isConfigureOnDemand() && gradle.isRootBuild()) {
            new ProjectsEvaluatedNotifier(buildOperationExecutor).notify(gradle);
        }
    }

�其核心在第一个调用,其会对任务进行选择. 其通过buildConfigurationActionExecuter的seletc发起

 @Override
    public void select(final GradleInternal gradle) {
        // We know that we're running single-threaded here, so we can use coarse grained locks
        projectStateRegistry.withMutableStateOfAllProjects(() -> {
            configure(taskSelectors, gradle, 0);
        });
    }

其中configure内部为遍历taskSelectors,依次取出每一个taskSelector,即BuildConfigurationAction �然后调用其config去筛选计算任务。

rivate void configure(final List<? extends BuildConfigurationAction> processingConfigurationActions, final GradleInternal gradle, final int index) {
        if (index >= processingConfigurationActions.size()) {
            return;
        }
        processingConfigurationActions.get(index).configure(new BuildExecutionContext() {
            @Override
            public GradleInternal getGradle() {
                return gradle;
            }

            @Override
            public void proceed() {
                configure(processingConfigurationActions, gradle, index + 1);
            }

        });
    }

BuildConfigurationAction

其默认有两个实现类,因此遍历即分别调用这两个类

  • DefaultTasksBuildExecutionAction
  • TaskNameResolvingBuildConfigurationAction
  1. TaskNameResolvingBuildConfigurationAction

其根据平常去构建taskGraph

 @Override
    public void configure(BuildExecutionContext context) {
        GradleInternal gradle = context.getGradle();
        TaskExecutionGraphInternal taskGraph = gradle.getTaskGraph();

        List<TaskExecutionRequest> taskParameters = gradle.getStartParameter().getTaskRequests();
        for (TaskExecutionRequest taskParameter : taskParameters) {
            List<TaskSelection> taskSelections = commandLineTaskParser.parseTasks(taskParameter);
            for (TaskSelection taskSelection : taskSelections) {
                LOGGER.info("Selected primary task '{}' from project {}", taskSelection.getTaskName(), taskSelection.getProjectPath());
                //添加到taskGraph
                taskGraph.addEntryTasks(taskSelection.getTasks());
            }
        }

        context.proceed();
    }

  1. DefaultTasksBuildExecutionAction

�其是处理project默认的task,如果没有会为其添加helpTask

public void configure(BuildExecutionContext context) {
        StartParameter startParameter = context.getGradle().getStartParameter();
        for (TaskExecutionRequest request : startParameter.getTaskRequests()) {
            if (!request.getArgs().isEmpty()) {
                context.proceed();
                return;
            }
        }

        // 获取Project默认的Tasks
        ProjectInternal project = context.getGradle().getDefaultProject();
        //so that we don't miss out default tasks
        projectConfigurer.configure(project);
        //处理默认的task
        List<String> defaultTasks = project.getDefaultTasks();
        if (defaultTasks.size() == 0) {
            defaultTasks = new ArrayList<>();
            for (BuiltInCommand command : builtInCommands) {
                defaultTasks.addAll(command.asDefaultTask());
            }
            LOGGER.info("No tasks specified. Using default task {}", GUtil.toString(defaultTasks));
        } else {
            LOGGER.info("No tasks specified. Using project default tasks {}", GUtil.toString(defaultTasks));
        }
        //将处理后的tasks,设置到参数里,交由我们上面分析的TaskNameResolvingBuildConfigurationAction
        //处理
        startParameter.setTaskNames(defaultTasks);
        context.proceed();
    }

到这里,通过doBuildStage中的prepareForTaskExecution,我们将处理后的任务添加到了taskGraph中。

populateTaskGraphs

该方法完成任务图的填充。

/**
     * Finish populating task graphs, once all entry point tasks have been scheduled.
     */
    void populateTaskGraphs();

 @Override
    public void populateTaskGraphs() {
        withState(() -> {
            assertCanQueueTask();
            includedBuilds.populateTaskGraphs();
            state = State.Populated;
            return null;
        });
    }
Controller填充任务图

填充任务图具体有对应的IncludeBuildControllers完成

@Override
    public void populateTaskGraphs() {
        boolean tasksDiscovered = true;
        while (tasksDiscovered) {
            tasksDiscovered = false;
            for (IncludedBuildController buildController : ImmutableList.copyOf(buildControllers.values())) {
                if (buildController.populateTaskGraph()) {
                    tasksDiscovered = true;
                }
            }
        }
        for (IncludedBuildController buildController : buildControllers.values()) {
            buildController.prepareForExecution();
        }
    }

到这里就完成了任务图的构建,同时为下一步任务执行做好准备,触发时间开始执行任务

finalizeWorkGraph

�其会调用taskGraph的polulate,如果一切就绪

 @Override
    public void finalizeWorkGraph(boolean workScheduled) {
        if (workScheduled) {
            TaskExecutionGraphInternal taskGraph = gradle.getTaskGraph();
            taskGraph.populate();
        }
        finalizeGradleServices(gradle);
    }

我们查看该方法对应的注释

   /**
     * Does the work to populate the task graph based on tasks that have been added. Fires events and no further tasks should be added.
     */
    void populate();

后续具体执行这里就不分析了。 ​

总结

经过上面的整个分析,我们就清楚的知道了,当我们在AndroidStudio中敲下命令后,其如何去检测我们gradle的版本,并进行下载。同时我们项目中的setting.gradle的作用,最后就是任务如何添加,依赖关系如何构建。其中有的地方逻辑比较复杂,这里没有去深入分析,重点是掌握其整个流程。后续有需要,我们就可深入去分析研究它。 ​

参考资料

Gradle 源码解析
Gradle