An overview of the
I started a new series. The goal of this series of learning Gradle is to thoroughly understand Gradle. The main goal is to make notes on your own understanding to prevent forgetting
Gradle Series (1) : Groovy learning
Gradle Learning series (2) : Gradle core decryption
Gradle Plugins
Gradle dependencies
Gradle Transform. Gradle Transform
Gradle learning series (6) : Gradle source code parsing
Gradle source code parsing
gradlew
First of all, we usually use the command./ gradLew assembleDebug, where gradLew is the entrance of Gradle
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
Copy the code
This command triggers GradleWrapperMain. It also supports $@ as an argument, which is how all of our usual gradLew commands work
Now take a look at GradleWrapperMain
GradleWrapperMain
public class GradleWrapperMain {
// Run the gradLew script command to trigger the entry
public static void main(String[] args) throws Exception {
// This is to get the wrapper.jar and properties files in the project directoryFile wrapperJar = wrapperJar(); File propertiesFile = wrapperProperties(wrapperJar); File rootDir = rootDir(wrapperJar); .// The following two lines are the most important
WrapperExecutor wrapperExecutor = WrapperExecutor.forWrapperPropertiesFile(propertiesFile);
wrapperExecutor.execute(
args,
new Install(logger,
new Download(logger, "gradlew", wrapperVersion()), new PathAssembler(gradleUserHome)),
new BootstrapMainStarter());
}
Copy the code
WrapperExecutor. ForWrapperPropertiesFile is through Java Properties to parse gradle/wrapper/gradle-wrapper. Properties files such as distributionUrl
WrapperExecutor. Execute (args) is the parameter in gradLew, Install is the parameter to manage whether the local project has the gradle version specified in the wrapper, if not, parse and download it. BootstrapMainStarter is the wrapper’s actual entry point for executing Gradle. Let’s take a look at the execute method
public void execute(String[] args, Install install, BootstrapMainStarter bootstrapMainStarter) throws Exception {
// Config is the configuration resolved by gradle-wrapper.properties
File gradleHome = install.createDist(config);
bootstrapMainStarter.start(args, gradleHome);
}
Copy the code
Install. CreateDist (config) download gradle Wrappe dependencies and source code Gradle /wrapper/gradle-wrapper.properties configuredistributionURL. The download addresses are the distributionPath and zipStorePath configured in gradle-wrapper.properties. ZipStorePath is where the compressed package is downloaded and distributionPath is where it is decompressed
Gradle builds consist of the following 5 processes, and the enumeration of these processes
private static enum Stage {
LoadSettings,
Configure,
TaskGraph,
RunTasks {
String getDisplayName() {
return "Build";
}
},
Finished;
private Stage() {
}
String getDisplayName() {
return this.name(); }}Copy the code
Gradle builds go through five processes. Let’s examine each of these processes in turn
A LoadSettings.
LoadSettings mainly loads settings.gradle file, and then creates the corresponding project.
BootstrapMainStarter. Start function is executed gradle build process, through complex call process, will eventually trigger DefaultGradleLauncher. ExecuteTasks () method, we look at the way
public GradleInternal executeTasks() {
this.doBuildStages(DefaultGradleLauncher.Stage.RunTasks);
return this.gradle;
}
Copy the code
The doBuildStages method is called
private void doBuildStages(DefaultGradleLauncher.Stage upTo) {
// Check that the state is not FinishPreconditions.checkArgument(upTo ! = DefaultGradleLauncher.Stage.Finished,"Stage.Finished is not supported by doBuildStages.");
try {
if (upTo == DefaultGradleLauncher.Stage.RunTasks && this.instantExecution.canExecuteInstantaneously()) {
// Execute this method if the state is RunTasks
this.doInstantExecution();
} else {
// If not RunTasks, execute the following
this.doClassicBuildStages(upTo); }}catch (Throwable var3) {
this.finishBuild(upTo.getDisplayName(), var3); }}Copy the code
Next look at doClassicBuildStages
private void doClassicBuildStages(DefaultGradleLauncher.Stage upTo) {
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(); }}}}Copy the code
This code is divided by state, and the method that each state needs to execute is differentiated
- When the state is LoadSettings, prepareSettings is executed by loading the setting.gralde file and creating the corresponding project
- When the state is Configure, perform prepareProjects
- PrepareTaskExecution is performed when the state is TaskGraph
- When the state is RunTasks, perform instantExecution. SaveScheduledWork () and runWork ()
Let’s go ahead and look at the prepareSettings method
private void prepareSettings() {
if (this.stage == null) {
this.buildListener.buildStarted(this.gradle);
this.settingsPreparer.prepareSettings(this.gradle);
// Set the status to LoadSettings
this.stage = DefaultGradleLauncher.Stage.LoadSettings; }}Copy the code
buildListener.buildStarted(this.gradle)
First call the buildListener. BuildStarted (enclosing gradle); Notifies the build to begin. We talked about this callback in the previous article
settingsPreparer.prepareSettings(this.gradle);
Then the prepareSettings method for DefaultSettingsPreparer is executed
public void prepareSettings(GradleInternal gradle) {
// Run the init.gradle script
this.initScriptHandler.executeScripts(gradle); SettingsLoader settingsLoader = gradle.getParent() ! =null ? this.settingsLoaderFactory.forNestedBuild() : this.settingsLoaderFactory.forTopLevelBuild();
// Find and load the location of setting.gradle
settingsLoader.findAndLoadSettings(gradle);
}
Copy the code
PrepareSettings basically does two things
- Run the init.gradle script
- Locate and load setting.gradle
The findAndLoadSettings method here does a lot of things like this:
- Find the location of setting.gradle
- Build the contents of the buildSrc folder, which is the buildSrc plug-in mentioned earlier
- Parsing gradle. Properites
- The analytic setting. Gradle
- Create a project and subproject
2. ConfigureBuild
The LoadSettings phase is the configureBuild phase, which compiles gradle scripts into classes and executes them. This phase executes the prepareProjects method
private void prepareProjects() {
if (this.stage == DefaultGradleLauncher.Stage.LoadSettings) {
Prepare classlocder / /
ClassLoaderScope baseProjectClassLoaderScope = this.buildSourceBuilder.buildAndCreateClassLoader(this.gradle);
this.gradle.setBaseProjectClassLoaderScope(baseProjectClassLoaderScope);
// Here the prepareProjects method for DefaultProjectsPreparer is called
this.projectsPreparer.prepareProjects(this.gradle);
// Reset the status to Configure
this.stage = DefaultGradleLauncher.Stage.Configure; }}Copy the code
Next, look at the prepareProjects method for DefaultProjectsPreparer
public void prepareProjects(GradleInternal gradle) {
this.maybeInformAboutIncubatingMode(gradle);
this.buildLoader.load(gradle.getSettings(), gradle);
if (gradle.getParent() == null) {
this.buildRegistry.beforeConfigureRootBuild();
}
/ / comment 1
if (gradle.getStartParameter().isConfigureOnDemand()) {
this.projectConfigurer.configure(gradle.getRootProject());
} else {
/ / comment 2
this.projectConfigurer.configureHierarchy(gradle.getRootProject());
(new ProjectsEvaluatedNotifier(this.buildOperationExecutor)).notify(gradle);
}
this.modelConfigurationListener.onConfigure(gradle);
}
Copy the code
- Note 1: If the parameter configure-on-demand is specified in the gradle.properties file, only the main project and the projects needed to execute the task will be configured.
- Note 2: If no parameter is configured, then all items are configured, and the last call is
TaskPathProjectEvaluator
theconfigureHierarchy
methods
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); }}Copy the code
So you go through all the porject, you configure all the projects, and then the configure method calls the run method of EvaluateProject
public void run(final BuildOperationContext context) {
this.project.getMutationState().withMutableState(new Runnable() {
public void run() {
try {
EvaluateProject.this.state.toBeforeEvaluate();
/ / callback ProjectEvaluationListener beforeEvaluate interface
LifecycleProjectEvaluator.this.buildOperationExecutor.run(new LifecycleProjectEvaluator.NotifyBeforeEvaluate(EvaluateProject.this.project, EvaluateProject.this.state));
if(! EvaluateProject.this.state.hasFailure()) {
EvaluateProject.this.state.toEvaluate();
try {
// 2. The default init, wrapper task and default plug-in are set in the evaluate method, and the build. Gradle script is compiled and executed
LifecycleProjectEvaluator.this.delegate.evaluate(EvaluateProject.this.project, EvaluateProject.this.state);
} catch (Exception var10) {
LifecycleProjectEvaluator.addConfigurationFailure(EvaluateProject.this.project, EvaluateProject.this.state, var10, context);
} finally {
EvaluateProject.this.state.toAfterEvaluate();
/ / callback ProjectEvaluationListener afterEvaluate
LifecycleProjectEvaluator.this.buildOperationExecutor.run(new LifecycleProjectEvaluator.NotifyAfterEvaluate(EvaluateProject.this.project, EvaluateProject.this.state)); }}if (EvaluateProject.this.state.hasFailure()) {
EvaluateProject.this.state.rethrowFailure();
} else{ context.setResult(ConfigureProjectBuildOperationType.RESULT); }}finally {
EvaluateProject.this.state.configured(); }}}); }Copy the code
This method basically does three things
- The callback ProjectEvaluationListener beforeEvaluate interface
evaluate
Set up theInit and wrapper
Two default tasks, set the default help pluginorg.gradle.help-tasks
, and compile and executebuild.gradle
- The callback ProjectEvaluationListener afterEvaluate interface.
3. TaskGraph
The next step is to configure the Task directed graph by calling DefaultGradleLauncher’s prepareTaskExecution method to create a directed acyclic graph
private void prepareTaskExecution() {
if (this.stage == DefaultGradleLauncher.Stage.Configure) {
this.taskExecutionPreparer.prepareForTaskExecution(this.gradle);
// Change the phase to TaskGraph
this.stage = DefaultGradleLauncher.Stage.TaskGraph; }}Copy the code
Call the next BuildOperatingFiringTaskExecutionPreparer prepareForTaskExecution
public void prepareForTaskExecution(GradleInternal gradle) {
this.buildOperationExecutor.run(new BuildOperatingFiringTaskExecutionPreparer.CalculateTaskGraph(gradle));
}
Copy the code
And then the run method of CalculateTaskGraph is called
private class CalculateTaskGraph implements RunnableBuildOperation {
public void run(BuildOperationContext buildOperationContext) {
// Fill the task diagram
final TaskExecutionGraphInternal taskGraph = this.populateTaskGraph();
buildOperationContext.setResult(new Result() {
public List<String> getRequestedTaskPaths() {
return this.toTaskPaths(taskGraph.getRequestedTasks());
}
public List<String> getExcludedTaskPaths() {
return this.toTaskPaths(taskGraph.getFilteredTasks());
}
private List<String> toTaskPaths(Set<Task> tasks) {
return ImmutableSortedSet.copyOf(Collections2.transform(tasks, new Function<Task, String>() {
public String apply(Task task) {
returntask.getPath(); } })).asList(); }}); }}Copy the code
Here we call the populateTaskGraph method directly to populate the task graph, so let’s take a look at that method
TaskExecutionGraphInternal populateTaskGraph() {
BuildOperatingFiringTaskExecutionPreparer.this.delegate.prepareForTaskExecution(this.gradle);
return this.gradle.getTaskGraph();
}
Copy the code
There are calls the DefaultTaskExecutionPreparer prepareForTaskExecution method
public void prepareForTaskExecution(GradleInternal gradle) {
/ / comment 1
this.buildConfigurationActionExecuter.select(gradle);
TaskExecutionGraphInternal taskGraph = gradle.getTaskGraph();
/ / comment 2
taskGraph.populate();
this.includedBuildControllers.populateTaskGraphs();
if (gradle.getStartParameter().isConfigureOnDemand()) {
(new ProjectsEvaluatedNotifier(this.buildOperationExecutor)).notify(gradle); }}Copy the code
See note 1 at first, and finally call DefaultBuildConfigurationActionExecuter select method, the source code is as follows
public void select(final GradleInternal gradle) {
this.projectStateRegistry.withLenientState(new Runnable() {
public void run() {
// Create a collection
List<BuildConfigurationAction> processingBuildActions = CollectionUtils.flattenCollections(BuildConfigurationAction.class.new Object[]{DefaultBuildConfigurationActionExecuter.this.configurationActions, DefaultBuildConfigurationActionExecuter.this.taskSelectors});
// Then the configure method is called
DefaultBuildConfigurationActionExecuter.this.configure(processingBuildActions, gradle, 0); }}); }Copy the code
Note that you first create a List, and then you call the configure method, so let’s look at the source code for the configure method
private void configure(final List<BuildConfigurationAction> processingConfigurationActions, final GradleInternal gradle, final int index) {
if (index < processingConfigurationActions.size()) {
((BuildConfigurationAction)processingConfigurationActions.get(index)).configure(new BuildExecutionContext() {
public GradleInternal getGradle() {
return gradle;
}
public void proceed() {
DefaultBuildConfigurationActionExecuter.this.configure(processingConfigurationActions, gradle, index + 1); }}); }}Copy the code
Here you can see is removed from the List in order, and then in turn perform ExcludedTaskFilteringBuildConfigurationAction, DefaultTasksBuildExecutionAction TaskNameResolvingBuildConfigurationAction, perform the configure method of class
Let’s look at the configure methods for each of these classes in turn
ExcludedTaskFilteringBuildConfigurationAction ## configure
public void configure(BuildExecutionContext context) {
GradleInternal gradle = context.getGradle();
// Get the task to be excluded
Set<String> excludedTaskNames = gradle.getStartParameter().getExcludedTaskNames();
if(! excludedTaskNames.isEmpty()) { Set<Spec<Task>> filters =new HashSet();
Iterator var5 = excludedTaskNames.iterator();
while(var5.hasNext()) {
String taskName = (String)var5.next();
filters.add(this.taskSelector.getFilter(taskName));
}
// Add tasks to the TaskGraph to filter
gradle.getTaskGraph().useFilter(Specs.intersect(filters));
}
context.proceed();
}
Copy the code
The TaskGraph is set to filter tasks that need to be excluded from the task, so that the subsequent calculation of dependencies will exclude the corresponding task
DefaultTasksBuildExecutionAction ## configure
public void configure(BuildExecutionContext context) {
StartParameter startParameter = context.getGradle().getStartParameter();
Iterator var3 = startParameter.getTaskRequests().iterator();
TaskExecutionRequest request;
do {
if(! var3.hasNext()) { ProjectInternal project = context.getGradle().getDefaultProject();this.projectConfigurer.configure(project);
List<String> defaultTasks = project.getDefaultTasks();
if (defaultTasks.size() == 0) {
defaultTasks = Collections.singletonList("help");
LOGGER.info("No tasks specified. Using default task {}", GUtil.toString(defaultTasks));
} else {
LOGGER.info("No tasks specified. Using project default tasks {}", GUtil.toString(defaultTasks));
}
startParameter.setTaskNames(defaultTasks);
context.proceed();
return;
}
request = (TaskExecutionRequest)var3.next();
} while(request.getArgs().isEmpty());
context.proceed();
}
Copy the code
Will the command line pass in the name of the Task? If you specify the Task to execute, then do nothing
If not specified, see if there is a defaultTask in the project, which can be specified in build.gradle with defaultTasks
If the default task does not have one, set the specified task to Help task
TaskNameResolvingBuildConfigurationAction ## configure
public void configure(BuildExecutionContext context) {
GradleInternal gradle = context.getGradle();
TaskExecutionGraphInternal taskGraph = gradle.getTaskGraph();
List<TaskExecutionRequest> taskParameters = gradle.getStartParameter().getTaskRequests();
Iterator var5 = taskParameters.iterator();
while(var5.hasNext()) {
TaskExecutionRequest taskParameter = (TaskExecutionRequest)var5.next();
/ / parsing task
List<TaskSelection> taskSelections = this.commandLineTaskParser.parseTasks(taskParameter);
Iterator var8 = taskSelections.iterator();
// Add task to taskGraph
while(var8.hasNext()) {
TaskSelection taskSelection = (TaskSelection)var8.next();
LOGGER.info("Selected primary task '{}' from project {}", taskSelection.getTaskName(), taskSelection.getProjectPath());
taskGraph.addEntryTasks(taskSelection.getTasks());
}
}
context.proceed();
}
Copy the code
There are two main operations here
- If the task name is specified, the task name in the Project will be selected. If the task name is not specified, the task name in the Project will be selected
- Walk through and add all selected Tasks to the taskGraph instance. This will handle the dependencies of the task, including dependson finalizedby MustrunAfter shouldrunAfter, And then the information is stored in the org. Gradle. Execution. Taskgraph. TaskInfo
Finally back to DefaultTaskExecutionPreparer prepareForTaskExecution 2
Call the taskGraph populate method to generate a task graph based on the tasks and dependencies calculated in the previous step
Four RunTasks.
Next, look at the RunTasks phase
private void doClassicBuildStages(DefaultGradleLauncher.Stage upTo) {
this.prepareSettings();
if(upTo ! = DefaultGradleLauncher.Stage.LoadSettings) {this.prepareProjects();
if(upTo ! = DefaultGradleLauncher.Stage.Configure) {this.prepareTaskExecution();
if(upTo ! = DefaultGradleLauncher.Stage.TaskGraph) {this.instantExecution.saveTaskGraph();
/ / comment 1
this.runWork(); }}}}Copy the code
The RunTasks phase calls the runWork() method in comment 1. Let’s look at the code in detail
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();
/ / comment 1
this.buildExecuter.execute(this.gradle, taskFailures);
if(! taskFailures.isEmpty()) {throw new MultipleBuildFailures(taskFailures);
} else {
this.stage = DefaultGradleLauncher.Stage.RunTasks; }}}Copy the code
The Execute method of DefaultBuildWorkExecutor is called at note 1
public void execute(GradleInternal gradle, Collection<? super Throwable> failures) {
this.execute(gradle, 0, failures);
}
private void execute(final GradleInternal gradle, final int index, final Collection<? super Throwable> taskFailures) {
if (index < this.executionActions.size()) {
// Execute the execute method of the list class
((BuildExecutionAction)this.executionActions.get(index)).execute(new BuildExecutionContext() {
public GradleInternal getGradle() {
return gradle;
}
public void proceed() {
// Get the next execution in the list
DefaultBuildWorkExecutor.this.execute(gradle, index + 1, taskFailures); } }, taskFailures); }}Copy the code
This is going to be called firstDryRunBuildExecutionAction
theexecute
methods
public void execute(BuildExecutionContext context, Collection<? super Throwable> taskFailures) {
GradleInternal gradle = context.getGradle();
/ / comment 1if (gradle.getStartParameter().isDryRun()) { Iterator var4 = gradle.getTaskGraph().getAllTasks().iterator(); while(var4.hasNext()) { Task task = (Task)var4.next(); this.textOutputFactory.create(DryRunBuildExecutionAction.class).append(((TaskInternal)task).getIdentityPath().getPath()) .append("").style(Style.ProgressStatus).append("SKIPPED").println(); } } else { context.proceed(); }}}Copy the code
Check the command line at note 1 to see if there is an argument –dry-run. If there is, skip the execution of the task and print the task name and order
Then execute SelectedTaskExecutionAction the execute method
public void execute(BuildExecutionContext context, Collection<? super Throwable> taskFailures) {
GradleInternal gradle = context.getGradle();
TaskExecutionGraphInternal taskGraph = gradle.getTaskGraph();
if (gradle.getStartParameter().isContinueOnFailure()) {
taskGraph.setContinueOnFailure(true);
}
taskGraph.addTaskExecutionGraphListener(new SelectedTaskExecutionAction.BindAllReferencesOfProjectsToExecuteListener());
/ / comment 1
taskGraph.execute(taskFailures);
}
Copy the code
In the note 1 call the DefaultTaskExecutionGraph the execute method, we look at the specific code
public void execute(Collection<? super Throwable> failures) {
ProjectExecutionServiceRegistry projectExecutionServices = new ProjectExecutionServiceRegistry(this.globalServices);
try {
/ / comment 1this.executeWithServices(projectExecutionServices, failures); } finally { projectExecutionServices.close(); }}Copy the code
The executeWithServices method was called at comment 1. Take a look at the source code
private void executeWithServices(ProjectExecutionServiceRegistry projectExecutionServices, Collection<? super Throwable> failures) {
...
try {
/ / comment 1
this.planExecutor.process(this.executionPlan, failures, new DefaultTaskExecutionGraph.BuildOperationAwareExecutionAction(this.buildOperationExecutor.getCurrentOperation(), new DefaultTaskExecutionGraph.InvokeNodeExecutorsAction(this.nodeExecutors, projectExecutionServices)));
LOGGER.debug("Timing: Executing the DAG took "+ clock.getElapsed()); } finally { ... }}Copy the code
Planexecutor. process is called at note 1, and finally the process method of DefaultPlanExecutor is called
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();
/ / comment 1this.startAdditionalWorkers(executionPlan, nodeExecutor, executor, parentWorkerLease); (new DefaultPlanExecutor.ExecutorWorker(executionPlan, nodeExecutor, parentWorkerLease, this.cancellationToken, this.coordinationService)).run(); this.awaitCompletion(executionPlan, failures); } finally { executor.stop(); }}Copy the code
The startAdditionalWorkers method is called at note 1
private void startAdditionalWorkers(ExecutionPlan executionPlan, Action<? super Node> nodeExecutor, Executor executor, WorkerLease parentWorkerLease) {
LOGGER.debug("Using {} parallel executor threads", this.executorCount);
for(int i = 1; i < this.executorCount; ++i) { executor.execute(new DefaultPlanExecutor.ExecutorWorker(executionPlan, nodeExecutor, parentWorkerLease, this.cancellationToken, this.coordinationService)); }}Copy the code
By default, 8 threads are used to execute tasks
Some preprocessing before executing a Task
First, call TaskExecutionListener#beforeExecute.
CatchExceptionTaskExecuter.execute // Add a try catch to prevent exceptions during execution
ExecuteAtMostOnceTaskExecuter.execute // Check whether the task has been executed
SkipOnlyIfTaskExecuter.execute // Check whether the onlyif condition of the task is met
SkipTaskWithNoActionsExecuter.execute // Skip tasks that have no action. Without action, the task does not need to be executed
ResolveTaskArtifactStateTaskExecuter.execute // Set the artifact's state
SkipEmptySourceFilesTaskExecuter.execute // Skip tasks whose source file has been set but whose source file is empty. An empty source file indicates that the task has no resources to process
ValidatingTaskExecuter.execute() // Verify whether the task can be executed
ResolveTaskOutputCachingStateExecuter.execute // Process the task output cache
SkipUpToDateTaskExecuter.execute // Skip the update-to-date task
ExecuteActionsTaskExecuter.execute // Execute the task
Copy the code
Actually executing task
Final call ExecuteActionsTaskExecuter. TaskExecution execute to actually perform the task
public WorkResult execute(@Nullable InputChangesInternal inputChanges, InputChangesContext context) {
....
WorkResult var5;
try {
var5 = this.executeWithPreviousOutputFiles(inputChanges);
} finally {
outputs.setPreviousOutputFiles((FileCollection)null);
}
return var5;
}
private WorkResult executeWithPreviousOutputFiles(@Nullable InputChangesInternal inputChanges) {
this.task.getState().setExecuting(true);
WorkResult var2;
try {
ExecuteActionsTaskExecuter.LOGGER.debug("Executing actions for {}.".this.task);
// Callback the TaskActionListener's beforeActions interface.
ExecuteActionsTaskExecuter.this.actionListener.beforeActions(this.task);
// The traversal execution executes all actions
ExecuteActionsTaskExecuter.this.executeActions(this.task, inputChanges);
var2 = this.task.getState().getDidWork() ? WorkResult.DID_WORK : WorkResult.DID_NO_WORK;
} finally {
this.task.getState().setExecuting(false);
// Callback the TaskActionListener's beforeActions interface.
ExecuteActionsTaskExecuter.this.actionListener.afterActions(this.task);
}
return var2;
}
Copy the code
There are three main things that have been done here
- Calls back the TaskActionListener’s beforeActions interface.
- Traversal execution Executes all actions. Executing a Task is essentially executing an Action
- Calls back the TaskActionListener’s beforeActions interface.
Five Finish.
The only important thing to do in the Finished phase is to call back to the buildListener’s buildFinished interface
Here borrow [Android training manual] Gradle – Gradle source code analysis in a flowchart, to show the order of the whole process
conclusion
The Gradle build can be summarized in the following steps
- Parse seeting.gradle and execute it, generating a project instance
- Parse build.gradle and execute
- Generate a task dependency graph
- To perform a task
reference
Mainly refer to the following blog, thank you for your efforts
Gradle source code analysis
【【 soul 7 ask 】 Deep exploration Gradle automatic building technology (5, Gradle plug-in architecture implementation principle analysis — first)