Gradle打包流程-Gradle Wrapper

主要概念

Gradle是什么?

Gradle其实就是个构建系统,一个构建项目的工具,即把一堆堆的目录、文件按照一定的规则关联起来,形成一个项目的自动化构建工具,能够简化你的编译、打包、测试过程。Gradle版本,如下gradle-6.1.1-all.zip。

位置:项目主目录 gradle 文件夹->wrapper->gradle-wrapper.properties

1
2
3
4
5
distributionBase=GRADLE_USER_HOME // ~/.gradle
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists // 下载到本地的~/.gradle/wrapper/dists目录
distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip //要下载的gradle的地址

Gradle Wrapper是什么?

Gradle Wrapper的作用是简化Gradle本身的安装、部署。不同版本的项目可能需要不同版本的Gradle,手工部署的话比较麻烦,而且可能产生冲突,所以需要Gradle Wrapper帮你搞定这些事情。Gradle Wrapper是Gradle项目的一部分.gradle-wrapper.jar/gradle-wrapper.properties,gradle-wrapper.jar是Gradle Wrapper的主体功能包。在Android Studio安装过程中产生gradle-wrapper.jar.然后每次新建项目,会将gradle-wrapper.jar拷贝到你的项目的gradle/wrapper目录中。

Gradle插件又是什么?

Gradle插件是针对Gradle发行版和Android SDK Build Tools封装的一个工具,是一堆适合Android开发的Gradle插件的集合,主要有两大功能:

调用Gradle本身的代码和批处理工具来构建项目

调用Android SDK的编译、打包功能

Gradle插件版本:项目主目录下的 build.gradle 中,如“com.android.tools.build:gradle:4.0.2”:它会下载到~.gradle\caches\modules-2\files-2.1\com.android.tools.build目录中。

1
2
3
dependencies {
classpath 'com.android.tools.build:gradle:4.0.2'
}

Android SDK Build Tools Version:Android SDK 构建工具版本;
buildToolsVersion 位置:app 目录->buid.gradle 文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
android {
compileSdkVersion 28
defaultConfig {
applicationId "com.myapplication"
minSdkVersion 23
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}

依赖关系

明确概念:

  • Gradle Plugin Version: Gradle 插件版本

  • Gradle Version: Gradle发行版本

  • Android SDK Build Tools Version:Android SDK 构建工具版本
    Gradle Plugin 有不同的版本号。 即我们常见的:classpath ‘com.android.tools.build:gradle:4.0.2’】,
    每个插件版本号又对应一个或一些 Gradle 发行版本【即我们常见的:gradle-6.1.1-all.zip】
    如果这两个版本对应不上了,那么构建项目的时候就会报错。
    Android Gradle 插件版本说明

Gradle Plugin 还和 Android SDK BuildTool 有关联,因为它还负责和编译相关的功能,这也是为何我们要在 build.gradle 里注明 buildToolsVersion 的原因。

断点调试

debug调试

执行流程

先看一下来自掘金社区Gradle构建的核心流程图
核心流程图
时序图:
时序图
1.当我们执行一个 gralde 命令时,便会调用 gradle/wrapper/gradle-wrapper.jar 里面 org.gradle.wrapper.GradleWrapperMain 类的 main 方法,它就是 gradle 的一个入口方法。

1
2
3
4
5
6
7
8
public static void main(String[] args) throws Exception {
......
WrapperExecutor wrapperExecutor = WrapperExecutor.forWrapperPropertiesFile(propertiesFile);
wrapperExecutor.execute(
args,
new Install(logger, new Download(logger, "gradlew", UNKNOWN_VERSION), new PathAssembler(gradleUserHome)),
new BootstrapMainStarter());
}

2.WrapperExecutor 的 execute 方法:createDist,会根据config的配置去校验版本和下载gradle wrapper需要的依赖与源码;start方法开始执行gradle的构建流程。Gradle对应版本下载完成之后,Gradle Wrapper的使命基本完成了.

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

3.
BootstrapMainStarter的start做了什么:就是调用GradleMain里的main方法。

1
2
3
4
5
6
7
8
9
public void start(String[] args, File gradleHome) throws Exception {
......
Class<?> mainClass = contextClassLoader.loadClass("org.gradle.launcher.GradleMain");
Method mainMethod = mainClass.getMethod("main", String[].class);
mainMethod.invoke(null, new Object[]{args});
if (contextClassLoader instanceof Closeable) {
((Closeable) contextClassLoader).close();
}
}

4.GradleMain不解释。

1
2
3
public static void main(String[] args) {
new ProcessBootstrap().run("org.gradle.launcher.Main", args);
}

5.Main

1
2
3
4
5
6
7
8
9
10
11
12
public static void main(String[] args) {
new Main().run(args);
}

@Override
protected void doAction(String[] args, ExecutionListener listener) {
createActionFactory().convert(Arrays.asList(args)).execute(listener);
}

CommandLineActionFactory createActionFactory() {
return new DefaultCommandLineActionFactory();
}

6.DefaultCommandLineActionFactory

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public CommandLineExecution convert(List<String> args) {
......
return new WithLogging(loggingServices,
args,
loggingConfiguration,
new ParseAndBuildAction(loggingServices, args),
new BuildExceptionReporter(loggingServices.get(StyledTextOutputFactory.class), loggingConfiguration, clientMetaData()));
}

public void execute(ExecutionListener executionListener) {
......
Action<? super ExecutionListener> action;
try {
ParsedCommandLine commandLine = parser.parse(args);
action = createAction(actions, parser, commandLine);
} catch (CommandLineArgumentException e) {
action = new CommandLineParseFailureAction(parser, e);
}

action.execute(executionListener);
}

时序图
1.BuildActionsFactory

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
private Runnable runBuildInProcess(StartParameterInternal startParameter, DaemonParameters daemonParameters) {
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));
}

public ServiceRegistry build() {
DefaultServiceRegistry registry = new DefaultServiceRegistry(displayName, parents.toArray(new ServiceRegistry[0]));
for (Object provider : providers) {
registry.addProvider(provider);
}
return registry;
}

private Runnable runBuildAndCloseServices(StartParameterInternal startParameter, DaemonParameters daemonParameters, BuildActionExecuter<BuildActionParameters> executer, ServiceRegistry sharedServices, Object... stopBeforeSharedServices) {
BuildActionParameters parameters = createBuildActionParameters(startParameter, daemonParameters);
Stoppable stoppable = new CompositeStoppable().add(stopBeforeSharedServices).add(sharedServices);
return new RunBuildAction(executer, startParameter, clientMetaData(), getBuildStartTime(), parameters, sharedServices, stoppable);
}

2.DefaultServiceRegistry

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
private void findProviderMethods(Object target) {
Class<?> type = target.getClass();
RelevantMethods methods = RelevantMethods.getMethods(type);
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));
}
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) {
}
}

3.GlobalScopeServices

1
2
3
4
5
6
7
8
void configure(ServiceRegistration registration, ClassLoaderRegistry classLoaderRegistry) {
registration.add(ClassLoaderScopeListeners.class);
final List<PluginServiceRegistry> pluginServiceFactories = new DefaultServiceLocator(classLoaderRegistry.getRuntimeClassLoader(), classLoaderRegistry.getPluginsClassLoader()).getAll(PluginServiceRegistry.class);
for (PluginServiceRegistry pluginServiceRegistry : pluginServiceFactories) {
registration.add(PluginServiceRegistry.class, pluginServiceRegistry);
pluginServiceRegistry.registerGlobalServices(registration);
}
}

4.LauncherServices

1
2
3
public void registerGlobalServices(ServiceRegistration registration) {
registration.addProvider(new ToolingGlobalScopeServices());
}

5.InProcessBuildActionExecuter

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
public BuildActionResult execute(final BuildAction action, final BuildRequestContext buildRequestContext, BuildActionParameters actionParameters, ServiceRegistry contextServices) {
BuildStateRegistry buildRegistry = contextServices.get(BuildStateRegistry.class);
final PayloadSerializer payloadSerializer = contextServices.get(PayloadSerializer.class);
BuildOperationNotificationValve buildOperationNotificationValve = contextServices.get(BuildOperationNotificationValve.class);

buildOperationNotificationValve.start();
try {
RootBuildState rootBuild = buildRegistry.createRootBuild(BuildDefinition.fromStartParameter(action.getStartParameter(), null));
return rootBuild.run(new Transformer<BuildActionResult, BuildController>() {
@Override
public BuildActionResult transform(BuildController buildController) {
BuildActionRunner.Result result = buildActionRunner.run(action, buildController);
if (result.getBuildFailure() == null) {
return BuildActionResult.of(payloadSerializer.serialize(result.getClientResult()));
}
if (buildRequestContext.getCancellationToken().isCancellationRequested()) {
return BuildActionResult.cancelled(payloadSerializer.serialize(result.getBuildFailure()));
}
return BuildActionResult.failed(payloadSerializer.serialize(result.getClientFailure()));
}
});
} finally {
buildOperationNotificationValve.stop();
}
}

时序图
1.InProcessBuildActionExecuter

1
2
3
4
5
6
7
8
9
10
11
12
try {
RootBuildState rootBuild = buildRegistry.createRootBuild(BuildDefinition.fromStartParameter(action.getStartParameter(), null));
return rootBuild.run(new Transformer<BuildActionResult, BuildController>() {
@Override
public BuildActionResult transform(BuildController buildController) {
BuildActionRunner.Result result = buildActionRunner.run(action, buildController);
......
}
});
} finally {
buildOperationNotificationValve.stop();
}

2.DefaultRootBuildState

1
2
3
4
5
6
7
8
9
10
11
public <T> T run(Transformer<T, ? super BuildController> buildAction) {
final GradleBuildController buildController = new GradleBuildController(gradleLauncher);
RootBuildLifecycleListener buildLifecycleListener = listenerManager.getBroadcaster(RootBuildLifecycleListener.class);
GradleInternal gradle = buildController.getGradle();
buildLifecycleListener.afterStart(gradle);
try {
return buildAction.transform(buildController);
} finally {
buildLifecycleListener.beforeComplete(gradle);
}
}

3.GradleBuildController

1
2
3
4
5
6
7
8
public GradleInternal run() {
return doBuild(GradleInternal.BuildType.TASKS, new Action<GradleLauncher>() {
@Override
public void execute(@Nonnull GradleLauncher gradleLauncher) {
gradleLauncher.executeTasks();
}
});
}

4.DefaultGradleLauncher

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
private void doClassicBuildStages(Stage upTo) {
if (stage == null) {
instantExecution.prepareForBuildLogicExecution();
}
prepareSettings();
if (upTo == Stage.LoadSettings) {
return;
}
prepareProjects();
if (upTo == Stage.Configure) {
return;
}
prepareTaskExecution();
if (upTo == Stage.TaskGraph) {
return;
}
instantExecution.saveScheduledWork();
runWork();
}

Task源码对应

Task Name Class Name 作用
preBuild 空 task,只做锚点使用
preDebugBuild 空 task,只做锚点使用,与 preBuild 区别是这个 task 是 variant 的锚点
compileDebugAidl AidlCompile 处理 aidl
compileDebugRenderscript RenderscriptCompile 处理 renderscript
checkDebugManifest CheckManifest 检测 manifest 是否存在
generateDebugBuildConfig GenerateBuildConfig 生成 BuildConfig.java
prepareLintJar PrepareLintJar 拷贝 lint jar 包到指定位置
generateDebugResValues GenerateResValues 生成 resvalues,generated.xml
generateDebugResources 空 task,锚点
mergeDebugResources MergeResources 合并资源文件
createDebugCompatibleScreenManifests CompatibleScreensManifest manifest 文件中生成 compatible-screens,指定屏幕适配
processDebugManifest MergeManifests 合并 manifest 文件
splitsDiscoveryTaskDebug SplitsDiscovery 生成 split-list.json,用于 apk 分包
processDebugResources ProcessAndroidResources aapt 打包资源
generateDebugSources 空 task,锚点
javaPreCompileDebug JavaPreCompileTask 生成 annotationProcessors.json 文件
compileDebugJavaWithJavac AndroidJavaCompile 编译 java 文件
compileDebugNdk NdkCompile 编译 ndk
compileDebugSources 空 task,锚点使用
mergeDebugShaders MergeSourceSetFolders 合并 shader 文件
compileDebugShaders ShaderCompile 编译 shaders
generateDebugAssets 空 task,锚点
mergeDebugAssets MergeSourceSetFolders 合并 assets 文件
transformClassesWithDexBuilderForDebug DexArchiveBuilderTransform class 打包 dex
transformDexArchiveWithExternalLibsDexMergerForDebug ExternalLibsMergerTransform 打包三方库的 dex,在 dex 增量的时候就不需要再 merge 了,节省时间
transformDexArchiveWithDexMergerForDebug DexMergerTransform 打包最终的 dex
mergeDebugJniLibFolders MergeSouceSetFolders 合并 jni lib 文件
transformNativeLibsWithMergeJniLibsForDebug MergeJavaResourcesTransform 合并 jnilibs
transformNativeLibsWithStripDebugSymbolForDebug StripDebugSymbolTransform 去掉 native lib 里的 debug 符号
processDebugJavaRes ProcessJavaResConfigAction 处理 java res
transformResourcesWithMergeJavaResForDebug MergeJavaResourcesTransform 合并 java res
validateSigningDebug ValidateSigningTask 验证签名
packageDebug PackageApplication 打包 apk
assembleDebug 空 task,锚点

参考

Gradle、Gradle Wrapper与Android Plugin for Gradle的区别和联系
Gradle之Android Gradle Plugin 主要 Task 分析