grade-1 启动流程(v6.9.1)
引子
做为Android开发,不仅需要对Apk构建流程熟悉外,还要知道gradle内部实现,通常说的gradle的生命周期你知道分为哪几个阶段吗?在不同生命周期你知道gradle到底做了什么吗?
本篇开始研究下gradle源码内部基本实现吧,你能从中找到答案,此处以6.9.1版本为分析
先看入口吧,gradlew.bat文件,里面核心代码
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
前三个为空,最终调用的是GradleWrapperMain.main方法
准备
准备gradle源码
git clone https://github.com/gradle/gradle
gcb feature_v6.9.1 v6.9.1
修改com.gradle.enterprise:test-distribution-gradle-plugin:1.1.2-rc-1调整为com.gradle.enterprise:test-distribution-gradle-plugin:1.1.2同步即可
wrapper模块

入口如下
// org.gradle.wrapper.GradleWrapperMain.java
public static void main(String[] args) throws Exception {
// gradle-wrapper.jar
File wrapperJar = wrapperJar();
// load gradle-wrapper.properties file
File propertiesFile = wrapperProperties(wrapperJar);
File rootDir = rootDir(wrapperJar);
CommandLineParser parser = new CommandLineParser();
parser.allowUnknownOptions();
parser.option(GRADLE_USER_HOME_OPTION, GRADLE_USER_HOME_DETAILED_OPTION).hasArgument();
parser.option(GRADLE_QUIET_OPTION, GRADLE_QUIET_DETAILED_OPTION);
SystemPropertiesCommandLineConverter converter = new SystemPropertiesCommandLineConverter();
converter.configure(parser);
ParsedCommandLine options = parser.parse(args);
Properties systemProperties = System.getProperties();
systemProperties.putAll(converter.convert(options, new HashMap<String, String>()));
// gradle home 目录:~/.gradle
File gradleUserHome = gradleUserHome(options);
addSystemProperties(gradleUserHome, rootDir);
Logger logger = logger(options);
// 构建一个wrapper执行器,调用execute;
// 1. 执行安装(如果本地没有安装
WrapperExecutor wrapperExecutor = WrapperExecutor.forWrapperPropertiesFile(propertiesFile);
wrapperExecutor.execute(
args,
new Install(logger, new Download(logger, "gradlew", UNKNOWN_VERSION), new PathAssembler(gradleUserHome)),
new BootstrapMainStarter());
}
// org.gradle.wrapper.WrapperExecutor.java
public void execute(String[] args, Install install, BootstrapMainStarter bootstrapMainStarter) throws Exception {
//
File gradleHome = install.createDist(config);
bootstrapMainStarter.start(args, gradleHome);
}
此处会调用wrapperExecutor.execute方法;主要做了2件事件
- createDist -> 如果没有gradle,下载grade文件(Grade-wrapper.properties文件中distributionUrl对应的文件)并解压;否则直接返回gradlehome文件
- start -> 调用org.gradle.launcher.GradleMain.main方法(反射)
1. 下载,解压gradle
先看下Grade-wrapper.properties文件格式如下
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.9-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
里面包含了需要下载gradle包的链接地址,WrapperConfiguration配置里面就包含了这些元信息
public File createDist(final WrapperConfiguration configuration) throws Exception {
final URI distributionUrl = configuration.getDistribution();
final String distributionSha256Sum = configuration.getDistributionSha256Sum();
final PathAssembler.LocalDistribution localDistribution = pathAssembler.getDistribution(configuration);
final File distDir = localDistribution.getDistributionDir();
final File localZipFile = localDistribution.getZipFile();
return exclusiveFileAccessManager.access(localZipFile, new Callable<File>() {
public File call() throws Exception {
final File markerFile = new File(localZipFile.getParentFile(), localZipFile.getName() + ".ok");
// 如果本地目录存在&存在.ok文件;
if (distDir.isDirectory() && markerFile.isFile()) {
InstallCheck installCheck = verifyDistributionRoot(distDir, distDir.getAbsolutePath());
if (installCheck.isVerified()) {
// 验证通过,直接返回gradlehome
return installCheck.gradleHome;
}
// Distribution is invalid. Try to reinstall.
System.err.println(installCheck.failureMessage);
markerFile.delete();
}
boolean needsDownload = !localZipFile.isFile();
URI safeDistributionUrl = Download.safeUri(distributionUrl);
if (needsDownload) {
File tmpZipFile = new File(localZipFile.getParentFile(), localZipFile.getName() + ".part");
tmpZipFile.delete();
logger.log("Downloading " + safeDistributionUrl);
download.download(distributionUrl, tmpZipFile);
tmpZipFile.renameTo(localZipFile);
}
List<File> topLevelDirs = listDirs(distDir);
for (File dir : topLevelDirs) {
logger.log("Deleting directory " + dir.getAbsolutePath());
deleteDir(dir);
}
verifyDownloadChecksum(configuration.getDistribution().toString(), localZipFile, distributionSha256Sum);
try {
unzip(localZipFile, distDir);
} catch (IOException e) {
logger.log("Could not unzip " + localZipFile.getAbsolutePath() + " to " + distDir.getAbsolutePath() + ".");
logger.log("Reason: " + e.getMessage());
throw e;
}
InstallCheck installCheck = verifyDistributionRoot(distDir, safeDistributionUrl.toString());
if (installCheck.isVerified()) {
setExecutablePermissions(installCheck.gradleHome);
markerFile.createNewFile();
return installCheck.gradleHome;
}
// Distribution couldn't be installed.
throw new RuntimeException(installCheck.failureMessage);
}
});
}
2. 启动

GradleMain.main

GradleMain.main -> ProcessBootstrap.run 最终来到了org.gradle.launcher.Main.run方法 -> DefaultCommandLineActionFactory.convert(Arrays.asList(args)).execute(listener) ==> WithLogging.execute ==>

做了一层装饰器,层层调用最终还是执行了action 也即是ParseAndBuildAction.execute

ParseAndBuildAction中最终会调用BuildActionsFactory.createAction ==> runBuildInProcess
private Runnable runBuildInProcess(StartParameterInternal startParameter, DaemonParameters daemonParameters) {
// DefaultServiceRegistry
ServiceRegistry globalServices = ServiceRegistryBuilder.builder()
.displayName("Global services")
.parent(loggingServices)
.parent(NativeServices.getInstance())
.provider(new GlobalScopeServices(startParameter.isContinuous()))
.build();
// Force the user home services to be stopped first, the dependencies between the user home services and the global services are not preserved currently
return runBuildAndCloseServices(startParameter, daemonParameters, globalServices.get(BuildExecuter.class), globalServices, globalServices.get(GradleUserHomeScopeServiceRegistry.class));
}
此处的globalServices其实是DefaultServiceRegistry类型,可以理解为全局服务,别人可以向他注册服务

那么DefaultServiceRegistry是如何做到自动提供多项服务呢?先来看看DefaultServiceRegistry的构造器比较有意思

重点是findProviderMethods方法,这里传的参数其实是他本身;
该方法总结下,其实是扫描自身类的三类方法

- decorator方法:create_xxxxx或decorate_xxxx (返回值不能为void)
- factory方法:非静态方法 create_xxxx (返回值不能为void)
- configure方法:configure_xxx
解析这些方法,生成一个RelevantMethods对象,这个对象被放到缓存中;后续调用相关服务直接从这里取就行了
我看仔细看下DefaultServiceRegistry类其实并没有我们所说的那些方法,猜测应该是放到对应的子类去实现了,下面的类都是其子类,每个类对应一个服务

private void findProviderMethods(Object target) {
Class<?> type = target.getClass();
//1. 方法解析
RelevantMethods methods = RelevantMethods.getMethods(type);
// 2. 对方法进行分类处理,转化为相关的方法服务,编译外部调用
for (ServiceMethod method : methods.decorators) {
if (parentServices == null) {
throw new ServiceLookupException(String.format("Cannot use decorator method %s.%s() when no parent registry is provided.", type.getSimpleName(), method.getName()));
}
ownServices.add(new FactoryMethodService(this, target, method));
}
for (ServiceMethod method : methods.factories) {
ownServices.add(new FactoryMethodService(this, target, method));
}
// 3. 针对 config配置,则直接反射调用
for (ServiceMethod method : methods.configurers) {
applyConfigureMethod(method, target);
}
}
private void applyConfigureMethod(ServiceMethod method, Object target) {
Object[] params = new Object[method.getParameterTypes().length];
for (int i = 0; i < method.getParameterTypes().length; i++) {
Type paramType = method.getParameterTypes()[i];
if (paramType.equals(ServiceRegistration.class)) {
params[i] = newRegistration();
} else {
Service paramProvider = find(paramType, allServices);
if (paramProvider == null) {
throw new ServiceLookupException(String.format("Cannot configure services using %s.%s() as required service of type %s is not available.",
method.getOwner().getSimpleName(),
method.getName(),
format(paramType)));
}
params[i] = paramProvider.get();
}
}
try {
method.invoke(target, params);
} catch (Exception e) {
throw new ServiceLookupException(String.format("Could not configure services using %s.%s().",
method.getOwner().getSimpleName(),
method.getName()), e);
}
}
回头再看ServiceRegistryBuilder
public ServiceRegistry build() {
DefaultServiceRegistry registry = new DefaultServiceRegistry(displayName, parents.toArray(new ServiceRegistry[0]));
for (Object provider : providers) {
registry.addProvider(provider);
}
return registry;
}
// DefaultServiceRegistry.java
/**
* Adds a service provider bean to this registry. This provider may define factory and decorator methods.
*/
public DefaultServiceRegistry addProvider(Object provider) {
assertMutable();
findProviderMethods(provider);
return this;
}
可以看到此处又再次调用了findProviderMethods(provider);也就是对GlobalScopeServices类做解析处理了,GlobalScopeServices类中包含了需要相关的服务方法,这样globalServices就正式成为名副其实的全局服务了

后面中间流程有点绕,可以忽略,最终来到了DefaultGradleLauncher.executeTasks
public GradleInternal executeTasks() {
doBuildStages(Stage.RunTasks);
return gradle;
}
至此进入了gradle五个Stage流程中,很熟悉吧,就是传说中gradle的几个阶段,后续会对这几个阶段进行逐篇介绍
private enum Stage {
LoadSettings,
Configure,
TaskGraph,
RunTasks() {
@Override
String getDisplayName() {
return "Build";
}
},
Finished;
String getDisplayName() {
return name();
}
}
本文详细剖析了gradle-6.9.1的启动过程,从gradlew.bat入口到GradleWrapperMain.main方法,再到wrapper模块的下载与解压,以及GradleMain.main的执行。在启动过程中,重点解析了Gradle服务注册与查找机制,如何通过DefaultServiceRegistry创建和装饰服务。文章最后提到gradle的五个执行阶段,并预告后续将深入探讨这些阶段。
1349





