继续上一篇   。 

这篇从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方法:public Object execute(BuildAction action, BuildRequestContext buildRequestContext, BuildActionParameters actionParameters, ServiceRegistry contextServices) {    GradleLauncher gradleLauncher = gradleLauncherFactory.newInstance(action.getStartParameter(), buildRequestContext, contextServices);    try {        gradleLauncher.addStandardOutputListener(buildRequestContext.getOutputListener());        gradleLauncher.addStandardErrorListener(buildRequestContext.getErrorListener());        GradleBuildController buildController = new GradleBuildController(gradleLauncher);        buildActionRunner.run(action, buildController);                    System.out.println("Sandy buildController.getResult(): " + buildController.getResult());        return buildController.getResult();    } finally {        gradleLauncher.stop();    }}文件路径:subprojects\launcher\src\main\java\org\gradle\launcher\exec\InProcessBuildActionExecuter.java方法:public GradleInternal run() {    try {      	System.out.println("Sandy GradleInternal run state: " + state);        return (GradleInternal) getLauncher().run().getGradle();    } finally {        state = State.Completed;    }}文件路径:subprojects\launcher\src\main\java\org\gradle\launcher\exec\ChainingBuildActionRunner.java方法:@Overridepublic void run(BuildAction action, BuildController buildController) {  	System.out.println("Sandy ChainingBuildActionRunner run runners.size: " + runners.size());    for (BuildActionRunner runner : runners) {       	System.out.println("runner: " + runner);        runner.run(action, buildController);		if (buildController.hasResult()) {			return;        }    }    throw new UnsupportedOperationException(String.format("Don't know how to run a build action of type %s.", action.getClass().getSimpleName()));}文件路径:subprojects\launcher\src\main\java\org\gradle\tooling\internal\provider\ExecuteBuildActionRunner.java方法:public void run(BuildAction action, BuildController buildController) {   	System.out.println("ExecuteBuildActionRunner action: " + action  			+ " buildController: " + buildController);    if (action instanceof ExecuteBuildAction) {      	System.out.println("ExecuteBuildActionRunner run..");        buildController.run();        buildController.setResult(null);        System.out.println("ExecuteBuildActionRunner result: " + "null");    }}文件路径:subprojects\launcher\src\main\java\org\gradle\launcher\exec\GradleBuildController.java方法:public GradleInternal run() {    try {        System.out.println("Sandy GradleInternal run state: " + state);        return (GradleInternal) getLauncher().run().getGradle();    } finally {        state = State.Completed;    }}

上面的步骤比较清晰明了,需要注意的是ChainingBuildActionRunner和ExecuteBuildActionRunner,其实他们都是同一个接口BuildActionRunner,所以这里又是喜闻乐见的装饰者模式。

public class ChainingBuildActionRunner implements BuildActionRunner {	private final List
 runners;    public ChainingBuildActionRunner(List
 runners) {        this.runners = runners;          }}public class ExecuteBuildActionRunner implements BuildActionRunner {}

最后来到ExecuteBuildActionRunner.run方法,它会调用GradleBuildController.run(),顾名思义,它是GradleBuild的控制器,所以马上就要接触到Gradle build步骤了;接下来会调用DefaultGradleLauncher.run()方法。

二. DefaultGradleLauncher 

@Overridepublic BuildResult run() {   return doBuild(Stage.Build);}private BuildResult doBuild(final Stage upTo) {    return buildOperationExecutor.run("Run build", new Factory
() {        @Override        public BuildResult create() {            Throwable failure = null;            try {                                System.out.println("buildListener: " + buildListener.getClass() + " gradle: " + gradle.getClass());                buildListener.buildStarted(gradle);                doBuildStages(upTo);            } catch (Throwable t) {                failure = exceptionAnalyser.transform(t);            }            BuildResult buildResult = new BuildResult(upTo.name(), gradle, failure);            buildListener.buildFinished(buildResult);            if (failure != null) {                throw new ReportedException(failure);            }            return buildResult;        }    });}

首先来看buildListener.buildStarted(gradle); 这行代码的作用是通知gradle构建已经开始,那既然是通知,接收者是谁呢?

看buildListener赋值的地方:

文件路径:

subprojects\core\src\main\java\org\gradle\initialization\DefaultGradleLauncher.java

方法

public DefaultGradleLauncher(GradleInternal gradle, InitScriptHandler initScriptHandler, SettingsLoader settingsLoader,                                 BuildConfigurer buildConfigurer, ExceptionAnalyser exceptionAnalyser,                                 LoggingManagerInternal loggingManager, BuildListener buildListener,                                 ModelConfigurationListener modelConfigurationListener,                                 BuildCompletionListener buildCompletionListener, BuildOperationExecutor operationExecutor,                                 BuildConfigurationActionExecuter buildConfigurationActionExecuter, BuildExecuter buildExecuter, BuildScopeServices buildServices) {     ...    this.buildListener = buildListener;     ...}

继续看调动的地方

文件路径:

subprojects\core\src\main\java\org\gradle\initialization\DefaultGradleLauncherFactory.java

方法:

return new DefaultGradleLauncher(            ...            gradle.getBuildListenerBroadcaster(),            ...        );

//文件路径:

subprojects\core\src\main\java\org\gradle\invocation\DefaultGradle.java

    public BuildListener getBuildListenerBroadcaster() {        return buildListenerBroadcast.getSource();}            public DefaultGradle(Gradle parent, StartParameter startParameter, ServiceRegistryFactory parentRegistry) {        ...        buildListenerBroadcast = getListenerManager().createAnonymousBroadcaster(BuildListener.class);        projectEvaluationListenerBroadcast = getListenerManager().createAnonymousBroadcaster(ProjectEvaluationListener.class);        buildListenerBroadcast.add(new BuildAdapter() {        	            @Override			public void buildStarted(Gradle gradle) {				super.buildStarted(gradle);				Exception ex = new Exception("Sandy buildStarted");				ex.printStackTrace();				System.out.println("buildListenerBroadcast sandy buildStarted");			}			@Override			public void settingsEvaluated(Settings settings) {				super.settingsEvaluated(settings);				Exception ex = new Exception("Sandy settingsEvaluated");				ex.printStackTrace();				System.out.println("buildListenerBroadcast sandy settingsEvaluated");			}			@Override			public void projectsEvaluated(Gradle gradle) {				super.projectsEvaluated(gradle);				System.out.println("buildListenerBroadcast sandy projectsEvaluated");			}			@Override			public void buildFinished(BuildResult result) {				super.buildFinished(result);				System.out.println("buildListenerBroadcast sandy buildFinished");			}			@Override            public void projectsLoaded(Gradle gradle) {            	System.out.println("buildListenerBroadcast sandy projectsLoaded");                rootProjectActions.execute(rootProject);                rootProjectActions = null;            }        });    }

嗯,也就是接受者是在DefaultGradle里面,也就是说通知gradle build已经开始,接下来看doBuildStages(Stage.Build)方法,这个方法很重要,gradle build的主要流程都在这里面。

private void doBuildStages(Stage upTo) {        if (stage == Stage.Build) {            throw new IllegalStateException("Cannot build with GradleLauncher multiple times");        }        if (stage == null) {            // Evaluate init scripts            initScriptHandler.executeScripts(gradle);            // Build `buildSrc`, load settings.gradle, and construct composite (if appropriate)            settings = settingsLoader.findAndLoadSettings(gradle);            stage = Stage.Load;        }        if (upTo == Stage.Load) {            return;        }        if (stage == Stage.Load) {            // Configure build            buildOperationExecutor.run("Configure build", new Runnable() {                @Override                public void run() {                    buildConfigurer.configure(gradle);                    if (!gradle.getStartParameter().isConfigureOnDemand()) {                        buildListener.projectsEvaluated(gradle);                    }                    modelConfigurationListener.onConfigure(gradle);                }            });            stage = Stage.Configure;        }        if (upTo == Stage.Configure) {            return;        }        // After this point, the GradleLauncher cannot be reused        stage = Stage.Build;        // Populate task graph        buildOperationExecutor.run("Calculate task graph", new Runnable() {            @Override            public void run() {                buildConfigurationActionExecuter.select(gradle);                if (gradle.getStartParameter().isConfigureOnDemand()) {                    buildListener.projectsEvaluated(gradle);                }            }        });        // Execute build        buildOperationExecutor.run("Run tasks", new Runnable() {            @Override            public void run() {                buildExecuter.execute(gradle);            }        });    }

还记得最开始说过的gradle构建分成3个步骤吗?Load-> Configure->Build

那这个方法doBuildStages可以很清楚的看到这个流程,大家看下上面的代码即可明白,那接下来我们一步步分析这个过程。

三. Load.executeScripts 初始化脚本

if (stage == null) {     // Evaluate init scripts     initScriptHandler.executeScripts(gradle);     // Build `buildSrc`, load settings.gradle, and construct composite (if appropriate)     settings = settingsLoader.findAndLoadSettings(gradle);     stage = Stage.Load;}

1. 首先来看第一行

initScriptHandler.executeScripts(gradle);

// Evaluate init scripts  看解释是统计初始化脚本,那具体是干什么呢?

文件路径:

subprojects\core\src\main\java\org\gradle\initialization\InitScriptHandler.java

/** * Finds and executes all init scripts for a given build. */public class InitScriptHandler {    ...        public void executeScripts(final GradleInternal gradle) {    	System.out.println("executeScripts");        final List
 initScripts = gradle.getStartParameter().getAllInitScripts();        if (initScripts.isEmpty()) {            return;        }        BuildOperationDetails operationDetails = BuildOperationDetails.displayName("Run init scripts").progressDisplayName("init scripts").build();        buildOperationExecutor.run(operationDetails, new Runnable() {            @Override            public void run() {                for (File script : initScripts) {                 System.out.println("InitScriptHandler run processor" + processor);                    processor.process(new UriScriptSource("initialization script", script), gradle);                }            }        });    }}

从类InitScriptHandler的注释就知道,这个类的作用是找到并且执行初始化脚本,那我们接下来看看:

a. 它说的初始化脚本指的是什么?

b. 怎么执行初始化脚本的?

2. 首先来看getAllInitScripts是在干什么:

subprojects\core\src\main\java\org\gradle\StartParameter.java

public List
 getAllInitScripts() {        CompositeInitScriptFinder initScriptFinder = new CompositeInitScriptFinder(            new UserHomeInitScriptFinder(getGradleUserHomeDir()), new DistributionInitScriptFinder(gradleHomeDir)        );                List
 scripts = new ArrayList
(getInitScripts());        initScriptFinder.findScripts(scripts);        return Collections.unmodifiableList(scripts);    }

subprojects\core\src\main\java\org\gradle\initialization\UserHomeInitScriptFinder.java

public void findScripts(Collection
 scripts) {        File userInitScript = new File(userHomeDir, "init.gradle");        if (userInitScript.isFile()) {            scripts.add(userInitScript);        }        findScriptsInDir(new File(userHomeDir, "init.d"), scripts);    }

subprojects\core\src\main\java\org\gradle\initialization\DistributionInitScriptFinder.java

public void findScripts(Collection
 scripts) {        if (gradleHome == null) {            return;        }        findScriptsInDir(new File(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文件,里面有这样的描述:

You can add .gradle init scripts to this directory. Each one is executed at the start of the build.

那我们的Gradle 源代码流程分析也验证了这句话。

3. 然后来看看processor.process在干什么

for (File script : initScripts) {     processor.process(new UriScriptSource("initialization script", script), gradle);}

首先initScripts是指上面我们统计3个目录下得到的脚本文件集合,那这里就是挨个执行它们。

那UriScriptSource是用来解析传入的script文件,把它的内容读出来。

那继续看process方法

文件路径:

subprojects\core\src\main\java\org\gradle\configuration\DefaultInitScriptProcessor.java

/** * Processes (and runs) an init script for a specified build.  Handles defining * the classpath based on the initscript {} configuration closure. */public class DefaultInitScriptProcessor implements InitScriptProcessor {    ...    public void process(final ScriptSource initScript, GradleInternal gradle) {        ....        configurer.apply(gradle);    }}

文件路径:

subprojects\core\src\main\java\org\gradle\configuration\DefaultScriptPluginFactory.java

public void apply(final Object target) {        	System.out.println("ScriptPluginImpl apply 1");            ...                        // Pass 1, extract plugin requests and plugin repositories and execute buildscript {}, ignoring (i.e. not even compiling) anything else            Class
 scriptType = initialPassScriptTarget.getScriptClass();            InitialPassStatementTransformer initialPassStatementTransformer = new InitialPassStatementTransformer(scriptSource, initialPassScriptTarget, documentationRegistry);            SubsetScriptTransformer initialTransformer = new SubsetScriptTransformer(initialPassStatementTransformer);            String id = INTERNER.intern("cp_" + initialPassScriptTarget.getId());            CompileOperation
 initialOperation = new FactoryBackedCompileOperation
(id, initialTransformer, initialPassStatementTransformer, pluginRequestsSerializer);            ScriptRunner
 initialRunner = compiler.compile(scriptType, initialOperation, baseScope.getExportClassLoader(), Actions.doNothing());            initialRunner.run(target, services);            PluginRequests pluginRequests = initialRunner.getData();            PluginManagerInternal pluginManager = initialPassScriptTarget.getPluginManager();            System.out.println("ScriptPluginImpl apply is empty: " + pluginRequests.isEmpty());            pluginRequestApplicator.applyPlugins(pluginRequests, scriptHandler, pluginManager, targetScope);            System.out.println("ScriptPluginImpl apply 4");            // Pass 2, compile everything except buildscript {}, pluginRepositories{}, and plugin requests, then run            final ScriptTarget scriptTarget = secondPassTarget(target);            scriptType = scriptTarget.getScriptClass();            BuildScriptTransformer buildScriptTransformer = new BuildScriptTransformer(scriptSource, scriptTarget);            String operationId = scriptTarget.getId();            CompileOperation
 operation = new FactoryBackedCompileOperation
(operationId, buildScriptTransformer, buildScriptTransformer, buildScriptDataSerializer);            final ScriptRunner
 runner = compiler.compile(scriptType, operation, targetScope.getLocalClassLoader(), ClosureCreationInterceptingVerifier.INSTANCE);            if (scriptTarget.getSupportsMethodInheritance() && runner.getHasMethods()) {             System.out.println("ScriptPluginImpl apply 5");                scriptTarget.attachScript(runner.getScript());            }            System.out.println("ScriptPluginImpl apply 6");            if (!runner.getRunDoesSomething()) {             System.out.println("ScriptPluginImpl apply 7");                return;            }            Runnable buildScriptRunner = new Runnable() {                public void run() {                 System.out.println("ScriptPluginImpl apply 8");                    runner.run(target, services);                }            };            System.out.println("ScriptPluginImpl apply 9");            boolean hasImperativeStatements = 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: Sandy compile to dir	at org.gradle.groovy.scripts.internal.DefaultScriptCompilationHandler.compileToDir(DefaultScriptCompilationHandler.java:97)	at org.gradle.groovy.scripts.internal.FileCacheBackedScriptClassCompiler$CompileToCrossBuildCacheAction.execute(FileCacheBackedScriptClassCompiler.java:160)	at org.gradle.groovy.scripts.internal.FileCacheBackedScriptClassCompiler$CompileToCrossBuildCacheAction.execute(FileCacheBackedScriptClassCompiler.java:141)	at org.gradle.groovy.scripts.internal.FileCacheBackedScriptClassCompiler$Progre***eportingInitializer.execute(FileCacheBackedScriptClassCompiler.java:185)	at org.gradle.groovy.scripts.internal.FileCacheBackedScriptClassCompiler$Progre***eportingInitializer.execute(FileCacheBackedScriptClassCompiler.java:164)	at org.gradle.cache.internal.DefaultPersistentDirectoryCache$Initializer.initialize(DefaultPersistentDirectoryCache.java:100)	at org.gradle.cache.internal.DefaultCacheAccess$2.run(DefaultCacheAccess.java:116)	at org.gradle.cache.internal.DefaultFileLockManager$DefaultFileLock.doWriteAction(DefaultFileLockManager.java:179)	at org.gradle.cache.internal.DefaultFileLockManager$DefaultFileLock.writeFile(DefaultFileLockManager.java:169)	at org.gradle.cache.internal.DefaultCacheAccess.open(DefaultCacheAccess.java:113)	at org.gradle.cache.internal.DefaultPersistentDirectoryStore.open(DefaultPersistentDirectoryStore.java:47)	at org.gradle.cache.internal.DefaultPersistentDirectoryStore.open(DefaultPersistentDirectoryStore.java:28)	at org.gradle.cache.internal.DefaultCacheFactory.doOpen(DefaultCacheFactory.java:83)	at org.gradle.cache.internal.DefaultCacheFactory.open(DefaultCacheFactory.java:51)	at org.gradle.cache.internal.DefaultCacheRepository$PersistentCacheBuilder.doOpen(DefaultCacheRepository.java:147)	at org.gradle.cache.internal.DefaultCacheRepository$AbstractCacheBuilder.open(DefaultCacheRepository.java:121)	at org.gradle.groovy.scripts.internal.FileCacheBackedScriptClassCompiler$RemapBuildScriptsAction.execute(FileCacheBackedScriptClassCompiler.java:365)	at org.gradle.groovy.scripts.internal.FileCacheBackedScriptClassCompiler$RemapBuildScriptsAction.execute(FileCacheBackedScriptClassCompiler.java:333)	at org.gradle.groovy.scripts.internal.FileCacheBackedScriptClassCompiler$Progre***eportingInitializer.execute(FileCacheBackedScriptClassCompiler.java:185)	at org.gradle.groovy.scripts.internal.FileCacheBackedScriptClassCompiler$Progre***eportingInitializer.execute(FileCacheBackedScriptClassCompiler.java:164)	at org.gradle.cache.internal.DefaultPersistentDirectoryCache$Initializer.initialize(DefaultPersistentDirectoryCache.java:100)	at org.gradle.cache.internal.DefaultCacheAccess$2.run(DefaultCacheAccess.java:116)	at org.gradle.cache.internal.DefaultFileLockManager$DefaultFileLock.doWriteAction(DefaultFileLockManager.java:179)	at org.gradle.cache.internal.DefaultFileLockManager$DefaultFileLock.writeFile(DefaultFileLockManager.java:169)	at org.gradle.cache.internal.DefaultCacheAccess.open(DefaultCacheAccess.java:113)	at org.gradle.cache.internal.DefaultPersistentDirectoryStore.open(DefaultPersistentDirectoryStore.java:47)	at org.gradle.cache.internal.DefaultPersistentDirectoryStore.open(DefaultPersistentDirectoryStore.java:28)	at org.gradle.cache.internal.DefaultCacheFactory.doOpen(DefaultCacheFactory.java:83)	at org.gradle.cache.internal.DefaultCacheFactory.open(DefaultCacheFactory.java:51)	at org.gradle.cache.internal.DefaultCacheRepository$PersistentCacheBuilder.doOpen(DefaultCacheRepository.java:147)	at org.gradle.cache.internal.DefaultCacheRepository$AbstractCacheBuilder.open(DefaultCacheRepository.java:121)	at org.gradle.groovy.scripts.internal.FileCacheBackedScriptClassCompiler.compile(FileCacheBackedScriptClassCompiler.java:111)	at org.gradle.groovy.scripts.internal.CrossBuildInMemoryCachingScriptClassCache.getOrCompile(CrossBuildInMemoryCachingScriptClassCache.java:46)	at org.gradle.groovy.scripts.internal.BuildScopeInMemoryCachingScriptClassCompiler.compile(BuildScopeInMemoryCachingScriptClassCompiler.java:48)	at org.gradle.groovy.scripts.DefaultScriptCompilerFactory$ScriptCompilerImpl.compile(DefaultScriptCompilerFactory.java:50)	at org.gradle.configuration.DefaultScriptPluginFactory$ScriptPluginImpl.apply(DefaultScriptPluginFactory.java:154)	at org.gradle.configuration.project.BuildScriptProcessor.execute(BuildScriptProcessor.java:40)	at org.gradle.configuration.project.BuildScriptProcessor.execute(BuildScriptProcessor.java:25)	at org.gradle.configuration.project.ConfigureActionsProjectEvaluator.evaluate(ConfigureActionsProjectEvaluator.java:34)	at org.gradle.configuration.project.LifecycleProjectEvaluator.evaluate(LifecycleProjectEvaluator.java:55)	at org.gradle.api.internal.project.DefaultProject.evaluate(DefaultProject.java:573)	at org.gradle.api.internal.project.DefaultProject.evaluate(DefaultProject.java:125)	at org.gradle.execution.TaskPathProjectEvaluator.configureHierarchy(TaskPathProjectEvaluator.java:42)	at org.gradle.configuration.DefaultBuildConfigurer.configure(DefaultBuildConfigurer.java:38)	at org.gradle.initialization.DefaultGradleLauncher$2.run(DefaultGradleLauncher.java:154)	at org.gradle.internal.Factories$1.create(Factories.java:22)	at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:91)	at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:53)	at org.gradle.initialization.DefaultGradleLauncher.doBuildStages(DefaultGradleLauncher.java:151)	at org.gradle.initialization.DefaultGradleLauncher.access$200(DefaultGradleLauncher.java:33)	at org.gradle.initialization.DefaultGradleLauncher$1.create(DefaultGradleLauncher.java:114)	at org.gradle.initialization.DefaultGradleLauncher$1.create(DefaultGradleLauncher.java:106)	at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:91)	at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:63)	at org.gradle.initialization.DefaultGradleLauncher.doBuild(DefaultGradleLauncher.java:106)	at org.gradle.initialization.DefaultGradleLauncher.run(DefaultGradleLauncher.java:92)	at org.gradle.launcher.exec.GradleBuildController.run(GradleBuildController.java:67)	at org.gradle.tooling.internal.provider.ExecuteBuildActionRunner.run(ExecuteBuildActionRunner.java:31)	at org.gradle.launcher.exec.ChainingBuildActionRunner.run(ChainingBuildActionRunner.java:43)	at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:42)	at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:26)	at org.gradle.tooling.internal.provider.ContinuousBuildActionExecuter.execute(ContinuousBuildActionExecuter.java:79)	at org.gradle.tooling.internal.provider.ContinuousBuildActionExecuter.execute(ContinuousBuildActionExecuter.java:51)	at org.gradle.launcher.cli.RunBuildAction.run(RunBuildAction.java:54)	at org.gradle.internal.Actions$RunnableActionAdapter.execute(Actions.java:173)	at org.gradle.launcher.cli.CommandLineActionFactory$ParseAndBuildAction.execute(CommandLineActionFactory.java:250)	at org.gradle.launcher.cli.CommandLineActionFactory$ParseAndBuildAction.execute(CommandLineActionFactory.java:217)	at org.gradle.launcher.cli.JavaRuntimeValidationAction.execute(JavaRuntimeValidationAction.java:33)	at org.gradle.launcher.cli.JavaRuntimeValidationAction.execute(JavaRuntimeValidationAction.java:24)	at org.gradle.launcher.cli.ExceptionReportingAction.execute(ExceptionReportingAction.java:33)	at org.gradle.launcher.cli.ExceptionReportingAction.execute(ExceptionReportingAction.java:22)	at org.gradle.launcher.cli.CommandLineActionFactory$WithLogging.execute(CommandLineActionFactory.java:210)	at org.gradle.launcher.cli.CommandLineActionFactory$WithLogging.execute(CommandLineActionFactory.java:174)	at org.gradle.launcher.Main.doAction(Main.java:33)	at org.gradle.launcher.bootstrap.EntryPoint.run(EntryPoint.java:45)	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)	at java.lang.reflect.Method.invoke(Method.java:483)	at org.gradle.launcher.bootstrap.ProcessBootstrap.runNoExit(ProcessBootstrap.java:60)	at org.gradle.launcher.bootstrap.ProcessBootstrap.run(ProcessBootstrap.java:37)	at org.gradle.launcher.GradleMain.main(GradleMain.java:24)

接下来,继续往下面看Load步骤的第二个步骤findAndLoadSettings.

// Build `buildSrc`, load settings.gradle, and construct composite (if appropriate)settings = settingsLoader.findAndLoadSettings(gradle);

四. Load.findAndLoadSettings 

settings = settingsLoader.findAndLoadSettings(gradle);

首先settingsLoader使用了装饰者模式,从外到内包装顺序是:

public class NotifyingSettingsLoader implements SettingsLoader {    private final SettingsLoader settingsLoader;    ...    @Override    public SettingsInternal findAndLoadSettings(GradleInternal gradle) {        SettingsInternal settings = settingsLoader.findAndLoadSettings(gradle);                gradle.getBuildListenerBroadcaster().settingsEvaluated(settings);        buildLoader.load(settings.getRootProject(), settings.getDefaultProject(), gradle, settings.getRootClassLoaderScope());        gradle.getBuildListenerBroadcaster().projectsLoaded(gradle);        return settings;    }}public class CompositeBuildSettingsLoader implements SettingsLoader {    private final SettingsLoader delegate;    ...    @Override    public SettingsInternal findAndLoadSettings(GradleInternal gradle) {        SettingsInternal settings = delegate.findAndLoadSettings(gradle);        ...    }}/** * Handles locating and processing setting.gradle files.  Also deals with the buildSrc module, since that modules is * found after settings is located, but needs to be built before settings is processed. */public class DefaultSettingsLoader implements SettingsLoader {    ...    @Override    public SettingsInternal findAndLoadSettings(GradleInternal gradle) {        ...                SettingsInternal settings = findSettingsAndLoadIfAppropriate(gradle, startParameter);                ...        ProjectSpec spec = ProjectSpecs.forStartParameter(startParameter, settings);        System.out.println(" spec: " + spec);                if (spec.containsProject(settings.getProjectRegistry())) {        	System.out.println("spec.containsProject");            setDefaultProject(spec, settings);            return settings;        }        // Try again with empty settings        StartParameter noSearchParameter = startParameter.newInstance();        noSearchParameter.useEmptySettings();        settings = findSettingsAndLoadIfAppropriate(gradle, noSearchParameter);        // Set explicit build file, if required        if (noSearchParameter.getBuildFile() != null) {            ProjectDescriptor rootProject = settings.getRootProject();            rootProject.setBuildFileName(noSearchParameter.getBuildFile().getName());        }        setDefaultProject(spec, settings);        return settings;}

NotifyingSettingsLoader首先会根据装饰者模式逐个的调用进去,所以DefaultSettingsLoader.findAndLoadSettings方法,然后在回头看NotifyingSettingsLoader.findAndLoadSettings的其他代码。

DefaultSettingsLoader根据注释,它是要处理项目目录下的setting.gradle文件,同时处理buildSrc模块,这个好像一般项目没有。

所以,可以先看DefaultSettingsLoader.findAndLoadSettings方法。

1. DefaultSettingsLoader

文件路径:

subprojects\core\src\main\java\org\gradle\initialization\DefaultSettingsLoader.java

@Overridepublic SettingsInternal findAndLoadSettings(GradleInternal gradle) {    StartParameter startParameter = gradle.getStartParameter();            System.out.println("DefaultSettingsLoader.findAndLoadSettings startParameter: " + startParameter        		+ " gradle: " + gradle);            SettingsInternal settings = findSettingsAndLoadIfAppropriate(gradle, startParameter);    System.out.println(" settings: " + settings);    ProjectSpec spec = ProjectSpecs.forStartParameter(startParameter, settings);    System.out.println(" spec: " + spec);            if (spec.containsProject(settings.getProjectRegistry())) {     	System.out.println("spec.containsProject");         setDefaultProject(spec, settings);         return settings;    }    // Try again with empty settings    StartParameter noSearchParameter = startParameter.newInstance();    noSearchParameter.useEmptySettings();    settings = findSettingsAndLoadIfAppropriate(gradle, noSearchParameter);    // Set explicit build file, if required    if (noSearchParameter.getBuildFile() != null) {       ProjectDescriptor rootProject = settings.getRootProject();       rootProject.setBuildFileName(noSearchParameter.getBuildFile().getName());    }    setDefaultProject(spec, settings);    return settings;}    private SettingsInternal findSettingsAndLoadIfAppropriate(GradleInternal gradle,    ...    return settingsProcessor.process(gradle, settingsLocation, buildSourceClassLoader, startParameter);}  2. 首先看findSettingsAndLoadIfAppropriate 这个方法。看名字应该是寻找Settings并尝试加载它。它调用的是settingsProcessor.process 这个settingsProcessor又使用了装饰者模式,共有3个类。public class NotifyingSettingsProcessor implements SettingsProcessor {}public class PropertiesLoadingSettingsProcessor implements SettingsProcessor {    public SettingsInternal process(GradleInternal gradle,                                    SettingsLocation settingsLocation,                                    ClassLoaderScope baseClassLoaderScope,                                    StartParameter startParameter) {    	System.out.println("PropertiesLoadingSettingsProcessor run");        propertiesLoader.loadProperties(settingsLocation.getSettingsDir());        return processor.process(gradle, settingsLocation, baseClassLoaderScope, startParameter);    }}public class ScriptEvaluatingSettingsProcessor implements SettingsProcessor {    public SettingsInternal process(GradleInternal gradle,                                    SettingsLocation settingsLocation,                                    ClassLoaderScope baseClassLoaderScope,                                    StartParameter startParameter) {    	System.out.println("Script Process process");        Clock settingsProcessingClock = new Clock();        Map
 properties = propertiesLoader.mergeProperties(Collections.
emptyMap());        SettingsInternal settings = settingsFactory.createSettings(gradle, settingsLocation.getSettingsDir(),                settingsLocation.getSettingsScriptSource(), properties, startParameter, baseClassLoaderScope);        applySettingsScript(settingsLocation, settings);        LOGGER.debug("Timing: Processing settings took: {}", settingsProcessingClock.getTime());        return settings;    }}

真的,gradle源代码使用了很多装饰者模式。

3. 首先看看PropertiesLoadingSettingsProcessor.process方法

文件路径:subprojects\core\src\main\java\org\gradle\initialization\PropertiesLoadingSettingsProcessor.java

public class PropertiesLoadingSettingsProcessor implements SettingsProcessor {    ...    public SettingsInternal process(GradleInternal gradle,                                    SettingsLocation settingsLocation,                                    ClassLoaderScope baseClassLoaderScope,                                    StartParameter startParameter) {    	System.out.println("PropertiesLoadingSettingsProcessor run");        propertiesLoader.loadProperties(settingsLocation.getSettingsDir());        return processor.process(gradle, settingsLocation, baseClassLoaderScope, startParameter);    }}

文件路径:

subprojects\core\src\main\java\org\gradle\initialization\DefaultGradlePropertiesLoader.java

public static final String SYSTEM_PROP_PREFIX = "systemProp";String ENV_PROJECT_PROPERTIES_PREFIX = "ORG_GRADLE_PROJECT_";String SYSTEM_PROJECT_PROPERTIES_PREFIX = "org.gradle.project.";public void loadProperties(File settingsDir) {        loadProperties(settingsDir, startParameter, getAllSystemProperties(), getAllEnvProperties());    }    void loadProperties(File settingsDir, StartParameter startParameter, Map
 systemProperties, Map
 envProperties) {        defaultProperties.clear();        overrideProperties.clear();        addGradleProperties(defaultProperties, new File(settingsDir, Project.GRADLE_PROPERTIES));        addGradleProperties(overrideProperties, new File(startParameter.getGradleUserHomeDir(), Project.GRADLE_PROPERTIES));        setSystemProperties(startParameter.getSystemPropertiesArgs());        overrideProperties.putAll(getEnvProjectProperties(envProperties));        overrideProperties.putAll(getSystemProjectProperties(systemProperties));                for (String key : systemProperties.keySet()) {            System.out.println("system properties, key: " + key + " value: " + systemProperties.get(key)); }        for (String key : envProperties.keySet()) {     System.out.println("env properties, key: " + key + " value: " + envProperties.get(key)); }        overrideProperties.putAll(startParameter.getProjectProperties());}    private void setSystemProperties(Map
 properties) {    addSystemPropertiesFromGradleProperties(defaultProperties);    addSystemPropertiesFromGradleProperties(overrideProperties);    System.getProperties().putAll(properties);}private void addSystemPropertiesFromGradleProperties(Map
 properties) {    for (String key : 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# When configured, Gradle will run in incubating parallel mode.# This option should only be used with decoupled projects. More details, 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

public class ScriptEvaluatingSettingsProcessor implements SettingsProcessor {    ...    public SettingsInternal process(GradleInternal gradle,                                    SettingsLocation settingsLocation,                                    ClassLoaderScope baseClassLoaderScope,                                    StartParameter startParameter) {    	...        Map
 properties = propertiesLoader.mergeProperties(Collections.
emptyMap());        SettingsInternal settings = settingsFactory.createSettings(gradle, settingsLocation.getSettingsDir(),                settingsLocation.getSettingsScriptSource(), properties, startParameter, baseClassLoaderScope);        applySettingsScript(settingsLocation, settings);        ...    }      ...               //文件路径:subprojects\core\src\main\java\org\gradle\initialization\DefaultGradlePropertiesLoader.java     public Map
 mergeProperties(Map
 properties) {        Map
 result = new HashMap
();        result.putAll(defaultProperties);        result.putAll(properties);        result.putAll(overrideProperties);        return result;     }                  private void applySettingsScript(SettingsLocation settingsLocation, final SettingsInternal settings) {        ScriptSource settingsScriptSource = settingsLocation.getSettingsScriptSource();        ClassLoaderScope settingsClassLoaderScope = settings.getClassLoaderScope();        ScriptHandler scriptHandler = scriptHandlerFactory.create(settingsScriptSource, settingsClassLoaderScope);        ScriptPlugin configurer = configurerFactory.create(settingsScriptSource, scriptHandler, settingsClassLoaderScope, settings.getRootClassLoaderScope(), true);                System.out.println("applySettingsScript configurer: " + configurer);        configurer.apply(settings);    }}

首先呢,把上一步加载好的属性都merge在一起,放到properties里面。

然后调用configurer.apply(settings)设置项目目录下settings.gradle文件属性

那DefaultSettingsLoader.findAndLoadSettings就基本结束了,回过头去看看NotifyingSettingsLoader.findAndLoadSettings的剩余部分代码。

5. 继续看NotifyingSettingsLoader.

public class NotifyingSettingsLoader implements SettingsLoader {    ...    @Override    public SettingsInternal findAndLoadSettings(GradleInternal gradle) {        SettingsInternal settings = settingsLoader.findAndLoadSettings(gradle);        ...                gradle.getBuildListenerBroadcaster().settingsEvaluated(settings);        buildLoader.load(settings.getRootProject(), settings.getDefaultProject(), gradle, settings.getRootClassLoaderScope());        gradle.getBuildListenerBroadcaster().projectsLoaded(gradle);        return settings;    }}

首先发送一个事件通知settingsEvaulated,就是settings配置文件处理完毕。

然后调用buildLoader.load(xxx)

buildLoader又是使用了一个装饰者模式!从外到内包装如下:

public class ProjectPropertySettingBuildLoader implements BuildLoader {    ...    public void load(ProjectDescriptor rootProjectDescriptor, ProjectDescriptor defaultProject, GradleInternal gradle, ClassLoaderScope classLoaderScope) {        buildLoader.load(rootProjectDescriptor, defaultProject, gradle, classLoaderScope);        setProjectProperties(gradle.getRootProject(), new CachingPropertyApplicator());    }}public class InstantiatingBuildLoader implements BuildLoader {    private final IProjectFactory projectFactory;    public InstantiatingBuildLoader(IProjectFactory projectFactory) {        this.projectFactory = projectFactory;    }    /**     * Creates the {@link org.gradle.api.internal.GradleInternal} and {@link ProjectInternal} instances for the given root project, ready for the projects to be configured.     */    public void load(ProjectDescriptor rootProjectDescriptor, ProjectDescriptor defaultProject, GradleInternal gradle, ClassLoaderScope baseClassLoaderScope) {        createProjects(rootProjectDescriptor, gradle, baseClassLoaderScope);        attachDefaultProject(defaultProject, gradle);    }    private void attachDefaultProject(ProjectDescriptor defaultProject, GradleInternal gradle) {        gradle.setDefaultProject(gradle.getRootProject().getProjectRegistry().getProject(defaultProject.getPath()));    }    private void createProjects(ProjectDescriptor rootProjectDescriptor, GradleInternal gradle, ClassLoaderScope baseClassLoaderScope) {        ProjectInternal rootProject = projectFactory.createProject(rootProjectDescriptor, null, gradle, baseClassLoaderScope.createChild("root-project"), baseClassLoaderScope);                System.out.println("create project, rootProject: " + rootProject);        gradle.setRootProject(rootProject);        addProjects(rootProject, rootProjectDescriptor, gradle, baseClassLoaderScope);    }   }

那上面这段代码的作用就是配置gradle project层级关系,比如上层是项目根目录,也就是rootProject。

然后试各个模块,包括主模块app

日志如下:

createProject buildFile: E:\work_space\Android-Prototype\build.gradle parent: nullcreateProject buildFile: E:\work_space\Android-Prototype\app\build.gradle parent: root project 'Android-Prototype'createProject buildFile: E:\work_space\Android-Prototype\pushsdk\build.gradle parent: root project 'Android-Prototype'createProject buildFile: E:\work_space\Android-Prototype\moduletest\build.gradle parent: root project 'Android-Prototype'

然后发送project loaded通知。

gradle.getBuildListenerBroadcaster().projectsLoaded(gradle);

至此,Load步骤结束!

if (stage == null) {  // Evaluate init scripts  initScriptHandler.executeScripts(gradle);  // Build `buildSrc`, load settings.gradle, and construct composite (if appropriate)   settings = settingsLoader.findAndLoadSettings(gradle);  stage = Stage.Load;}

下一篇文章来继续Configure过程。