继续上一篇 13. Gradle编译其他应用代码流程(二)。
这篇从InProcessBuildActionExecuter.execute开始这一篇的内容。
在正式内容前,首先要讲个gradle构建的流程,这个也是接下来内容的流程。
Load->Configure->Build
大家可以思考下,这3步都主要做了什么事。
另外,从执行流程的事件通知来看,它还分成下面5个通知事件:
1
2
3
4
5
|
buildStarted //开始编译
settingsEvaluated //settings处理完毕
projectsLoaded //项目loaded
projectsEvaluated //项目处理完毕
buildFinished //编译结束
|
一. InProcessBuildActionExecuter.execute
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
|
文件路径:
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
方法:
@Override
public
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,所以这里又是喜闻乐见的装饰者模式。
1
2
3
4
5
6
7
8
9
|
public
class
ChainingBuildActionRunner
implements
BuildActionRunner {
private
final
List<?
extends
BuildActionRunner> runners;
public
ChainingBuildActionRunner(List<?
extends
BuildActionRunner> runners) {
this
.runners = runners;
}
}
public
class
ExecuteBuildActionRunner
implements
BuildActionRunner {}
|
最后来到ExecuteBuildActionRunner.run方法,它会调用GradleBuildController.run(),顾名思义,它是GradleBuild的控制器,所以马上就要接触到Gradle build步骤了;接下来会调用DefaultGradleLauncher.run()方法。
二. DefaultGradleLauncher
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
@Override
public
BuildResult run() {
return
doBuild(Stage.Build);
}
private
BuildResult doBuild(
final
Stage upTo) {
return
buildOperationExecutor.run(
"Run build"
,
new
Factory<BuildResult>() {
@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
方法
1
2
3
4
5
6
7
8
9
10
|
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
方法:
1
2
3
4
5
|
return
new
DefaultGradleLauncher(
...
gradle.getBuildListenerBroadcaster(),
...
);
|
//文件路径:
subprojects\core\src\main\java\org\gradle\invocation\DefaultGradle.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
|
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的主要流程都在这里面。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
|
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 初始化脚本
1
2
3
4
5
6
7
8
9
|
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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
/**
* 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<File> 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
1
2
3
4
5
6
7
8
9
10
|
public
List<File> getAllInitScripts() {
CompositeInitScriptFinder initScriptFinder =
new
CompositeInitScriptFinder(
new
UserHomeInitScriptFinder(getGradleUserHomeDir()),
new
DistributionInitScriptFinder(gradleHomeDir)
);
List<File> scripts =
new
ArrayList<File>(getInitScripts());
initScriptFinder.findScripts(scripts);
return
Collections.unmodifiableList(scripts);
}
|
subprojects\core\src\main\java\org\gradle\initialization\UserHomeInitScriptFinder.java
1
2
3
4
5
6
7
|
public
void
findScripts(Collection<File> 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
1
2
3
4
5
6
|
public
void
findScripts(Collection<File> 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分别是:
1
2
|
gradleUserHomeDir=D:\gradle_jar_cache
gradleHome=E:\work_space\gradle-source-from-csdn\gradle-3.1\build\distributions\gradle-3.1-snapshot-1
|
其实如果大家去看下gradle home目录的init.d目录,你会发现里面有个readme.txt文件,里面有这样的描述:
1
|
You can add .gradle init scripts to this directory. Each one is executed at the start of the build.
|
那我们的Gradle 源代码流程分析也验证了这句话。
3. 然后来看看processor.process在干什么
1
2
3
|
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
1
2
3
4
5
6
7
8
9
10
11
12
|
/**
* 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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
|
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<?
extends
BasicScript> scriptType = initialPassScriptTarget.getScriptClass();
InitialPassStatementTransformer initialPassStatementTransformer =
new
InitialPassStatementTransformer(scriptSource, initialPassScriptTarget, documentationRegistry);
SubsetScriptTransformer initialTransformer =
new
SubsetScriptTransformer(initialPassStatementTransformer);
String id = INTERNER.intern(
"cp_"
+ initialPassScriptTarget.getId());
CompileOperation<PluginRequests> initialOperation =
new
FactoryBackedCompileOperation<PluginRequests>(id, initialTransformer, initialPassStatementTransformer, pluginRequestsSerializer);
ScriptRunner<?
extends
BasicScript, PluginRequests> 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<BuildScriptData> operation =
new
FactoryBackedCompileOperation<BuildScriptData>(operationId, buildScriptTransformer, buildScriptTransformer, buildScriptDataSerializer);
final
ScriptRunner<?
extends
BasicScript, BuildScriptData> 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. 如果有这些文件,而且内容不为空,那么将会加载它们配置的属性。
比较重要也很令人费解是这行代码:
1
|
scriptCompilerFactory.createCompiler(scriptSource);
|
这行代码粗看没有什么,但是仔细分析后其实大有乾坤!它是在为下一行
1
|
initialRunner.run(target, services);
|
生成可以加载的Java类,最终调用DefaultScriptCompilationHandler.compileToDir来生成类。 生成的类路径如下:
D:\gradle_jar_cache\caches\3.1-snapshot-1\scripts\df5frxe005h8vnbjcuzkr2g0s\cp_settings\cp_settingsd7eae713beda1bd9e69f8461da734880
执行堆栈如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
|
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$ProgressReportingInitializer.execute(FileCacheBackedScriptClassCompiler.java:185)
at org.gradle.groovy.scripts.internal.FileCacheBackedScriptClassCompiler$ProgressReportingInitializer.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$ProgressReportingInitializer.execute(FileCacheBackedScriptClassCompiler.java:185)
at org.gradle.groovy.scripts.internal.FileCacheBackedScriptClassCompiler$ProgressReportingInitializer.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.
1
2
|
// Build `buildSrc`, load settings.gradle, and construct composite (if appropriate)
settings = settingsLoader.findAndLoadSettings(gradle);
|
四. Load.findAndLoadSettings
settings = settingsLoader.findAndLoadSettings(gradle);
首先settingsLoader使用了装饰者模式,从外到内包装顺序是:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
|
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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
|
@Override
public
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<String, String> properties = propertiesLoader.mergeProperties(Collections.<String, String>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
1
2
3
4
5
6
7
8
9
10
11
|
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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
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<String, String> systemProperties, Map<String, String> 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<String, String> properties) {
addSystemPropertiesFromGradleProperties(defaultProperties);
addSystemPropertiesFromGradleProperties(overrideProperties);
System.getProperties().putAll(properties);
}
private
void
addSystemPropertiesFromGradleProperties(Map<String, String> 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中。
比如,像这种属性:
1
2
3
4
5
6
|
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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
public
class
ScriptEvaluatingSettingsProcessor
implements
SettingsProcessor {
...
public
SettingsInternal process(GradleInternal gradle,
SettingsLocation settingsLocation,
ClassLoaderScope baseClassLoaderScope,
StartParameter startParameter) {
...
Map<String, String> properties = propertiesLoader.mergeProperties(Collections.<String, String>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<String, String> mergeProperties(Map<String, String> properties) {
Map<String, String> result =
new
HashMap<String, String>();
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.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
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又是使用了一个装饰者模式!从外到内包装如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
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
日志如下:
1
2
3
4
|
createProject buildFile: E:\work_space\Android-Prototype\build.gradle parent: null
createProject 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通知。
1
|
gradle.getBuildListenerBroadcaster().projectsLoaded(gradle);
|
至此,Load步骤结束!
1
2
3
4
5
6
7
8
9
|
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过程。
本文转自rongwei84n 51CTO博客,原文链接:http://blog.51cto.com/483181/1928513,如需转载请自行联系原作者