blob: c4de6e38c9b22f2a593d0a9203469ef9b7c6e352 [file] [log] [blame]
Rico Wind3d369b42021-01-12 10:26:24 +01001#!/usr/bin/env python3
Christoffer Quist Adamsenf2e8db72020-11-07 14:09:49 +01002# Copyright (c) 2020, the R8 project authors. Please see the AUTHORS file
3# for details. All rights reserved. Use of this source code is governed by a
4# BSD-style license that can be found in the LICENSE file.
Morten Krogh-Jespersen45d7a7b2020-11-02 08:31:09 +01005
Morten Krogh-Jespersencd55f812020-11-04 09:13:31 +01006import adb
7import apk_masseur
Christoffer Quist Adamsenf79f1a22021-01-12 16:24:34 +01008import as_utils
Morten Krogh-Jespersen45d7a7b2020-11-02 08:31:09 +01009import compiledump
10import gradle
Morten Krogh-Jespersen45d7a7b2020-11-02 08:31:09 +010011import optparse
12import os
13import shutil
14import sys
15import time
Morten Krogh-Jespersen47764032020-11-11 15:09:39 +010016import update_prebuilds_in_android
Morten Krogh-Jespersen45d7a7b2020-11-02 08:31:09 +010017import utils
18import zipfile
19
20from datetime import datetime
21
22SHRINKERS = ['r8', 'r8-full', 'r8-nolib', 'r8-nolib-full']
23
24class AttrDict(dict):
25 def __getattr__(self, name):
26 return self.get(name, None)
27
Morten Krogh-Jespersen45d7a7b2020-11-02 08:31:09 +010028# To generate the files for a new app, navigate to the app source folder and
29# run:
30# ./gradlew clean :app:assembleRelease -Dcom.android.tools.r8.dumpinputtodirectory=<path>
31# and store the dump and the apk.
32# If the app has instrumented tests, adding `testBuildType "release"` and
33# running:
34# ./gradlew assembleAndroidTest -Dcom.android.tools.r8.dumpinputtodirectory=<path>
35# will also generate dumps and apk for tests.
36
37class App(object):
38 def __init__(self, fields):
39 defaults = {
40 'id': None,
41 'name': None,
Christoffer Quist Adamsen53e29472020-11-13 10:53:06 +010042 'collections': [],
Morten Krogh-Jespersen45d7a7b2020-11-02 08:31:09 +010043 'dump_app': None,
Morten Krogh-Jespersencd55f812020-11-04 09:13:31 +010044 'apk_app': None,
Morten Krogh-Jespersen571cfe72020-11-09 23:44:03 +010045 'dump_test': None,
Morten Krogh-Jespersen51a16352020-11-04 09:31:15 +010046 'apk_test': None,
Morten Krogh-Jespersen45d7a7b2020-11-02 08:31:09 +010047 'skip': False,
48 'url': None, # url is not used but nice to have for updating apps
49 'revision': None,
50 'folder': None,
51 'skip_recompilation': False,
Morten Krogh-Jespersen43f3cea2020-11-12 17:09:51 +010052 'compiler_properties': [],
Morten Krogh-Jespersen45d7a7b2020-11-02 08:31:09 +010053 }
54 # This below does not work in python3
55 defaults.update(fields.items())
56 self.__dict__ = defaults
57
58
Christoffer Quist Adamsen53e29472020-11-13 10:53:06 +010059class AppCollection(object):
60 def __init__(self, fields):
61 defaults = {
62 'name': None
63 }
64 # This below does not work in python3
65 defaults.update(fields.items())
66 self.__dict__ = defaults
67
68
Morten Krogh-Jespersen45d7a7b2020-11-02 08:31:09 +010069APPS = [
70 App({
Morten Krogh-Jespersen0f85fa52020-11-04 13:40:43 +010071 'id': 'com.numix.calculator',
72 'name': 'Calculator',
73 'dump_app': 'dump_app.zip',
74 'apk_app': 'app-release.apk',
75 # Compiling tests fail: Library class android.content.res.XmlResourceParser
76 # implements program class org.xmlpull.v1.XmlPullParser. Nothing to really
77 # do about that.
78 'id_test': 'com.numix.calculator.test',
79 'dump_test': 'dump_test.zip',
80 'apk_test': 'app-release-androidTest.apk',
81 'url': 'https://github.com/numixproject/android-suite/tree/master/Calculator',
82 'revision': 'f58e1b53f7278c9b675d5855842c6d8a44cccb1f',
83 'folder': 'android-suite-calculator',
84 }),
85 App({
Morten Krogh-Jespersen3f0d72f2020-11-04 15:49:17 +010086 'id': 'dev.dworks.apps.anexplorer.pro',
87 'name': 'AnExplorer',
88 'dump_app': 'dump_app.zip',
89 'apk_app': 'AnExplorer-googleMobileProRelease-4.0.3.apk',
90 'url': 'https://github.com/christofferqa/AnExplorer',
91 'revision': '365927477b8eab4052a1882d5e358057ae3dee4d',
92 'folder': 'anexplorer',
93 }),
94 App({
Morten Krogh-Jespersen09e2fda2020-11-04 16:43:25 +010095 'id': 'de.danoeh.antennapod',
96 'name': 'AntennaPod',
97 'dump_app': 'dump_app.zip',
98 'apk_app': 'app-free-release.apk',
99 # TODO(b/172452102): Tests and monkey do not work
100 'id_test': 'de.danoeh.antennapod.test',
101 'dump_test': 'dump_test.zip',
102 'apk_test': 'app-free-release-androidTest.apk',
103 'url': 'https://github.com/christofferqa/AntennaPod.git',
104 'revision': '77e94f4783a16abe9cc5b78dc2d2b2b1867d8c06',
105 'folder': 'antennapod',
Morten Krogh-Jespersen09e2fda2020-11-04 16:43:25 +0100106 }),
107 App({
Morten Krogh-Jespersen45d7a7b2020-11-02 08:31:09 +0100108 'id': 'com.example.applymapping',
109 'name': 'applymapping',
110 'dump_app': 'dump_app.zip',
Morten Krogh-Jespersencd55f812020-11-04 09:13:31 +0100111 'apk_app': 'app-release.apk',
Morten Krogh-Jespersen51a16352020-11-04 09:31:15 +0100112 'id_test': 'com.example.applymapping.test',
113 'dump_test': 'dump_test.zip',
114 'apk_test': 'app-release-androidTest.apk',
Morten Krogh-Jespersen45d7a7b2020-11-02 08:31:09 +0100115 'url': 'https://github.com/mkj-gram/applymapping',
116 'revision': 'e3ae14b8c16fa4718e5dea8f7ad00937701b3c48',
117 'folder': 'applymapping',
Morten Krogh-Jespersen90912fd2020-11-05 09:21:16 +0100118 }),
119 App({
Morten Krogh-Jespersena98a4222020-11-05 10:50:10 +0100120 'id': 'com.chanapps.four.activity',
121 'name': 'chanu',
122 'dump_app': 'dump_app.zip',
123 'apk_app': 'app-release.apk',
124 'url': 'https://github.com/mkj-gram/chanu.git',
125 'revision': '6e53458f167b6d78398da60c20fd0da01a232617',
126 'folder': 'chanu',
Morten Krogh-Jespersen43f3cea2020-11-12 17:09:51 +0100127 # The app depends on a class file that has access flags interface but
128 # not abstract
129 'compiler_properties': ['-Dcom.android.tools.r8.allowInvalidCfAccessFlags=true']
Morten Krogh-Jespersena98a4222020-11-05 10:50:10 +0100130 }),
Morten Krogh-Jespersend06ff012020-11-05 10:50:21 +0100131 # TODO(b/172539375): Monkey runner fails on recompilation.
132 App({
133 'id': 'com.google.firebase.example.fireeats',
134 'name': 'FriendlyEats',
135 'dump_app': 'dump_app.zip',
136 'apk_app': 'app-release-unsigned.apk',
137 'url': 'https://github.com/firebase/friendlyeats-android',
138 'revision': '7c6dd016fc31ea5ecb948d5166b8479efc3775cc',
139 'folder': 'friendlyeats',
140 }),
Morten Krogh-Jespersena98a4222020-11-05 10:50:10 +0100141 App({
Morten Krogh-Jespersen162b3452020-11-05 13:07:10 +0100142 'id': 'com.google.samples.apps.sunflower',
143 'name': 'Sunflower',
144 'dump_app': 'dump_app.zip',
145 'apk_app': 'app-debug.apk',
146 # TODO(b/172549283): Compiling tests fails
Morten Krogh-Jespersend0389c02020-11-09 23:42:51 +0100147 'id_test': 'com.google.samples.apps.sunflower.test',
Morten Krogh-Jespersen162b3452020-11-05 13:07:10 +0100148 'dump_test': 'dump_test.zip',
149 'apk_test': 'app-debug-androidTest.apk',
150 'url': 'https://github.com/android/sunflower',
151 'revision': '0c4c88fdad2a74791199dffd1a6559559b1dbd4a',
152 'folder': 'sunflower',
Morten Krogh-Jespersen162b3452020-11-05 13:07:10 +0100153 }),
Morten Krogh-Jespersenac9de3f2020-11-05 17:07:26 +0100154 # TODO(b/172565385): Monkey runner fails on recompilation
155 App({
156 'id': 'com.google.samples.apps.iosched',
157 'name': 'iosched',
158 'dump_app': 'dump_app.zip',
159 'apk_app': 'mobile-release.apk',
160 'url': 'https://github.com/christofferqa/iosched.git',
161 'revision': '581cbbe2253711775dbccb753cdb53e7e506cb02',
162 'folder': 'iosched',
163 }),
Morten Krogh-Jespersen162b3452020-11-05 13:07:10 +0100164 App({
Morten Krogh-Jespersend0389c02020-11-09 23:42:51 +0100165 'id': 'fr.neamar.kiss',
166 'name': 'KISS',
167 'dump_app': 'dump_app.zip',
168 'apk_app': 'app-release.apk',
169 # TODO(b/172569220): Running tests fails due to missing keep rules
170 'id_test': 'fr.neamar.kiss.test',
171 'dump_test': 'dump_test.zip',
172 'apk_test': 'app-release-androidTest.apk',
173 'url': 'https://github.com/Neamar/KISS',
174 'revision': '8ccffaadaf0d0b8fc4418ed2b4281a0935d3d971',
175 'folder': 'kiss',
176 }),
Morten Krogh-Jespersenaaacd722020-11-09 23:43:24 +0100177 # TODO(b/172577344): Monkey runner not working.
178 App({
179 'id': 'io.github.hidroh.materialistic',
180 'name': 'materialistic',
181 'dump_app': 'dump_app.zip',
182 'apk_app': 'app-release.apk',
183 'url': 'https://github.com/christofferqa/materialistic.git',
184 'revision': '2b2b2ee25ce9e672d5aab1dc90a354af1522b1d9',
185 'folder': 'materialistic',
186 }),
Morten Krogh-Jespersend0389c02020-11-09 23:42:51 +0100187 App({
Morten Krogh-Jespersen571cfe72020-11-09 23:44:03 +0100188 'id': 'com.avjindersinghsekhon.minimaltodo',
189 'name': 'MinimalTodo',
190 'dump_app': 'dump_app.zip',
191 'apk_app': 'app-release.apk',
192 'url': 'https://github.com/christofferqa/Minimal-Todo',
193 'revision': '9d8c73746762cd376b718858ec1e8783ca07ba7c',
194 'folder': 'minimal-todo',
195 }),
196 App({
Morten Krogh-Jespersen3e3781f2020-11-09 23:44:33 +0100197 'id': 'net.nurik.roman.muzei',
198 'name': 'muzei',
199 'dump_app': 'dump_app.zip',
200 'apk_app': 'muzei-release.apk',
201 'url': 'https://github.com/romannurik/muzei',
202 'revision': '9eac6e98aebeaf0ae40bdcd85f16dd2886551138',
203 'folder': 'muzei',
204 }),
Morten Krogh-Jespersenf8e77032020-11-09 23:44:58 +0100205 # TODO(b/172806281): Monkey runner does not work.
206 App({
207 'id': 'org.schabi.newpipe',
208 'name': 'NewPipe',
209 'dump_app': 'dump_app.zip',
210 'apk_app': 'app-release-unsigned.apk',
211 'url': 'https://github.com/TeamNewPipe/NewPipe',
212 'revision': 'f4435f90313281beece70c544032f784418d85fa',
213 'folder': 'newpipe',
Morten Krogh-Jespersenf8e77032020-11-09 23:44:58 +0100214 }),
Morten Krogh-Jespersendf700642020-11-09 23:45:25 +0100215 # TODO(b/172806808): Monkey runner does not work.
216 App({
217 'id': 'io.rover.app.debug',
218 'name': 'Rover',
219 'dump_app': 'dump_app.zip',
220 'apk_app': 'example-app-release-unsigned.apk',
221 'url': 'https://github.com/RoverPlatform/rover-android',
222 'revision': '94342117097770ea3ca2c6df6ab496a1a55c3ce7',
223 'folder': 'rover-android',
224 }),
Morten Krogh-Jespersen2f1be952020-11-09 23:45:48 +0100225 # TODO(b/172808159): Monkey runner does not work
226 App({
227 'id': 'com.google.android.apps.santatracker',
228 'name': 'SantaTracker',
229 'dump_app': 'dump_app.zip',
230 'apk_app': 'santa-tracker-release.apk',
231 'url': 'https://github.com/christofferqa/santa-tracker-android',
232 'revision': '8dee74be7d9ee33c69465a07088c53087d24a6dd',
233 'folder': 'santa-tracker',
234 }),
235 App({
Morten Krogh-Jespersen88cc0772020-11-09 23:46:13 +0100236 'id': 'org.thoughtcrime.securesms',
237 'name': 'Signal',
238 'dump_app': 'dump_app.zip',
239 'apk_app': 'Signal-Android-play-prod-universal-release-4.76.2.apk',
240 # TODO(b/172812839): Instrumentation test fails.
241 'id_test': 'org.thoughtcrime.securesms.test',
242 'dump_test': 'dump_test.zip',
243 'apk_test': 'Signal-Android-play-prod-release-androidTest.apk',
244 'url': 'https://github.com/signalapp/Signal-Android',
245 'revision': '91ca19f294362ccee2c2b43c247eba228e2b30a1',
246 'folder': 'signal-android',
247 }),
Morten Krogh-Jespersen733bcff2020-11-09 23:46:43 +0100248 # TODO(b/172815827): Monkey runner does not work
249 App({
250 'id': 'com.simplemobiletools.calendar.pro',
251 'name': 'Simple-Calendar',
252 'dump_app': 'dump_app.zip',
253 'apk_app': 'calendar-release.apk',
254 'url': 'https://github.com/SimpleMobileTools/Simple-Calendar',
255 'revision': '906209874d0a091c7fce5a57972472f272d6b068',
256 'folder': 'simple-calendar',
257 }),
Morten Krogh-Jespersen8a564d32020-11-09 23:47:07 +0100258 # TODO(b/172815534): Monkey runner does not work
259 App({
260 'id': 'com.simplemobiletools.camera.pro',
261 'name': 'Simple-Camera',
262 'dump_app': 'dump_app.zip',
263 'apk_app': 'camera-release.apk',
264 'url': 'https://github.com/SimpleMobileTools/Simple-Camera',
265 'revision': 'ebf9820c51e960912b3238287e30a131244fdee6',
266 'folder': 'simple-camera',
267 }),
Morten Krogh-Jespersen88cc0772020-11-09 23:46:13 +0100268 App({
Morten Krogh-Jespersen805e31a2020-11-09 23:47:32 +0100269 'id': 'com.simplemobiletools.filemanager.pro',
270 'name': 'Simple-File-Manager',
271 'dump_app': 'dump_app.zip',
272 'apk_app': 'file-manager-release.apk',
273 'url': 'https://github.com/SimpleMobileTools/Simple-File-Manager',
274 'revision': '2b7fa68ea251222cc40cf6d62ad1de260a6f54d9',
275 'folder': 'simple-file-manager',
276 }),
277 App({
Morten Krogh-Jespersendc29e992020-11-09 23:48:01 +0100278 'id': 'com.simplemobiletools.gallery.pro',
279 'name': 'Simple-Gallery',
280 'dump_app': 'dump_app.zip',
281 'apk_app': 'gallery-326-foss-release.apk',
282 'url': 'https://github.com/SimpleMobileTools/Simple-Gallery',
283 'revision': '564e56b20d33b28d0018c8087ec705beeb60785e',
284 'folder': 'simple-gallery',
Morten Krogh-Jespersendc29e992020-11-09 23:48:01 +0100285 }),
286 App({
Morten Krogh-Jespersen4a9657a2020-11-09 23:48:21 +0100287 'id': 'com.example.sqldelight.hockey',
288 'name': 'SQLDelight',
289 'dump_app': 'dump_app.zip',
290 'apk_app': 'android-release.apk',
291 'url': 'https://github.com/christofferqa/sqldelight',
292 'revision': '2e67a1126b6df05e4119d1e3a432fde51d76cdc8',
293 'folder': 'sqldelight',
294 }),
Morten Krogh-Jespersenf12a57e2020-11-09 23:48:53 +0100295 # TODO(b/172824096): Monkey runner does not work.
296 App({
297 'id': 'eu.kanade.tachiyomi',
298 'name': 'Tachiyomi',
299 'dump_app': 'dump_app.zip',
300 'apk_app': 'app-dev-release.apk',
301 'url': 'https://github.com/inorichi/tachiyomi',
302 'revision': '8aa6486bf76ab9a61a5494bee284b1a5e9180bf3',
303 'folder': 'tachiyomi',
304 }),
Morten Krogh-Jespersen58974522020-11-10 00:20:46 +0100305 # TODO(b/172862042): Monkey runner does not work.
306 App({
307 'id': 'app.tivi',
308 'name': 'Tivi',
309 'dump_app': 'dump_app.zip',
310 'apk_app': 'app-release.apk',
311 'url': 'https://github.com/chrisbanes/tivi',
Morten Krogh-Jespersen44e2f892020-12-17 09:18:35 +0100312 'revision': '5c6d9ed338885c59b1fc64050d92d056417bb4de',
Morten Krogh-Jespersen58974522020-11-10 00:20:46 +0100313 'folder': 'tivi',
Morten Krogh-Jespersen58974522020-11-10 00:20:46 +0100314 }),
Morten Krogh-Jespersen4a9657a2020-11-09 23:48:21 +0100315 App({
Morten Krogh-Jespersen9033d1a2020-11-09 23:49:23 +0100316 'id': 'com.keylesspalace.tusky',
317 'name': 'Tusky',
318 'dump_app': 'dump_app.zip',
319 'apk_app': 'app-blue-release.apk',
320 'url': 'https://github.com/tuskyapp/Tusky',
321 'revision': '814a9b8f9bacf8d26f712b06a0313a3534a2be95',
322 'folder': 'tusky',
Morten Krogh-Jespersen9033d1a2020-11-09 23:49:23 +0100323 }),
324 App({
Morten Krogh-Jespersen90912fd2020-11-05 09:21:16 +0100325 'id': 'org.wikipedia',
326 'name': 'Wikipedia',
327 'dump_app': 'dump_app.zip',
328 'apk_app': 'app-prod-release.apk',
329 'url': 'https://github.com/wikimedia/apps-android-wikipedia',
330 'revision': '0fa7cad843c66313be8e25790ef084cf1a1fa67e',
331 'folder': 'wikipedia',
332 }),
Christoffer Quist Adamsen53e29472020-11-13 10:53:06 +0100333 # TODO(b/173167253): Check if monkey testing works.
334 App({
335 'id': 'androidx.compose.samples.crane',
336 'name': 'compose-crane',
337 'collections': ['compose-samples'],
338 'dump_app': 'dump_app.zip',
339 'apk_app': 'app-release-unsigned.apk',
340 'url': 'https://github.com/android/compose-samples',
341 'revision': '779cf9e187b8ee2c6b620b2abb4524719b3f10f8',
342 'folder': 'android/compose-samples/crane',
Morten Krogh-Jespersenc8d8cfe2020-11-16 09:32:57 +0100343 # TODO(b/173176042): Fix recompilation
344 'skip_recompilation': True,
Christoffer Quist Adamsen53e29472020-11-13 10:53:06 +0100345 }),
346 # TODO(b/173167253): Check if monkey testing works.
347 App({
348 'id': 'com.example.jetcaster',
349 'name': 'compose-jetcaster',
350 'collections': ['compose-samples'],
351 'dump_app': 'dump_app.zip',
352 'apk_app': 'app-release-unsigned.apk',
353 'url': 'https://github.com/android/compose-samples',
354 'revision': '779cf9e187b8ee2c6b620b2abb4524719b3f10f8',
355 'folder': 'android/compose-samples/jetcaster',
356 # TODO(b/173176042): Fix recompilation
357 'skip_recompilation': True,
358 }),
359 # TODO(b/173167253): Check if monkey testing works.
360 App({
361 'id': 'com.example.compose.jetchat',
362 'name': 'compose-jetchat',
363 'collections': ['compose-samples'],
364 'dump_app': 'dump_app.zip',
365 'apk_app': 'app-release-unsigned.apk',
366 'url': 'https://github.com/android/compose-samples',
367 'revision': '779cf9e187b8ee2c6b620b2abb4524719b3f10f8',
368 'folder': 'android/compose-samples/jetchat',
369 # TODO(b/173176042): Fix recompilation
370 'skip_recompilation': True,
371 }),
372 # TODO(b/173167253): Check if monkey testing works.
373 App({
374 'id': 'com.example.jetnews',
375 'name': 'compose-jetnews',
376 'collections': ['compose-samples'],
377 'dump_app': 'dump_app.zip',
378 'apk_app': 'app-release-unsigned.apk',
379 'url': 'https://github.com/android/compose-samples',
380 'revision': '779cf9e187b8ee2c6b620b2abb4524719b3f10f8',
381 'folder': 'android/compose-samples/jetnews',
382 # TODO(b/173176042): Fix recompilation
383 'skip_recompilation': True,
384 }),
385 # TODO(b/173167253): Check if monkey testing works.
386 App({
387 'id': 'com.example.jetsnack',
388 'name': 'compose-jetsnack',
389 'collections': ['compose-samples'],
390 'dump_app': 'dump_app.zip',
391 'apk_app': 'app-release-unsigned.apk',
392 'url': 'https://github.com/android/compose-samples',
393 'revision': '779cf9e187b8ee2c6b620b2abb4524719b3f10f8',
394 'folder': 'android/compose-samples/jetsnack',
Morten Krogh-Jespersenc8d8cfe2020-11-16 09:32:57 +0100395 # TODO(b/173176042): Fix recompilation
396 'skip_recompilation': True,
Christoffer Quist Adamsen53e29472020-11-13 10:53:06 +0100397 }),
398 # TODO(b/173167253): Check if monkey testing works.
399 App({
400 'id': 'com.example.compose.jetsurvey',
401 'name': 'compose-jetsurvey',
402 'collections': ['compose-samples'],
403 'dump_app': 'dump_app.zip',
404 'apk_app': 'app-release-unsigned.apk',
405 'url': 'https://github.com/android/compose-samples',
406 'revision': '779cf9e187b8ee2c6b620b2abb4524719b3f10f8',
407 'folder': 'android/compose-samples/jetsurvey',
Morten Krogh-Jespersenc8d8cfe2020-11-16 09:32:57 +0100408 # TODO(b/173176042): Fix recompilation
409 'skip_recompilation': True,
Christoffer Quist Adamsen53e29472020-11-13 10:53:06 +0100410 }),
411 # TODO(b/173167253): Check if monkey testing works.
412 App({
413 'id': 'com.example.owl',
414 'name': 'compose-owl',
415 'collections': ['compose-samples'],
416 'dump_app': 'dump_app.zip',
417 'apk_app': 'app-release-unsigned.apk',
418 'url': 'https://github.com/android/compose-samples',
419 'revision': '779cf9e187b8ee2c6b620b2abb4524719b3f10f8',
420 'folder': 'android/compose-samples/owl',
Morten Krogh-Jespersenc8d8cfe2020-11-16 09:32:57 +0100421 # TODO(b/173176042): Fix recompilation
422 'skip_recompilation': True,
Christoffer Quist Adamsen53e29472020-11-13 10:53:06 +0100423 }),
424 # TODO(b/173167253): Check if monkey testing works.
425 App({
426 'id': 'com.example.compose.rally',
427 'name': 'compose-rally',
428 'collections': ['compose-samples'],
429 'dump_app': 'dump_app.zip',
430 'apk_app': 'app-release-unsigned.apk',
431 'url': 'https://github.com/android/compose-samples',
432 'revision': '779cf9e187b8ee2c6b620b2abb4524719b3f10f8',
433 'folder': 'android/compose-samples/rally',
Morten Krogh-Jespersenc8d8cfe2020-11-16 09:32:57 +0100434 # TODO(b/173176042): Fix recompilation
435 'skip_recompilation': True,
Christoffer Quist Adamsen53e29472020-11-13 10:53:06 +0100436 }),
437]
438
439
440APP_COLLECTIONS = [
441 AppCollection({
442 'name': 'compose-samples',
443 })
Morten Krogh-Jespersen45d7a7b2020-11-02 08:31:09 +0100444]
445
Morten Krogh-Jespersenf8e77032020-11-09 23:44:58 +0100446
Morten Krogh-Jespersendfeb0e32020-11-04 14:55:55 +0100447def remove_print_lines(file):
448 with open(file) as f:
449 lines = f.readlines()
450 with open(file, 'w') as f:
451 for line in lines:
452 if '-printconfiguration' not in line:
453 f.write(line)
454
455
Morten Krogh-Jespersen45d7a7b2020-11-02 08:31:09 +0100456def download_app(app_sha):
457 utils.DownloadFromGoogleCloudStorage(app_sha)
458
459
Morten Krogh-Jespersencd55f812020-11-04 09:13:31 +0100460def is_logging_enabled_for(app, options):
461 if options.no_logging:
462 return False
463 if options.app_logging_filter and app.name not in options.app_logging_filter:
464 return False
465 return True
466
467
Morten Krogh-Jespersen45d7a7b2020-11-02 08:31:09 +0100468def is_minified_r8(shrinker):
469 return '-nolib' not in shrinker
470
471
472def is_full_r8(shrinker):
Morten Krogh-Jespersen270d0932020-11-11 11:05:57 +0100473 return '-full' in shrinker
Morten Krogh-Jespersen45d7a7b2020-11-02 08:31:09 +0100474
475
Morten Krogh-Jespersen51db2b02020-11-11 12:49:26 +0100476def version_is_built_jar(version):
477 return version != 'master' and version != 'source'
478
479
Morten Krogh-Jespersen45d7a7b2020-11-02 08:31:09 +0100480def compute_size_of_dex_files_in_package(path):
481 dex_size = 0
482 z = zipfile.ZipFile(path, 'r')
483 for filename in z.namelist():
484 if filename.endswith('.dex'):
485 dex_size += z.getinfo(filename).file_size
486 return dex_size
487
488
489def dump_for_app(app_dir, app):
490 return os.path.join(app_dir, app.dump_app)
491
492
Morten Krogh-Jespersen51a16352020-11-04 09:31:15 +0100493def dump_test_for_app(app_dir, app):
494 return os.path.join(app_dir, app.dump_test)
495
496
Morten Krogh-Jespersen51db2b02020-11-11 12:49:26 +0100497def get_r8_jar(options, temp_dir, shrinker):
498 if (options.version == 'source'):
499 return None
500 return os.path.join(
501 temp_dir, 'r8lib.jar' if is_minified_r8(shrinker) else 'r8.jar')
502
503
Morten Krogh-Jespersen45d7a7b2020-11-02 08:31:09 +0100504def get_results_for_app(app, options, temp_dir):
505 app_folder = app.folder if app.folder else app.name + "_" + app.revision
506 app_dir = os.path.join(utils.OPENSOURCE_DUMPS_DIR, app_folder)
507
508 if not os.path.exists(app_dir) and not options.golem:
509 # Download the app from google storage.
510 download_app(app_dir + ".tar.gz.sha1")
511
512 # Ensure that the dumps are in place
513 assert os.path.isfile(dump_for_app(app_dir, app)), "Could not find dump " \
514 "for app " + app.name
515
516 result = {}
517 result['status'] = 'success'
518 result_per_shrinker = build_app_with_shrinkers(
519 app, options, temp_dir, app_dir)
Christoffer Quist Adamsena9ff1cf2021-01-13 08:49:48 +0100520 for shrinker, shrinker_result in result_per_shrinker.items():
Morten Krogh-Jespersen45d7a7b2020-11-02 08:31:09 +0100521 result[shrinker] = shrinker_result
522 return result
523
524
525def build_app_with_shrinkers(app, options, temp_dir, app_dir):
526 result_per_shrinker = {}
527 for shrinker in options.shrinker:
528 results = []
529 build_app_and_run_with_shrinker(
530 app, options, temp_dir, app_dir, shrinker, results)
531 result_per_shrinker[shrinker] = results
532 if len(options.apps) > 1:
533 print('')
534 log_results_for_app(app, result_per_shrinker, options)
535 print('')
536
537 return result_per_shrinker
538
539
540def is_last_build(index, compilation_steps):
541 return index == compilation_steps - 1
542
543
544def build_app_and_run_with_shrinker(app, options, temp_dir, app_dir, shrinker,
545 results):
546 print('[{}] Building {} with {}'.format(
547 datetime.now().strftime("%H:%M:%S"),
548 app.name,
549 shrinker))
550 print('To compile locally: '
Morten Krogh-Jespersenf098b422020-11-11 13:53:52 +0100551 'tools/run_on_app_dump.py --shrinker {} --r8-compilation-steps {} '
Morten Krogh-Jespersen45d7a7b2020-11-02 08:31:09 +0100552 '--app {}'.format(
553 shrinker,
554 options.r8_compilation_steps,
555 app.name))
556 print('HINT: use --shrinker r8-nolib --no-build if you have a local R8.jar')
557 recomp_jar = None
558 status = 'success'
Morten Krogh-Jespersenee89b3a2020-11-13 11:59:43 +0100559 if options.r8_compilation_steps < 1:
560 return
561 compilation_steps = 1 if app.skip_recompilation else options.r8_compilation_steps
Morten Krogh-Jespersen45d7a7b2020-11-02 08:31:09 +0100562 for compilation_step in range(0, compilation_steps):
563 if status != 'success':
564 break
Morten Krogh-Jespersen51a16352020-11-04 09:31:15 +0100565 print('Compiling {} of {}'.format(compilation_step + 1, compilation_steps))
Morten Krogh-Jespersen45d7a7b2020-11-02 08:31:09 +0100566 result = {}
567 try:
568 start = time.time()
Morten Krogh-Jespersen51a16352020-11-04 09:31:15 +0100569 (app_jar, mapping, new_recomp_jar) = \
Morten Krogh-Jespersen45d7a7b2020-11-02 08:31:09 +0100570 build_app_with_shrinker(
571 app, options, temp_dir, app_dir, shrinker, compilation_step,
572 compilation_steps, recomp_jar)
573 end = time.time()
574 dex_size = compute_size_of_dex_files_in_package(app_jar)
575 result['build_status'] = 'success'
576 result['recompilation_status'] = 'success'
577 result['output_jar'] = app_jar
Morten Krogh-Jespersen51a16352020-11-04 09:31:15 +0100578 result['output_mapping'] = mapping
Morten Krogh-Jespersen45d7a7b2020-11-02 08:31:09 +0100579 result['dex_size'] = dex_size
580 result['duration'] = int((end - start) * 1000) # Wall time
581 if (new_recomp_jar is None
582 and not is_last_build(compilation_step, compilation_steps)):
583 result['recompilation_status'] = 'failed'
584 warn('Failed to build {} with {}'.format(app.name, shrinker))
Morten Krogh-Jespersen45d7a7b2020-11-02 08:31:09 +0100585 recomp_jar = new_recomp_jar
586 except Exception as e:
587 warn('Failed to build {} with {}'.format(app.name, shrinker))
588 if e:
589 print('Error: ' + str(e))
590 result['build_status'] = 'failed'
591 status = 'failed'
592
Morten Krogh-Jespersen51a16352020-11-04 09:31:15 +0100593 original_app_apk = os.path.join(app_dir, app.apk_app)
594 app_apk_destination = os.path.join(
595 temp_dir,"{}_{}.apk".format(app.id, compilation_step))
596
Morten Krogh-Jespersencd55f812020-11-04 09:13:31 +0100597 if result.get('build_status') == 'success' and options.monkey:
598 # Make a copy of the given APK, move the newly generated dex files into the
599 # copied APK, and then sign the APK.
Morten Krogh-Jespersencd55f812020-11-04 09:13:31 +0100600 apk_masseur.masseur(
601 original_app_apk, dex=app_jar, resources='META-INF/services/*',
Morten Krogh-Jespersen51a16352020-11-04 09:31:15 +0100602 out=app_apk_destination,
Morten Krogh-Jespersencd55f812020-11-04 09:13:31 +0100603 quiet=options.quiet, logging=is_logging_enabled_for(app, options),
604 keystore=options.keystore)
605
606 result['monkey_status'] = 'success' if adb.run_monkey(
Morten Krogh-Jespersen51a16352020-11-04 09:31:15 +0100607 app.id, options.emulator_id, app_apk_destination, options.monkey_events,
Morten Krogh-Jespersencd55f812020-11-04 09:13:31 +0100608 options.quiet, is_logging_enabled_for(app, options)) else 'failed'
609
Morten Krogh-Jespersen571cfe72020-11-09 23:44:03 +0100610 if (result.get('build_status') == 'success'
611 and options.run_tests and app.dump_test):
Morten Krogh-Jespersen51a16352020-11-04 09:31:15 +0100612 if not os.path.isfile(app_apk_destination):
613 apk_masseur.masseur(
614 original_app_apk, dex=app_jar, resources='META-INF/services/*',
615 out=app_apk_destination,
616 quiet=options.quiet, logging=is_logging_enabled_for(app, options),
617 keystore=options.keystore)
618
619 # Compile the tests with the mapping file.
620 test_jar = build_test_with_shrinker(
621 app, options, temp_dir, app_dir,shrinker, compilation_step,
622 result['output_mapping'])
Morten Krogh-Jespersen162b3452020-11-05 13:07:10 +0100623 if not test_jar:
624 result['instrumentation_test_status'] = 'compilation_failed'
625 else:
626 original_test_apk = os.path.join(app_dir, app.apk_test)
627 test_apk_destination = os.path.join(
628 temp_dir,"{}_{}.test.apk".format(app.id_test, compilation_step))
629 apk_masseur.masseur(
630 original_test_apk, dex=test_jar, resources='META-INF/services/*',
631 out=test_apk_destination,
632 quiet=options.quiet, logging=is_logging_enabled_for(app, options),
633 keystore=options.keystore)
634 result['instrumentation_test_status'] = 'success' if adb.run_instrumented(
635 app.id, app.id_test, options.emulator_id, app_apk_destination,
636 test_apk_destination, options.quiet,
637 is_logging_enabled_for(app, options)) else 'failed'
Morten Krogh-Jespersen51a16352020-11-04 09:31:15 +0100638
Morten Krogh-Jespersen45d7a7b2020-11-02 08:31:09 +0100639 results.append(result)
Morten Krogh-Jespersencd55f812020-11-04 09:13:31 +0100640 if result.get('recompilation_status') != 'success':
641 break
Morten Krogh-Jespersen45d7a7b2020-11-02 08:31:09 +0100642
643
644def build_app_with_shrinker(app, options, temp_dir, app_dir, shrinker,
645 compilation_step_index, compilation_steps,
646 prev_recomp_jar):
Morten Krogh-Jespersen45d7a7b2020-11-02 08:31:09 +0100647
648 args = AttrDict({
649 'dump': dump_for_app(app_dir, app),
Morten Krogh-Jespersen51db2b02020-11-11 12:49:26 +0100650 'r8_jar': get_r8_jar(options, temp_dir, shrinker),
Morten Krogh-Jespersen45d7a7b2020-11-02 08:31:09 +0100651 'ea': False if options.disable_assertions else True,
Morten Krogh-Jespersen51db2b02020-11-11 12:49:26 +0100652 'version': options.version,
Morten Krogh-Jespersen45d7a7b2020-11-02 08:31:09 +0100653 'compiler': 'r8full' if is_full_r8(shrinker) else 'r8',
654 'debug_agent': options.debug_agent,
655 'program_jar': prev_recomp_jar,
Morten Krogh-Jespersendfeb0e32020-11-04 14:55:55 +0100656 'nolib': not is_minified_r8(shrinker),
657 'config_file_consumer': remove_print_lines,
Morten Krogh-Jespersen43f3cea2020-11-12 17:09:51 +0100658 'properties': app.compiler_properties,
Morten Krogh-Jespersend86a81b2020-11-13 12:33:26 +0100659 'disable_desugared_lib': False,
Morten Krogh-Jespersen45d7a7b2020-11-02 08:31:09 +0100660 })
661
Morten Krogh-Jespersen45d7a7b2020-11-02 08:31:09 +0100662 app_jar = os.path.join(
663 temp_dir, '{}_{}_{}_dex_out.jar'.format(
664 app.name, shrinker, compilation_step_index))
Morten Krogh-Jespersen51a16352020-11-04 09:31:15 +0100665 app_mapping = os.path.join(
666 temp_dir, '{}_{}_{}_dex_out.jar.map'.format(
667 app.name, shrinker, compilation_step_index))
Morten Krogh-Jespersen45d7a7b2020-11-02 08:31:09 +0100668 recomp_jar = None
Morten Krogh-Jespersenc9d23462020-11-12 15:36:57 +0100669
670 with utils.TempDir() as compile_temp_dir:
671 compile_result = compiledump.run1(compile_temp_dir, args, [])
672 out_jar = os.path.join(compile_temp_dir, "out.jar")
673 out_mapping = os.path.join(compile_temp_dir, "out.jar.map")
674
675 if compile_result != 0 or not os.path.isfile(out_jar):
676 assert False, 'Compilation of {} failed'.format(dump_for_app(app_dir, app))
677 shutil.move(out_jar, app_jar)
678 shutil.move(out_mapping, app_mapping)
679
680 if compilation_step_index < compilation_steps - 1:
681 args['classfile'] = True
682 args['min_api'] = "10000"
Morten Krogh-Jespersend86a81b2020-11-13 12:33:26 +0100683 args['disable_desugared_lib'] = True
Morten Krogh-Jespersenc9d23462020-11-12 15:36:57 +0100684 compile_result = compiledump.run1(compile_temp_dir, args, [])
685 if compile_result == 0:
686 recomp_jar = os.path.join(
687 temp_dir, '{}_{}_{}_cf_out.jar'.format(
688 app.name, shrinker, compilation_step_index))
689 shutil.move(out_jar, recomp_jar)
Morten Krogh-Jespersen45d7a7b2020-11-02 08:31:09 +0100690
Morten Krogh-Jespersen51a16352020-11-04 09:31:15 +0100691 return (app_jar, app_mapping, recomp_jar)
692
Morten Krogh-Jespersen162b3452020-11-05 13:07:10 +0100693
Morten Krogh-Jespersen51a16352020-11-04 09:31:15 +0100694def build_test_with_shrinker(app, options, temp_dir, app_dir, shrinker,
695 compilation_step_index, mapping):
Morten Krogh-Jespersen51a16352020-11-04 09:31:15 +0100696
697 def rewrite_file(file):
Morten Krogh-Jespersendfeb0e32020-11-04 14:55:55 +0100698 remove_print_lines(file)
Morten Krogh-Jespersen51a16352020-11-04 09:31:15 +0100699 with open(file) as f:
700 lines = f.readlines()
701 with open(file, 'w') as f:
702 for line in lines:
703 if '-applymapping' not in line:
704 f.write(line + '\n')
705 f.write("-applymapping " + mapping + '\n')
706
707 args = AttrDict({
708 'dump': dump_test_for_app(app_dir, app),
Morten Krogh-Jespersen51db2b02020-11-11 12:49:26 +0100709 'r8_jar': get_r8_jar(options, temp_dir, shrinker),
Morten Krogh-Jespersen51a16352020-11-04 09:31:15 +0100710 'ea': False if options.disable_assertions else True,
Morten Krogh-Jespersen51db2b02020-11-11 12:49:26 +0100711 'version': options.version,
Morten Krogh-Jespersen51a16352020-11-04 09:31:15 +0100712 'compiler': 'r8full' if is_full_r8(shrinker) else 'r8',
713 'debug_agent': options.debug_agent,
714 'nolib': not is_minified_r8(shrinker),
715 # The config file will have an -applymapping reference to an old map.
716 # Update it to point to mapping file build in the compilation of the app.
717 'config_file_consumer': rewrite_file
718 })
719
Morten Krogh-Jespersen51a16352020-11-04 09:31:15 +0100720 test_jar = os.path.join(
721 temp_dir, '{}_{}_{}_test_out.jar'.format(
722 app.name, shrinker, compilation_step_index))
723
Morten Krogh-Jespersenc9d23462020-11-12 15:36:57 +0100724 with utils.TempDir() as compile_temp_dir:
725 compile_result = compiledump.run1(compile_temp_dir, args, [])
726 out_jar = os.path.join(compile_temp_dir, "out.jar")
727 if compile_result != 0 or not os.path.isfile(out_jar):
728 return None
729 shutil.move(out_jar, test_jar)
Morten Krogh-Jespersen51a16352020-11-04 09:31:15 +0100730
731 return test_jar
Morten Krogh-Jespersen45d7a7b2020-11-02 08:31:09 +0100732
733
734def log_results_for_apps(result_per_shrinker_per_app, options):
735 print('')
736 app_errors = 0
737 for (app, result_per_shrinker) in result_per_shrinker_per_app:
738 app_errors += (1 if log_results_for_app(app, result_per_shrinker, options)
739 else 0)
740 return app_errors
741
742
743def log_results_for_app(app, result_per_shrinker, options):
744 if options.print_dexsegments:
745 log_segments_for_app(app, result_per_shrinker, options)
746 return False
747 else:
748 return log_comparison_results_for_app(app, result_per_shrinker, options)
749
750
751def log_segments_for_app(app, result_per_shrinker, options):
752 for shrinker in SHRINKERS:
753 if shrinker not in result_per_shrinker:
754 continue
755 for result in result_per_shrinker.get(shrinker):
756 benchmark_name = '{}-{}'.format(options.print_dexsegments, app.name)
757 utils.print_dexsegments(benchmark_name, [result.get('output_jar')])
758 duration = result.get('duration')
759 print('%s-Total(RunTimeRaw): %s ms' % (benchmark_name, duration))
760 print('%s-Total(CodeSize): %s' % (benchmark_name, result.get('dex_size')))
761
762
763def percentage_diff_as_string(before, after):
764 if after < before:
765 return '-' + str(round((1.0 - after / before) * 100)) + '%'
766 else:
767 return '+' + str(round((after - before) / before * 100)) + '%'
768
769
770def log_comparison_results_for_app(app, result_per_shrinker, options):
771 print(app.name + ':')
772 app_error = False
773 if result_per_shrinker.get('status', 'success') != 'success':
774 error_message = result_per_shrinker.get('error_message')
775 print(' skipped ({})'.format(error_message))
776 return
777
778 proguard_result = result_per_shrinker.get('pg', {})
779 proguard_dex_size = float(proguard_result.get('dex_size', -1))
780
781 for shrinker in SHRINKERS:
782 if shrinker not in result_per_shrinker:
783 continue
784 compilation_index = 1
785 for result in result_per_shrinker.get(shrinker):
786 build_status = result.get('build_status')
787 if build_status != 'success' and build_status is not None:
788 app_error = True
789 warn(' {}-#{}: {}'.format(shrinker, compilation_index, build_status))
790 continue
791
792 print(' {}-#{}:'.format(shrinker, compilation_index))
793 dex_size = result.get('dex_size')
794 msg = ' dex size: {}'.format(dex_size)
Rudi Horn82e7d222020-11-17 11:22:39 +0000795 if options.print_runtimeraw:
796 print(' run time raw: {} ms'.format(result.get('duration')))
Morten Krogh-Jespersen45d7a7b2020-11-02 08:31:09 +0100797 if dex_size != proguard_dex_size and proguard_dex_size >= 0:
798 msg = '{} ({}, {})'.format(
799 msg, dex_size - proguard_dex_size,
800 percentage_diff_as_string(proguard_dex_size, dex_size))
801 success(msg) if dex_size < proguard_dex_size else warn(msg)
802 else:
803 print(msg)
804
Morten Krogh-Jespersencd55f812020-11-04 09:13:31 +0100805 if options.monkey:
806 monkey_status = result.get('monkey_status')
807 if monkey_status != 'success':
808 app_error = True
809 warn(' monkey: {}'.format(monkey_status))
810 else:
811 success(' monkey: {}'.format(monkey_status))
812
Morten Krogh-Jespersen51a16352020-11-04 09:31:15 +0100813 if options.run_tests and 'instrumentation_test_status' in result:
814 test_status = result.get('instrumentation_test_status')
815 if test_status != 'success':
816 warn(' instrumentation_tests: {}'.format(test_status))
817 else:
818 success(' instrumentation_tests: {}'.format(test_status))
819
Morten Krogh-Jespersen45d7a7b2020-11-02 08:31:09 +0100820 recompilation_status = result.get('recompilation_status', '')
821 if recompilation_status == 'failed':
822 app_error = True
823 warn(' recompilation {}-#{}: failed'.format(shrinker,
824 compilation_index))
825 continue
826
827 compilation_index += 1
828
829 return app_error
830
831
832def parse_options(argv):
833 result = optparse.OptionParser()
834 result.add_option('--app',
835 help='What app to run on',
836 choices=[app.name for app in APPS],
837 action='append')
Christoffer Quist Adamsen53e29472020-11-13 10:53:06 +0100838 result.add_option('--app-collection', '--app_collection',
839 help='What app collection to run',
840 choices=[collection.name for collection in APP_COLLECTIONS],
841 action='append')
Morten Krogh-Jespersen45d7a7b2020-11-02 08:31:09 +0100842 result.add_option('--bot',
843 help='Running on bot, use third_party dependency.',
844 default=False,
845 action='store_true')
846 result.add_option('--debug-agent',
847 help='Enable Java debug agent and suspend compilation '
848 '(default disabled)',
849 default=False,
850 action='store_true')
851 result.add_option('--disable-assertions', '--disable_assertions',
852 help='Disable assertions when compiling',
853 default=False,
854 action='store_true')
Morten Krogh-Jespersencd55f812020-11-04 09:13:31 +0100855 result.add_option('--emulator-id', '--emulator_id',
856 help='Id of the emulator to use',
857 default='emulator-5554')
Morten Krogh-Jespersen45d7a7b2020-11-02 08:31:09 +0100858 result.add_option('--golem',
859 help='Running on golem, do not download',
860 default=False,
861 action='store_true')
862 result.add_option('--hash',
863 help='The commit of R8 to use')
864 result.add_option('--keystore',
865 help='Path to app.keystore',
866 default=os.path.join(utils.TOOLS_DIR, 'debug.keystore'))
867 result.add_option('--keystore-password', '--keystore_password',
868 help='Password for app.keystore',
869 default='android')
870 result.add_option('--app-logging-filter', '--app_logging_filter',
871 help='The apps for which to turn on logging',
872 action='append')
873 result.add_option('--monkey',
874 help='Whether to install and run app(s) with monkey',
875 default=False,
876 action='store_true')
877 result.add_option('--monkey-events', '--monkey_events',
878 help='Number of events that the monkey should trigger',
879 default=250,
880 type=int)
881 result.add_option('--no-build', '--no_build',
882 help='Run without building ToT first (only when using ToT)',
883 default=False,
884 action='store_true')
885 result.add_option('--no-logging', '--no_logging',
886 help='Disable logging except for errors',
887 default=False,
888 action='store_true')
889 result.add_option('--print-dexsegments',
890 metavar='BENCHMARKNAME',
891 help='Print the sizes of individual dex segments as ' +
892 '\'<BENCHMARKNAME>-<APP>-<segment>(CodeSize): '
893 '<bytes>\'')
Rudi Horn82e7d222020-11-17 11:22:39 +0000894 result.add_option('--print-runtimeraw',
895 metavar='BENCHMARKNAME',
896 help='Print the line \'<BENCHMARKNAME>(RunTimeRaw):' +
897 ' <elapsed> ms\' at the end where <elapsed> is' +
898 ' the elapsed time in milliseconds.')
Morten Krogh-Jespersen45d7a7b2020-11-02 08:31:09 +0100899 result.add_option('--quiet',
900 help='Disable verbose logging',
901 default=False,
902 action='store_true')
903 result.add_option('--r8-compilation-steps', '--r8_compilation_steps',
904 help='Number of times R8 should be run on each app',
905 default=2,
906 type=int)
907 result.add_option('--run-tests', '--run_tests',
908 help='Whether to run instrumentation tests',
909 default=False,
910 action='store_true')
911 result.add_option('--sign-apks', '--sign_apks',
912 help='Whether the APKs should be signed',
913 default=False,
914 action='store_true')
915 result.add_option('--shrinker',
916 help='The shrinkers to use (by default, all are run)',
917 action='append')
918 result.add_option('--version',
Morten Krogh-Jespersen47764032020-11-11 15:09:39 +0100919 default='master',
Morten Krogh-Jespersen45d7a7b2020-11-02 08:31:09 +0100920 help='The version of R8 to use (e.g., 1.4.51)')
921 (options, args) = result.parse_args(argv)
Christoffer Quist Adamsen53e29472020-11-13 10:53:06 +0100922
923 if options.app or options.app_collection:
924 if not options.app:
925 options.app = []
926 if not options.app_collection:
927 options.app_collection = []
928 options.apps = [
929 app
930 for app in APPS
931 if app.name in options.app
932 or any(collection in options.app_collection
933 for collection in app.collections)]
Morten Krogh-Jespersen45d7a7b2020-11-02 08:31:09 +0100934 del options.app
Christoffer Quist Adamsen53e29472020-11-13 10:53:06 +0100935 del options.app_collection
Morten Krogh-Jespersen45d7a7b2020-11-02 08:31:09 +0100936 else:
937 options.apps = APPS
Christoffer Quist Adamsen53e29472020-11-13 10:53:06 +0100938
Morten Krogh-Jespersen45d7a7b2020-11-02 08:31:09 +0100939 if options.app_logging_filter:
940 for app_name in options.app_logging_filter:
941 assert any(app.name == app_name for app in options.apps)
942 if options.shrinker:
943 for shrinker in options.shrinker:
Christoffer Quist Adamsena9ff1cf2021-01-13 08:49:48 +0100944 assert shrinker in SHRINKERS, (
945 'Shrinker must be one of %s' % ', '.join(SHRINKERS))
Morten Krogh-Jespersen45d7a7b2020-11-02 08:31:09 +0100946 else:
947 options.shrinker = [shrinker for shrinker in SHRINKERS]
948
Morten Krogh-Jespersen51db2b02020-11-11 12:49:26 +0100949 if options.hash or version_is_built_jar(options.version):
Morten Krogh-Jespersen45d7a7b2020-11-02 08:31:09 +0100950 # No need to build R8 if a specific version should be used.
951 options.no_build = True
952 if 'r8-nolib' in options.shrinker:
953 warn('Skipping shrinker r8-nolib because a specific version '
954 + 'of r8 was specified')
955 options.shrinker.remove('r8-nolib')
956 if 'r8-nolib-full' in options.shrinker:
957 warn('Skipping shrinker r8-nolib-full because a specific version '
958 + 'of r8 was specified')
959 options.shrinker.remove('r8-nolib-full')
960 return (options, args)
961
962
963def main(argv):
964 (options, args) = parse_options(argv)
965
966 if options.bot:
967 options.no_logging = True
968 options.shrinker = ['r8', 'r8-full']
969 print(options.shrinker)
970
971 if options.golem:
972 golem.link_third_party()
973 options.disable_assertions = True
974 options.no_build = True
975 options.r8_compilation_steps = 1
976 options.quiet = True
977 options.no_logging = True
978
Morten Krogh-Jespersen45d7a7b2020-11-02 08:31:09 +0100979 with utils.TempDir() as temp_dir:
980 if options.hash:
981 # Download r8-<hash>.jar from
982 # https://storage.googleapis.com/r8-releases/raw/.
983 target = 'r8-{}.jar'.format(options.hash)
984 update_prebuilds_in_android.download_hash(
985 temp_dir, 'com/android/tools/r8/' + options.hash, target)
986 as_utils.MoveFile(
987 os.path.join(temp_dir, target), os.path.join(temp_dir, 'r8lib.jar'),
988 quiet=options.quiet)
Morten Krogh-Jespersen51db2b02020-11-11 12:49:26 +0100989 elif version_is_built_jar(options.version):
990 # Download r8-<version>.jar from
991 # https://storage.googleapis.com/r8-releases/raw/.
992 target = 'r8-{}.jar'.format(options.version)
993 update_prebuilds_in_android.download_version(
994 temp_dir, 'com/android/tools/r8/' + options.version, target)
995 as_utils.MoveFile(
996 os.path.join(temp_dir, target), os.path.join(temp_dir, 'r8lib.jar'),
997 quiet=options.quiet)
998 elif options.version == 'master':
Morten Krogh-Jespersen45d7a7b2020-11-02 08:31:09 +0100999 if not (options.no_build or options.golem):
1000 gradle.RunGradle(['r8', '-Pno_internal'])
1001 build_r8lib = False
1002 for shrinker in options.shrinker:
1003 if is_minified_r8(shrinker):
1004 build_r8lib = True
1005 if build_r8lib:
1006 gradle.RunGradle(['r8lib', '-Pno_internal'])
1007 # Make a copy of r8.jar and r8lib.jar such that they stay the same for
1008 # the entire execution of this script.
1009 if 'r8-nolib' in options.shrinker or 'r8-nolib-full' in options.shrinker:
1010 assert os.path.isfile(utils.R8_JAR), 'Cannot build without r8.jar'
1011 shutil.copyfile(utils.R8_JAR, os.path.join(temp_dir, 'r8.jar'))
1012 if 'r8' in options.shrinker or 'r8-full' in options.shrinker:
1013 assert os.path.isfile(utils.R8LIB_JAR), 'Cannot build without r8lib.jar'
1014 shutil.copyfile(utils.R8LIB_JAR, os.path.join(temp_dir, 'r8lib.jar'))
1015
1016 result_per_shrinker_per_app = []
1017 for app in options.apps:
1018 if app.skip:
1019 continue
1020 result_per_shrinker_per_app.append(
1021 (app, get_results_for_app(app, options, temp_dir)))
Morten Krogh-Jespersenf098b422020-11-11 13:53:52 +01001022 errors = log_results_for_apps(result_per_shrinker_per_app, options)
1023 if errors > 0:
1024 dest = 'gs://r8-test-results/r8-libs/' + str(int(time.time()))
1025 utils.upload_file_to_cloud_storage(os.path.join(temp_dir, 'r8lib.jar'), dest)
1026 print('R8lib saved to %s' % dest)
1027 return errors
Morten Krogh-Jespersen45d7a7b2020-11-02 08:31:09 +01001028
1029
1030def success(message):
1031 CGREEN = '\033[32m'
1032 CEND = '\033[0m'
1033 print(CGREEN + message + CEND)
1034
1035
1036def warn(message):
1037 CRED = '\033[91m'
1038 CEND = '\033[0m'
1039 print(CRED + message + CEND)
1040
1041
1042if __name__ == '__main__':
1043 sys.exit(main(sys.argv[1:]))