-
Notifications
You must be signed in to change notification settings - Fork 122
/
Copy pathextract_and_dex.gradle
122 lines (110 loc) · 4.51 KB
/
extract_and_dex.gradle
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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
// Copyright 2018 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Defines the task to extract the Jar file from the Android Aar, and
// the task to convert the Jar format to dex, using the dx tool.
def defineExtractionTasks(String resourceName, String buildType) {
project.ext {
sdk_dir = project.android.sdkDirectory
if (sdk_dir == null || !sdk_dir.exists()) {
sdk_dir = System.getenv('ANDROID_HOME')
if (sdk_dir == null || !sdk_dir.exists()) {
throw new StopActionException(
'Android SDK directory should be specified using the ' +
'sdk.dir property or ANDROID_HOME environment variable.')
}
}
}
// Create the tasks after evaluation, as the Android tasks are not available
// until that phase.
afterEvaluate {
Task extractJar = tasks.create(
name: "extractJar$buildType",
dependsOn: "bundle${buildType}Aar",
type: Copy).with {
String aarPath =
project.tasks.getByName("bundle${buildType}Aar").archivePath
from zipTree(aarPath)
into buildDir
// Aar files are defined as having a single jar file named classes.jar,
// which is the specific file we need to extract.
include "classes.jar"
}
String dexedJar = "$buildDir/${resourceName}_lib.jar"
String outPro = "$buildDir/${resourceName}.pro"
Task dexJar = tasks.create(
name: "generateDexJar$buildType",
dependsOn: [extractJar],
type: Exec).with {
String sdk_dir = project.ext.sdk_dir
String buildToolsVersion = project.android.buildToolsVersion
// Define the outputs of this task (the proguard file is generated in the
// doLast below, but must be declared as an output here).
outputs.file "$dexedJar"
outputs.file "$outPro"
// Convert the jar format using the dx tool.
String dex_path = "${sdk_dir}/build-tools/${buildToolsVersion}/lib/d8.jar"
commandLine "java", "-cp", "${dex_path}", "com.android.tools.r8.D8",
"$buildDir/classes.jar",
"--output",
"$dexedJar"
}
// Once the dexed jar has been made, generate a proguard file for it.
dexJar.doLast {
// The path to all the class files, to pass along to jdeps.
String classPath = "$buildDir";
def jdepsOutStream = new ByteArrayOutputStream()
def jdepsArgs = ['-verbose:class', '-cp', "$dexedJar"] + classPath
exec {
executable 'jdeps'
args jdepsArgs
standardOutput = jdepsOutStream
}
// Use a set to make the written lines unique.
Set<String> jdepSet = new HashSet<String>()
for (String jdepsLine : jdepsOutStream.toString().split("[\\r\\n]+")) {
// The lines we care about are formatted like " -> java.class extra"
// Split on the arrow to get the class name.
String[] splitJdep = jdepsLine.split("^ [^-]*-> *")
if (splitJdep.length == 2) {
// We don't care about the system level classes that begin with
// java or android.
String className = splitJdep[1]
if (!className.matches("^(java|android).*")) {
jdepSet.add(
"-keep,includedescriptorclasses public class " +
// Sometimes the class name has additional text after it, which
// this removes.
className.split()[0] +
" { *; }");
}
}
}
new File("$outPro").text = String.join('\n', jdepSet.toSorted())
}
}
}
// Defines the tasks for both debug and release.
def extractAndDexAarFile(String resourceName) {
defineExtractionTasks(resourceName, 'Debug')
defineExtractionTasks(resourceName, 'Release')
}
// Sets the dependencies on the Android prebuild steps to the generated tasks.
def setupDexDependencies(String subproject) {
preDebugBuild.dependsOn("$subproject:generateDexJarDebug")
preReleaseBuild.dependsOn("$subproject:generateDexJarRelease")
}
ext {
extractAndDexAarFile = this.&extractAndDexAarFile
setupDexDependencies = this.&setupDexDependencies
}