blob: d90ea426599dfb40083f9ce53a08d057f2266b76 [file] [log] [blame]
Ian Zernydcb172e2022-02-22 15:36:45 +01001#!/usr/bin/env python3
Mads Agera9745612017-11-02 12:42:15 +01002# Copyright (c) 2017, 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.
5
Mads Agera9745612017-11-02 12:42:15 +01006import argparse
Mads Agera4911eb2017-11-22 13:19:36 +01007import hashlib
Søren Gjessea70d3bd2019-09-24 15:07:00 +02008import jdk
Mads Agera9745612017-11-02 12:42:15 +01009import subprocess
10import sys
Søren Gjesse17fc67d2019-12-04 14:50:17 +010011import zipfile
Clément Béra031d83d2023-10-03 10:03:05 +020012from os import makedirs
13from os.path import basename
14from os.path import join
15from shutil import copyfile
16from shutil import make_archive
17from shutil import move
18from string import Template
19
20import gradle
21import utils
Mads Agera9745612017-11-02 12:42:15 +010022
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +020023LICENSETEMPLATE = Template("""
Søren Gjessec425e6a2019-06-28 11:41:14 +020024 <license>
25 <name>$name</name>
26 <url>$url</url>
27 <distribution>repo</distribution>
28 </license>""")
29
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +020030R8_POMTEMPLATE = Template("""<project
Mads Agera9745612017-11-02 12:42:15 +010031 xmlns="http://maven.apache.org/POM/4.0.0"
32 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
33 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
34 <modelVersion>4.0.0</modelVersion>
35 <groupId>com.android.tools</groupId>
36 <artifactId>r8</artifactId>
37 <version>$version</version>
38 <name>D8 dexer and R8 shrinker</name>
39 <description>
40 D8 dexer and R8 shrinker.
41 </description>
42 <url>http://r8.googlesource.com/r8</url>
43 <inceptionYear>2016</inceptionYear>
44 <licenses>
45 <license>
46 <name>BSD-3-Clause</name>
47 <url>https://opensource.org/licenses/BSD-3-Clause</url>
48 <distribution>repo</distribution>
Søren Gjessec425e6a2019-06-28 11:41:14 +020049 </license>$library_licenses
Mads Ager73460192017-11-08 10:02:50 +010050 </licenses>
Rico Windd6323ad2023-09-14 09:33:59 +020051 <dependencies>
Mads Agera4911eb2017-11-22 13:19:36 +010052 </dependencies>
Mads Agera9745612017-11-02 12:42:15 +010053 <developers>
54 <developer>
55 <name>The Android Open Source Project</name>
56 </developer>
57 </developers>
58 <scm>
59 <connection>
60 https://r8.googlesource.com/r8.git
61 </connection>
62 <url>
63 https://r8.googlesource.com/r8
64 </url>
65 </scm>
66</project>
67""")
68
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +020069DESUGAR_CONFIGUATION_POMTEMPLATE = Template("""<project
Søren Gjesse6e5e5842019-09-03 08:48:30 +020070 xmlns="http://maven.apache.org/POM/4.0.0"
71 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
72 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
73 <modelVersion>4.0.0</modelVersion>
74 <groupId>com.android.tools</groupId>
Søren Gjesse2b047692022-08-19 16:34:38 +020075 <artifactId>$artifactId</artifactId>
Søren Gjesse6e5e5842019-09-03 08:48:30 +020076 <version>$version</version>
77 <name>D8 configuration to desugar desugar_jdk_libs</name>
78 <description>
79 D8 configuration to desugar desugar_jdk_libs.
80 </description>
81 <url>http://r8.googlesource.com/r8</url>
82 <inceptionYear>2019</inceptionYear>
83 <licenses>
84 <license>
85 <name>BSD-3-Clause</name>
86 <url>https://opensource.org/licenses/BSD-3-Clause</url>
87 <distribution>repo</distribution>
88 </license>
89 </licenses>
Søren Gjesse6e5e5842019-09-03 08:48:30 +020090 <developers>
91 <developer>
92 <name>The Android Open Source Project</name>
93 </developer>
94 </developers>
95 <scm>
96 <connection>
97 https://r8.googlesource.com/r8.git
98 </connection>
99 <url>
100 https://r8.googlesource.com/r8
101 </url>
102 </scm>
103</project>
104""")
105
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200106
Mads Agera9745612017-11-02 12:42:15 +0100107def parse_options(argv):
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200108 result = argparse.ArgumentParser()
109 result.add_argument('--out', help='The zip file to output')
110 group = result.add_mutually_exclusive_group()
111 group.add_argument(
112 '--desugar-configuration',
113 action='store_true',
114 help='Build desugar library configuration (original JDK-8)')
115 group.add_argument(
116 '--desugar-configuration-jdk8',
117 action='store_true',
118 help='Build desugar library configuration (original JDK-8)')
119 group.add_argument(
120 '--desugar-configuration-jdk11-legacy',
121 action='store_true',
122 help='Build desugar library configuration (JDK-11 legacy)')
123 group.add_argument(
124 '--desugar-configuration-jdk11-minimal',
125 action='store_true',
126 help='Build desugar library configuration (JDK-11 minimal)')
127 group.add_argument('--desugar-configuration-jdk11',
128 action='store_true',
129 help='Build desugar library configuration (JDK-11)')
130 group.add_argument('--desugar-configuration-jdk11-nio',
131 action='store_true',
132 help='Build desugar library configuration (JDK-11 nio)')
133 return result.parse_args(argv)
134
Mads Agera9745612017-11-02 12:42:15 +0100135
Mads Agera4911eb2017-11-22 13:19:36 +0100136def determine_version():
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200137 version_file = join(utils.SRC_ROOT, 'com', 'android', 'tools', 'r8',
138 'Version.java')
139 with open(version_file, 'r') as file:
140 for line in file:
141 if 'final String LABEL ' in line:
142 result = line[line.find('"') + 1:]
143 result = result[:result.find('"')]
144 return result
145 raise Exception('Unable to determine version.')
146
Mads Agera9745612017-11-02 12:42:15 +0100147
148def generate_library_licenses():
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200149 artifact_prefix = '- artifact: '
150 license_prefix = 'license: '
151 licenses = []
152 license_url_prefix = 'licenseUrl: '
153 license_urls = []
154 # The ./LIBRARY-LICENSE file is a simple yaml file, which for each dependency
155 # has the following information:
156 #
157 # - artifact: <maven artifact> // in the form <group-id>:<artifact-id>:+
158 # name: <name of dependency>
159 # copyrightHolder: <name of copyright holder>
160 # license: <license name>
161 # licenseUrl: <url to license test>
162 #
163 # E.g. for Guava:
164 #
165 # - artifact: com.google.guava:guava:+
166 # name: Guava Google Core Libraries for Java
167 # copyrightHolder: The Guava Authors
168 # license: The Apache Software License, Version 2.0
169 # licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
170 #
171 # This file should always be up to date as the build will fail if it
172 # is does not have information for all dependencies.
173 with open('LIBRARY-LICENSE', 'r') as file:
Søren Gjessec425e6a2019-06-28 11:41:14 +0200174 name = None
175 url = None
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200176 for line in file:
177 trimmed = line.strip()
178 # Collect license name and url for each artifact. They must come in
179 # pairs for each artifact.
180 if trimmed.startswith(artifact_prefix):
181 assert not name
182 assert not url
183 if trimmed.startswith(license_prefix):
184 name = trimmed[len(license_prefix):]
185 if trimmed.startswith(license_url_prefix):
186 url = trimmed[len(license_url_prefix):]
187 # Licenses come in name/url pairs. When both are present add pair
188 # to collected licenses if either name or url has not been recorded yet,
189 # as some licenses with slightly different names point to the same url.
190 if name and url:
191 if (not name in licenses) or (not url in license_urls):
192 licenses.append(name)
193 license_urls.append(url)
194 name = None
195 url = None
196 assert len(licenses) == len(license_urls)
197 result = ''
198 for i in range(len(licenses)):
199 name = licenses[i]
200 url = license_urls[i]
201 result += LICENSETEMPLATE.substitute(name=name, url=url)
202 return result
203
Mads Agera9745612017-11-02 12:42:15 +0100204
Rico Wind257044c2019-11-22 08:21:21 +0100205def write_default_r8_pom_file(pom_file, version):
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200206 write_pom_file(R8_POMTEMPLATE, pom_file, version)
Rico Wind257044c2019-11-22 08:21:21 +0100207
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200208
209def write_pom_file(template,
210 pom_file,
211 version,
212 artifact_id=None,
213 library_licenses=''):
214 version_pom = (template.substitute(artifactId=artifact_id,
215 version=version,
216 library_licenses=library_licenses)
217 if artifact_id else template.substitute(
218 version=version, library_licenses=library_licenses))
219 with open(pom_file, 'w') as file:
220 file.write(version_pom)
221
Mads Agera9745612017-11-02 12:42:15 +0100222
223def hash_for(file, hash):
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200224 with open(file, 'rb') as f:
225 while True:
226 # Read chunks of 1MB
227 chunk = f.read(2**20)
228 if not chunk:
229 break
230 hash.update(chunk)
231 return hash.hexdigest()
232
Mads Agera9745612017-11-02 12:42:15 +0100233
234def write_md5_for(file):
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200235 hexdigest = hash_for(file, hashlib.md5())
236 with (open(file + '.md5', 'w')) as file:
237 file.write(hexdigest)
238
Mads Agera9745612017-11-02 12:42:15 +0100239
240def write_sha1_for(file):
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200241 hexdigest = hash_for(file, hashlib.sha1())
242 with (open(file + '.sha1', 'w')) as file:
243 file.write(hexdigest)
244
Mads Agera9745612017-11-02 12:42:15 +0100245
Søren Gjesse6e5e5842019-09-03 08:48:30 +0200246def generate_maven_zip(name, version, pom_file, jar_file, out):
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200247 with utils.TempDir() as tmp_dir:
248 # Create the base maven version directory
249 version_dir = join(tmp_dir, utils.get_maven_path(name, version))
250 makedirs(version_dir)
251 # Write the pom file.
252 pom_file_location = join(version_dir, name + '-' + version + '.pom')
253 copyfile(pom_file, pom_file_location)
254 # Write the jar file.
255 jar_file_location = join(version_dir, name + '-' + version + '.jar')
256 copyfile(jar_file, jar_file_location)
257 # Create check sums.
258 write_md5_for(jar_file_location)
259 write_md5_for(pom_file_location)
260 write_sha1_for(jar_file_location)
261 write_sha1_for(pom_file_location)
262 # Zip it up - make_archive will append zip to the file, so remove.
263 assert out.endswith('.zip')
264 base_no_zip = out[0:len(out) - 4]
265 make_archive(base_no_zip, 'zip', tmp_dir)
266
Rico Wind8fc8bfa2019-03-22 09:57:36 +0100267
Rico Wind28f3a0e2023-10-12 14:24:07 +0200268def generate_r8_maven_zip(out, version_file=None, skip_gradle_build=False):
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200269 if not skip_gradle_build:
270 gradle.RunGradle([utils.GRADLE_TASK_R8LIB, '-Pno_internal'])
271 version = determine_version()
272 with utils.TempDir() as tmp_dir:
273 file_copy = join(tmp_dir, 'copy_of_jar.jar')
274 copyfile(utils.R8LIB_JAR, file_copy)
Rico Windcdc39b62022-04-08 12:37:57 +0200275
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200276 if version_file:
277 with zipfile.ZipFile(file_copy, 'a') as zip:
278 zip.write(version_file, basename(version_file))
Rico Windcdc39b62022-04-08 12:37:57 +0200279
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200280 # Generate the pom file.
281 pom_file = join(tmp_dir, 'r8.pom')
282 write_pom_file(R8_POMTEMPLATE,
283 pom_file,
284 version,
285 library_licenses=generate_library_licenses())
286 # Write the maven zip file.
287 generate_maven_zip('r8', version, pom_file, file_copy, out)
288
Søren Gjesse6e5e5842019-09-03 08:48:30 +0200289
290# Write the desugaring configuration of a jar file with the following content:
Søren Gjesse17fc67d2019-12-04 14:50:17 +0100291# java/
292# util/
293# <java.util conversions classes>
294# time/
295# <java.time conversions classes>
296# META-INF/
297# desugar/
298# d8/
Søren Gjesse6e5e5842019-09-03 08:48:30 +0200299# desugar.json
Søren Gjesse17fc67d2019-12-04 14:50:17 +0100300# lint/
301# <lint files>
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200302def generate_jar_with_desugar_configuration(configuration, implementation,
303 conversions, destination):
304 with utils.TempDir() as tmp_dir:
305 # Add conversion classes.
306 with zipfile.ZipFile(conversions, 'r') as conversions_zip:
307 conversions_zip.extractall(tmp_dir)
Søren Gjesse17fc67d2019-12-04 14:50:17 +0100308
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200309 # Add configuration.
310 configuration_dir = join(tmp_dir, 'META-INF', 'desugar', 'd8')
311 makedirs(configuration_dir)
312 copyfile(configuration, join(configuration_dir, 'desugar.json'))
Søren Gjessea70d3bd2019-09-24 15:07:00 +0200313
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200314 # Add lint configuartion.
315 lint_dir = join(configuration_dir, 'lint')
316 makedirs(lint_dir)
317 cmd = [
318 jdk.GetJavaExecutable(), '-cp', utils.R8_JAR,
319 'com.android.tools.r8.ir.desugar.desugaredlibrary.lint.GenerateDesugaredLibraryLintFiles',
320 configuration, implementation, lint_dir,
321 utils.get_android_jar(34)
322 ]
323 utils.PrintCmd(cmd)
324 subprocess.check_call(cmd)
325
326 # Add LICENSE file.
327 copyfile(join(utils.REPO_ROOT, 'LICENSE'), join(tmp_dir, 'LICENSE'))
328
329 make_archive(destination, 'zip', tmp_dir)
330 move(destination + '.zip', destination)
331
332
333def convert_desugar_configuration(configuration, conversions, implementation,
334 machine_configuration):
Søren Gjessea70d3bd2019-09-24 15:07:00 +0200335 cmd = [
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200336 jdk.GetJavaExecutable(), '-cp', utils.R8_JAR,
337 'com.android.tools.r8.ir.desugar.desugaredlibrary.specificationconversion.DesugaredLibraryConverter',
338 configuration, implementation, conversions,
339 utils.get_android_jar(33), machine_configuration
340 ]
Søren Gjessea70d3bd2019-09-24 15:07:00 +0200341 subprocess.check_call(cmd)
342
Søren Gjesse2b047692022-08-19 16:34:38 +0200343
Søren Gjesse6e5e5842019-09-03 08:48:30 +0200344# Generate the maven zip for the configuration to desugar desugar_jdk_libs.
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200345def generate_desugar_configuration_maven_zip(out, configuration, implementation,
346 conversions):
347 with utils.TempDir() as tmp_dir:
348 (name, version) = utils.desugar_configuration_name_and_version(
349 configuration, False)
Søren Gjesse2b047692022-08-19 16:34:38 +0200350
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200351 if (not version.startswith("1.")):
352 machine_configuration = join(tmp_dir, "machine.json")
353 convert_desugar_configuration(configuration, conversions,
354 implementation, machine_configuration)
355 configuration = machine_configuration
Søren Gjesse2b047692022-08-19 16:34:38 +0200356
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200357 # Generate the pom file.
358 pom_file = join(tmp_dir, 'desugar_configuration.pom')
359 write_pom_file(DESUGAR_CONFIGUATION_POMTEMPLATE,
360 pom_file,
361 version,
362 artifact_id=name)
363 # Generate the jar with the configuration file.
364 jar_file = join(tmp_dir, 'desugar_configuration.jar')
365 generate_jar_with_desugar_configuration(configuration, implementation,
366 conversions, jar_file)
367 # Write the maven zip file.
368 generate_maven_zip(name, version, pom_file, jar_file, out)
369
Søren Gjesse6e5e5842019-09-03 08:48:30 +0200370
Rico Wind8fc8bfa2019-03-22 09:57:36 +0100371def main(argv):
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200372 options = parse_options(argv)
373 if options.out == None:
374 raise Exception('Need to supply output zip with --out.')
375 if options.desugar_configuration or options.desugar_configuration_jdk8:
376 generate_desugar_configuration_maven_zip(
377 options.out, utils.DESUGAR_CONFIGURATION,
378 utils.DESUGAR_IMPLEMENTATION,
379 utils.LIBRARY_DESUGAR_CONVERSIONS_LEGACY_ZIP)
380 elif options.desugar_configuration_jdk11_legacy:
381 generate_desugar_configuration_maven_zip(
382 options.out, utils.DESUGAR_CONFIGURATION_JDK11_LEGACY,
383 utils.DESUGAR_IMPLEMENTATION_JDK11,
384 utils.LIBRARY_DESUGAR_CONVERSIONS_LEGACY_ZIP)
385 elif options.desugar_configuration_jdk11_minimal:
386 generate_desugar_configuration_maven_zip(
387 options.out, utils.DESUGAR_CONFIGURATION_JDK11_MINIMAL,
388 utils.DESUGAR_IMPLEMENTATION_JDK11,
389 utils.LIBRARY_DESUGAR_CONVERSIONS_ZIP)
390 elif options.desugar_configuration_jdk11:
391 generate_desugar_configuration_maven_zip(
392 options.out, utils.DESUGAR_CONFIGURATION_JDK11,
393 utils.DESUGAR_IMPLEMENTATION_JDK11,
394 utils.LIBRARY_DESUGAR_CONVERSIONS_ZIP)
395 elif options.desugar_configuration_jdk11_nio:
396 generate_desugar_configuration_maven_zip(
397 options.out, utils.DESUGAR_CONFIGURATION_JDK11_NIO,
398 utils.DESUGAR_IMPLEMENTATION_JDK11,
399 utils.LIBRARY_DESUGAR_CONVERSIONS_ZIP)
400 else:
401 generate_r8_maven_zip(options.out)
402
Mads Agera9745612017-11-02 12:42:15 +0100403
404if __name__ == "__main__":
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200405 exit(main(sys.argv[1:]))