blob: 931fe23f778b84c7a6ffbba05e030cb21ed3b37a [file] [log] [blame]
Ian Zernydcb172e2022-02-22 15:36:45 +01001#!/usr/bin/env python3
Søren Gjesse1c115b52019-08-14 12:43:57 +02002# Copyright (c) 2019, 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
6# This script is designed to run on a buildbot to build from the source
7# of https://github.com/google/desugar_jdk_libs and publish to the
8# r8-release Cloud Storage Bucket.
9#
10# These files are uploaded:
11#
12# raw/desugar_jdk_libs/<VERSION>/desugar_jdk_libs.jar
13# raw/desugar_jdk_libs/<VERSION>/desugar_jdk_libs.zip
14# raw/com/android/tools/desugar_jdk_libs/<VERSION>/desugar_jdk_libs-<VERSION>.jar
15#
16# The first two are the raw jar file and the maven compatible zip file. The
17# third is the raw jar file placed and named so that the URL
Rico Wind70d614f2020-01-31 08:45:21 +010018# https://storage.googleapis.com/r8-releases/raw can be treated as a maven
Søren Gjesse1c115b52019-08-14 12:43:57 +020019# repository to fetch the artifact com.android.tools:desugar_jdk_libs:1.0.0
20
21import archive
Søren Gjesse2b047692022-08-19 16:34:38 +020022import defines
Søren Gjesse1c115b52019-08-14 12:43:57 +020023import git_utils
Søren Gjesse2b047692022-08-19 16:34:38 +020024import gradle
25import hashlib
Clément Béra54696f72021-11-16 09:27:22 +000026import jdk
Søren Gjesse1c115b52019-08-14 12:43:57 +020027import optparse
28import os
29import re
30import shutil
31import subprocess
32import sys
33import utils
Søren Gjesse2b047692022-08-19 16:34:38 +020034import zipfile
Søren Gjesse1c115b52019-08-14 12:43:57 +020035
Søren Gjesse5614efc2022-06-24 12:25:33 +020036VERSION_FILE_JDK8 = 'VERSION.txt'
Søren Gjesse2b047692022-08-19 16:34:38 +020037VERSION_FILE_JDK11_LEGACY = 'VERSION_JDK11_LEGACY.txt'
38VERSION_FILE_JDK11_MINIMAL = 'VERSION_JDK11_MINIMAL.txt'
Søren Gjesse5614efc2022-06-24 12:25:33 +020039VERSION_FILE_JDK11 = 'VERSION_JDK11.txt'
Søren Gjesse2b047692022-08-19 16:34:38 +020040VERSION_FILE_JDK11_NIO = 'VERSION_JDK11_NIO.txt'
41
42VERSION_MAP = {
43 'jdk8': VERSION_FILE_JDK8,
44 'jdk11_legacy': VERSION_FILE_JDK11_LEGACY,
45 'jdk11_minimal': VERSION_FILE_JDK11_MINIMAL,
46 'jdk11': VERSION_FILE_JDK11,
47 'jdk11_nio': VERSION_FILE_JDK11_NIO
48}
49
50GITHUB_REPRO = 'desugar_jdk_libs'
51
52BASE_LIBRARY_NAME = 'desugar_jdk_libs'
53
54LIBRARY_NAME_MAP = {
55 'jdk8': BASE_LIBRARY_NAME,
56 'jdk11_legacy': BASE_LIBRARY_NAME,
57 'jdk11_minimal': BASE_LIBRARY_NAME + '_minimal',
58 'jdk11': BASE_LIBRARY_NAME,
59 'jdk11_nio': BASE_LIBRARY_NAME + '_nio'
60}
61
62MAVEN_RELEASE_TARGET_MAP = {
63 'jdk8': 'maven_release',
64 'jdk11_legacy': 'maven_release_jdk11_legacy',
65 'jdk11_minimal': 'maven_release_jdk11_minimal',
66 'jdk11': 'maven_release_jdk11',
67 'jdk11_nio': 'maven_release_jdk11_nio'
68}
69
70MAVEN_RELEASE_ZIP = {
71 'jdk8': BASE_LIBRARY_NAME + '.zip',
72 'jdk11_legacy': BASE_LIBRARY_NAME + '_jdk11_legacy.zip',
73 'jdk11_minimal': BASE_LIBRARY_NAME + '_jdk11_minimal.zip',
74 'jdk11': BASE_LIBRARY_NAME + '_jdk11.zip',
75 'jdk11_nio': BASE_LIBRARY_NAME + '_jdk11_nio.zip'
76}
77
Søren Gjesse85c37922022-09-01 16:58:07 +020078DESUGAR_JDK_LIBS_HASH_FILE = os.path.join(
79 defines.THIRD_PARTY, 'openjdk', 'desugar_jdk_libs_11', 'desugar_jdk_libs_hash')
80
Søren Gjesse1c115b52019-08-14 12:43:57 +020081
82def ParseOptions(argv):
83 result = optparse.OptionParser()
Søren Gjesse124c4c42021-10-18 12:37:41 +020084 result.add_option('--variant',
Søren Gjesse2b047692022-08-19 16:34:38 +020085 help="Variant(s) to build",
86 metavar=('<variants(s)>'),
87 choices=['jdk8', 'jdk11_legacy', 'jdk11_minimal', 'jdk11', 'jdk11_nio'],
88 default=[],
89 action='append')
Søren Gjesse1c115b52019-08-14 12:43:57 +020090 result.add_option('--dry-run', '--dry_run',
91 help='Running on bot, use third_party dependency.',
92 default=False,
93 action='store_true')
94 result.add_option('--dry-run-output', '--dry_run_output',
95 help='Output directory for dry run.',
96 type="string", action="store")
97 result.add_option('--github-account', '--github_account',
98 help='GitHub account to clone from.',
99 default="google",
100 type="string", action="store")
Søren Gjesse53d14482021-02-10 16:53:38 +0100101 result.add_option('--build_only', '--build-only',
102 help='Build desugared library without archiving.',
103 type="string", action="store")
Søren Gjesse1c115b52019-08-14 12:43:57 +0200104 (options, args) = result.parse_args(argv)
105 return (options, args)
106
107
Søren Gjesse07b6aea2019-12-12 11:11:58 +0100108def GetVersion(version_file_name):
109 with open(version_file_name, 'r') as version_file:
Søren Gjessef298e7a2019-12-06 09:57:36 +0100110 lines = [line.strip() for line in version_file.readlines()]
111 lines = [line for line in lines if not line.startswith('#')]
Søren Gjesse1c115b52019-08-14 12:43:57 +0200112 if len(lines) != 1:
113 raise Exception('Version file '
Søren Gjesse07b6aea2019-12-12 11:11:58 +0100114 + version_file + ' is expected to have exactly one line')
Søren Gjesse1c115b52019-08-14 12:43:57 +0200115 version = lines[0].strip()
Søren Gjesse1e171532019-09-03 09:44:22 +0200116 utils.check_basic_semver_version(
Søren Gjesse1c091482022-03-23 10:36:55 +0100117 version, 'in version file ' + version_file_name, allowPrerelease = True)
Søren Gjesse1c115b52019-08-14 12:43:57 +0200118 return version
119
120
Rico Wind1b52acf2021-03-21 12:36:55 +0100121def Upload(options, file_name, storage_path, destination, is_main):
Søren Gjesse1c115b52019-08-14 12:43:57 +0200122 print('Uploading %s to %s' % (file_name, destination))
123 if options.dry_run:
124 if options.dry_run_output:
125 dry_run_destination = \
126 os.path.join(options.dry_run_output, os.path.basename(file_name))
127 print('Dry run, not actually uploading. Copying to '
128 + dry_run_destination)
129 shutil.copyfile(file_name, dry_run_destination)
130 else:
131 print('Dry run, not actually uploading')
132 else:
133 utils.upload_file_to_cloud_storage(file_name, destination)
134 print('File available at: %s' %
Rico Wind70d614f2020-01-31 08:45:21 +0100135 destination.replace('gs://', 'https://storage.googleapis.com/', 1))
Søren Gjesse1c115b52019-08-14 12:43:57 +0200136
Søren Gjesse85c37922022-09-01 16:58:07 +0200137def CloneDesugaredLibrary(github_account, checkout_dir, desugar_jdk_libs_hash):
Søren Gjesse53d14482021-02-10 16:53:38 +0100138 git_utils.GitClone(
139 'https://github.com/'
Søren Gjesse2b047692022-08-19 16:34:38 +0200140 + github_account + '/' + GITHUB_REPRO, checkout_dir)
Søren Gjesse85c37922022-09-01 16:58:07 +0200141 git_utils.GitCheckout(desugar_jdk_libs_hash, checkout_dir)
Søren Gjesse53d14482021-02-10 16:53:38 +0100142
Clément Béra2dc26b02022-11-14 09:50:57 +0100143def GetJavaEnv(androidHomeTemp):
Clément Béra54696f72021-11-16 09:27:22 +0000144 java_env = dict(os.environ, JAVA_HOME = jdk.GetJdk11Home())
145 java_env['PATH'] = java_env['PATH'] + os.pathsep + os.path.join(jdk.GetJdk11Home(), 'bin')
146 java_env['GRADLE_OPTS'] = '-Xmx1g'
Clément Béra2dc26b02022-11-14 09:50:57 +0100147 java_env['ANDROID_HOME'] = androidHomeTemp
Clément Béra54696f72021-11-16 09:27:22 +0000148 return java_env
149
Clément Béra2dc26b02022-11-14 09:50:57 +0100150def setUpFakeAndroidHome(androidHomeTemp):
151 # Bazel will check if 30 is present then extract android.jar from 32.
152 # We copy android.jar from third_party to mimic repository structure.
153 subpath = os.path.join(androidHomeTemp, "platforms")
154 cmd = ["mkdir", subpath]
155 subprocess.check_call(cmd)
156 subpath30 = os.path.join(subpath, "android-30")
157 cmd = ["mkdir", subpath30]
158 subprocess.check_call(cmd)
159 subpath = os.path.join(subpath, "android-32")
160 cmd = ["mkdir", subpath]
161 subprocess.check_call(cmd)
162 dest = os.path.join(subpath, "android.jar")
Clément Béra5d40a552022-11-14 10:54:44 +0100163 sha = os.path.join(utils.THIRD_PARTY, "android_jar", "lib-v32.tar.gz.sha1")
164 utils.DownloadFromGoogleCloudStorage(sha)
Clément Béra2dc26b02022-11-14 09:50:57 +0100165 src = os.path.join(utils.THIRD_PARTY, "android_jar", "lib-v32", "android.jar")
166 cmd = ["cp", src, dest]
167 subprocess.check_call(cmd)
Clément Béra54696f72021-11-16 09:27:22 +0000168
Søren Gjesse2b047692022-08-19 16:34:38 +0200169def BuildDesugaredLibrary(checkout_dir, variant, version = None):
170 if not variant in MAVEN_RELEASE_TARGET_MAP:
171 raise Exception('Variant ' + variant + ' is not supported')
172 if variant != 'jdk8' and variant != 'jdk11_legacy' and version is None:
173 raise Exception('Variant ' + variant + ' require version for undesugaring')
Søren Gjesse4b16c1b2023-01-30 15:04:30 +0100174 if variant != 'jdk8':
175 # Hack to workaround b/256723819.
176 os.remove(
Søren Gjesse3a75bd92023-01-31 13:04:22 +0100177 os.path.join(
Søren Gjesse4b16c1b2023-01-30 15:04:30 +0100178 checkout_dir,
179 "jdk11",
180 "src",
181 "java.base",
182 "share",
183 "classes",
184 "java",
185 "time",
186 "format",
187 "DesugarDateTimeFormatterBuilder.java"))
Søren Gjesse53d14482021-02-10 16:53:38 +0100188 with utils.ChangedWorkingDirectory(checkout_dir):
Clément Béra2dc26b02022-11-14 09:50:57 +0100189 with utils.TempDir() as androidHomeTemp:
190 setUpFakeAndroidHome(androidHomeTemp)
191 javaEnv = GetJavaEnv(androidHomeTemp)
192 bazel = os.path.join(utils.BAZEL_TOOL, 'lib', 'bazel', 'bin', 'bazel')
193 cmd = [
Søren Gjesse124c4c42021-10-18 12:37:41 +0200194 bazel,
195 '--bazelrc=/dev/null',
196 'build',
Rico Wind8eb5cbd2022-03-04 13:48:09 +0100197 '--spawn_strategy=local',
Rico Wind55de5d52022-02-23 08:00:23 +0100198 '--verbose_failures',
Søren Gjesse2b047692022-08-19 16:34:38 +0200199 MAVEN_RELEASE_TARGET_MAP[variant]]
Clément Béra2dc26b02022-11-14 09:50:57 +0100200 utils.PrintCmd(cmd)
201 subprocess.check_call(cmd, env=javaEnv)
202 cmd = [bazel, 'shutdown']
203 utils.PrintCmd(cmd)
204 subprocess.check_call(cmd, env=javaEnv)
Søren Gjesse53d14482021-02-10 16:53:38 +0100205
206 # Locate the library jar and the maven zip with the jar from the
207 # bazel build.
Søren Gjesseef195772021-03-11 16:04:42 +0100208 if variant == 'jdk8':
209 library_jar = os.path.join(
210 checkout_dir, 'bazel-bin', 'src', 'share', 'classes', 'java', 'libjava.jar')
211 else:
Søren Gjesse2b047692022-08-19 16:34:38 +0200212 # All JDK11 variants use the same library code.
Søren Gjesseef195772021-03-11 16:04:42 +0100213 library_jar = os.path.join(
Clément Bérac1fecfa2021-11-19 12:26:23 +0000214 checkout_dir, 'bazel-bin', 'jdk11', 'src', 'd8_java_base_selected_with_addon.jar')
Søren Gjesseef195772021-03-11 16:04:42 +0100215 maven_zip = os.path.join(
216 checkout_dir,
217 'bazel-bin',
Søren Gjesse2b047692022-08-19 16:34:38 +0200218 MAVEN_RELEASE_ZIP[variant])
Søren Gjesse53d14482021-02-10 16:53:38 +0100219
Søren Gjesse2b047692022-08-19 16:34:38 +0200220 if variant != 'jdk8' and variant != 'jdk11_legacy':
221 # The undesugaring is temporary...
222 undesugared_maven_zip = os.path.join(checkout_dir, 'undesugared_maven')
223 Undesugar(variant, maven_zip, version, undesugared_maven_zip)
224 undesugared_maven_zip = os.path.join(checkout_dir, 'undesugared_maven.zip')
225 return (library_jar, undesugared_maven_zip)
226 else:
227 return (library_jar, maven_zip)
228
229def hash_for(file, hash):
230 with open(file, 'rb') as f:
231 while True:
232 # Read chunks of 1MB
233 chunk = f.read(2 ** 20)
234 if not chunk:
235 break
236 hash.update(chunk)
237 return hash.hexdigest()
238
239def write_md5_for(file):
240 hexdigest = hash_for(file, hashlib.md5())
241 with (open(file + '.md5', 'w')) as file:
242 file.write(hexdigest)
243
244def write_sha1_for(file):
245 hexdigest = hash_for(file, hashlib.sha1())
246 with (open(file + '.sha1', 'w')) as file:
247 file.write(hexdigest)
248
249def Undesugar(variant, maven_zip, version, undesugared_maven_zip):
Søren Gjesseecace562022-08-25 09:13:48 +0200250 gradle.RunGradle(['testJar', 'repackageTestDeps', '-Pno_internal'])
Søren Gjesse2b047692022-08-19 16:34:38 +0200251 with utils.TempDir() as tmp:
252 with zipfile.ZipFile(maven_zip, 'r') as zip_ref:
253 zip_ref.extractall(tmp)
254 desugar_jdk_libs_jar = os.path.join(
255 tmp,
256 'com',
257 'android',
258 'tools',
259 LIBRARY_NAME_MAP[variant],
260 version,
261 '%s-%s.jar' % (LIBRARY_NAME_MAP[variant], version))
262 print(desugar_jdk_libs_jar)
263 undesugared_jar = os.path.join(tmp, 'undesugared.jar')
264 buildLibs = os.path.join(defines.REPO_ROOT, 'build', 'libs')
265 cmd = [jdk.GetJavaExecutable(),
266 '-cp',
267 '%s:%s:%s' % (os.path.join(buildLibs, 'r8_with_deps.jar'), os.path.join(buildLibs, 'r8tests.jar'), os.path.join(buildLibs, 'test_deps_all.jar')),
268 'com.android.tools.r8.desugar.desugaredlibrary.jdk11.DesugaredLibraryJDK11Undesugarer',
269 desugar_jdk_libs_jar,
270 undesugared_jar]
271 print(cmd)
272 try:
273 output = subprocess.check_output(cmd, stderr = subprocess.STDOUT).decode('utf-8')
274 except subprocess.CalledProcessError as e:
275 print(e)
276 print(e.output)
277 raise e
278 print(output)
279 # Copy the undesugared jar into place and update the checksums.
280 shutil.copyfile(undesugared_jar, desugar_jdk_libs_jar)
281 write_md5_for(desugar_jdk_libs_jar)
282 write_sha1_for(desugar_jdk_libs_jar)
283 shutil.make_archive(undesugared_maven_zip, 'zip', tmp)
284 print(undesugared_maven_zip)
285 output = subprocess.check_output(['ls', '-l', os.path.dirname(undesugared_maven_zip)], stderr = subprocess.STDOUT).decode('utf-8')
286 print(output)
Søren Gjesse53d14482021-02-10 16:53:38 +0100287
288def MustBeExistingDirectory(path):
289 if (not os.path.exists(path) or not os.path.isdir(path)):
290 raise Exception(path + ' does not exist or is not a directory')
Søren Gjesse1c115b52019-08-14 12:43:57 +0200291
Søren Gjesse2b047692022-08-19 16:34:38 +0200292def BuildAndUpload(options, variant):
Søren Gjesse85c37922022-09-01 16:58:07 +0200293 desugar_jdk_libs_hash = ''
294 with open(DESUGAR_JDK_LIBS_HASH_FILE, 'r') as input_hash:
295 desugar_jdk_libs_hash = input_hash.readline()
Søren Gjesse2b047692022-08-19 16:34:38 +0200296 if options.build_only:
297 with utils.TempDir() as checkout_dir:
Søren Gjesse85c37922022-09-01 16:58:07 +0200298 CloneDesugaredLibrary(options.github_account, checkout_dir, desugar_jdk_libs_hash)
299 (library_jar, maven_zip) = BuildDesugaredLibrary(checkout_dir, variant, desugar_jdk_libs_hash)
Søren Gjesse2b047692022-08-19 16:34:38 +0200300 shutil.copyfile(
301 library_jar,
302 os.path.join(options.build_only, os.path.basename(library_jar)))
303 shutil.copyfile(
304 maven_zip,
305 os.path.join(options.build_only, os.path.basename(maven_zip)))
306 return
307
308 # Only handling versioned desugar_jdk_libs.
309 is_main = False
310
311 with utils.TempDir() as checkout_dir:
Søren Gjesse85c37922022-09-01 16:58:07 +0200312 CloneDesugaredLibrary(options.github_account, checkout_dir, desugar_jdk_libs_hash)
Søren Gjesse2b047692022-08-19 16:34:38 +0200313 version = GetVersion(os.path.join(checkout_dir, VERSION_MAP[variant]))
314
315 destination = archive.GetVersionDestination(
316 'gs://', LIBRARY_NAME_MAP[variant] + '/' + version, is_main)
317 if utils.cloud_storage_exists(destination) and not options.dry_run:
318 raise Exception(
319 'Target archive directory %s already exists' % destination)
320
321 (library_jar, maven_zip) = BuildDesugaredLibrary(checkout_dir, variant, version)
322
323 storage_path = LIBRARY_NAME_MAP[variant] + '/' + version
324 # Upload the jar file with the library.
325 destination = archive.GetUploadDestination(
326 storage_path, LIBRARY_NAME_MAP[variant] + '.jar', is_main)
327 Upload(options, library_jar, storage_path, destination, is_main)
328
329 # Upload the maven zip file with the library.
330 destination = archive.GetUploadDestination(
331 storage_path, MAVEN_RELEASE_ZIP[variant], is_main)
332 Upload(options, maven_zip, storage_path, destination, is_main)
333
334 # Upload the jar file for accessing GCS as a maven repro.
335 maven_destination = archive.GetUploadDestination(
Søren Gjesse7ed07f42022-08-26 15:21:53 +0200336 utils.get_maven_path(LIBRARY_NAME_MAP[variant], version),
Christoffer Quist Adamsen62266902022-08-26 18:37:54 +0200337 '%s-%s.jar' % (LIBRARY_NAME_MAP[variant], version),
Søren Gjesse2b047692022-08-19 16:34:38 +0200338 is_main)
339 if options.dry_run:
340 print('Dry run, not actually creating maven repo')
341 else:
342 utils.upload_file_to_cloud_storage(library_jar, maven_destination)
343 print('Maven repo root available at: %s' % archive.GetMavenUrl(is_main))
344
Søren Gjesse1c115b52019-08-14 12:43:57 +0200345def Main(argv):
346 (options, args) = ParseOptions(argv)
347 if (len(args) > 0):
348 raise Exception('Unsupported arguments')
Søren Gjesse53d14482021-02-10 16:53:38 +0100349 if not utils.is_bot() and not (options.dry_run or options.build_only):
Søren Gjesse1c115b52019-08-14 12:43:57 +0200350 raise Exception('You are not a bot, don\'t archive builds. '
Søren Gjesse53d14482021-02-10 16:53:38 +0100351 + 'Use --dry-run or --build-only to test locally')
352 if options.dry_run_output:
353 MustBeExistingDirectory(options.dry_run_output)
354 if options.build_only:
355 MustBeExistingDirectory(options.build_only)
Søren Gjesse1c115b52019-08-14 12:43:57 +0200356 if utils.is_bot():
357 archive.SetRLimitToMax()
358
359 # Make sure bazel is extracted in third_party.
360 utils.DownloadFromGoogleCloudStorage(utils.BAZEL_SHA_FILE)
Søren Gjesse699f6362019-10-09 14:56:33 +0200361 utils.DownloadFromGoogleCloudStorage(utils.JAVA8_SHA_FILE)
Søren Gjesseef195772021-03-11 16:04:42 +0100362 utils.DownloadFromGoogleCloudStorage(utils.JAVA11_SHA_FILE)
Søren Gjesse85c37922022-09-01 16:58:07 +0200363 utils.DownloadFromGoogleCloudStorage(utils.DESUGAR_JDK_LIBS_11_SHA_FILE)
Søren Gjesse1c115b52019-08-14 12:43:57 +0200364
Søren Gjesse2b047692022-08-19 16:34:38 +0200365 for v in options.variant:
366 BuildAndUpload(options, v)
Søren Gjesse1c115b52019-08-14 12:43:57 +0200367
368if __name__ == '__main__':
369 sys.exit(Main(sys.argv[1:]))