Prepare release scripts for new JDK-11 desugared library variants

Bug: b/222647019
Change-Id: Iae6b31b24df54163da6327cac3080dd72a597ddb
diff --git a/tools/archive.py b/tools/archive.py
index 59d32f5..6a39594 100755
--- a/tools/archive.py
+++ b/tools/archive.py
@@ -182,6 +182,22 @@
         utils.DESUGAR_IMPLEMENTATION_JDK11,
         utils.LIBRARY_DESUGAR_CONVERSIONS_LEGACY_ZIP)
 
+    create_maven_release.generate_desugar_configuration_maven_zip(
+        utils.DESUGAR_CONFIGURATION_JDK11_MINIMAL_MAVEN_ZIP,
+        utils.DESUGAR_CONFIGURATION_JDK11_MINIMAL,
+        utils.DESUGAR_IMPLEMENTATION_JDK11,
+        utils.LIBRARY_DESUGAR_CONVERSIONS_ZIP)
+    create_maven_release.generate_desugar_configuration_maven_zip(
+        utils.DESUGAR_CONFIGURATION_JDK11_MAVEN_ZIP,
+        utils.DESUGAR_CONFIGURATION_JDK11,
+        utils.DESUGAR_IMPLEMENTATION_JDK11,
+        utils.LIBRARY_DESUGAR_CONVERSIONS_ZIP)
+    create_maven_release.generate_desugar_configuration_maven_zip(
+        utils.DESUGAR_CONFIGURATION_JDK11_NIO_MAVEN_ZIP,
+        utils.DESUGAR_CONFIGURATION_JDK11_NIO,
+        utils.DESUGAR_IMPLEMENTATION_JDK11,
+        utils.LIBRARY_DESUGAR_CONVERSIONS_ZIP)
+
     version = GetVersion()
     is_main = IsMain(version)
     if is_main:
@@ -213,6 +229,9 @@
       utils.DESUGAR_CONFIGURATION_MAVEN_ZIP,
       utils.DESUGAR_CONFIGURATION_JDK11_LEGACY,
       utils.DESUGAR_CONFIGURATION_JDK11_LEGACY_MAVEN_ZIP,
+      utils.DESUGAR_CONFIGURATION_JDK11_MINIMAL_MAVEN_ZIP,
+      utils.DESUGAR_CONFIGURATION_JDK11_MAVEN_ZIP,
+      utils.DESUGAR_CONFIGURATION_JDK11_NIO_MAVEN_ZIP,
       utils.GENERATED_LICENSE,
     ]:
       file_name = os.path.basename(file)
diff --git a/tools/archive_desugar_jdk_libs.py b/tools/archive_desugar_jdk_libs.py
index 5298435..1762c2c 100755
--- a/tools/archive_desugar_jdk_libs.py
+++ b/tools/archive_desugar_jdk_libs.py
@@ -19,7 +19,10 @@
 # repository to fetch the artifact com.android.tools:desugar_jdk_libs:1.0.0
 
 import archive
+import defines
 import git_utils
+import gradle
+import hashlib
 import jdk
 import optparse
 import os
@@ -28,17 +31,59 @@
 import subprocess
 import sys
 import utils
+import zipfile
 
 VERSION_FILE_JDK8 = 'VERSION.txt'
+VERSION_FILE_JDK11_LEGACY = 'VERSION_JDK11_LEGACY.txt'
+VERSION_FILE_JDK11_MINIMAL = 'VERSION_JDK11_MINIMAL.txt'
 VERSION_FILE_JDK11 = 'VERSION_JDK11.txt'
-LIBRARY_NAME = 'desugar_jdk_libs'
+VERSION_FILE_JDK11_NIO = 'VERSION_JDK11_NIO.txt'
+
+VERSION_MAP = {
+  'jdk8': VERSION_FILE_JDK8,
+  'jdk11_legacy': VERSION_FILE_JDK11_LEGACY,
+  'jdk11_minimal': VERSION_FILE_JDK11_MINIMAL,
+  'jdk11': VERSION_FILE_JDK11,
+  'jdk11_nio': VERSION_FILE_JDK11_NIO
+}
+
+GITHUB_REPRO = 'desugar_jdk_libs'
+
+BASE_LIBRARY_NAME = 'desugar_jdk_libs'
+
+LIBRARY_NAME_MAP = {
+  'jdk8': BASE_LIBRARY_NAME,
+  'jdk11_legacy': BASE_LIBRARY_NAME,
+  'jdk11_minimal': BASE_LIBRARY_NAME + '_minimal',
+  'jdk11': BASE_LIBRARY_NAME,
+  'jdk11_nio': BASE_LIBRARY_NAME + '_nio'
+}
+
+MAVEN_RELEASE_TARGET_MAP = {
+  'jdk8': 'maven_release',
+  'jdk11_legacy': 'maven_release_jdk11_legacy',
+  'jdk11_minimal': 'maven_release_jdk11_minimal',
+  'jdk11': 'maven_release_jdk11',
+  'jdk11_nio': 'maven_release_jdk11_nio'
+}
+
+MAVEN_RELEASE_ZIP = {
+  'jdk8': BASE_LIBRARY_NAME + '.zip',
+  'jdk11_legacy': BASE_LIBRARY_NAME + '_jdk11_legacy.zip',
+  'jdk11_minimal': BASE_LIBRARY_NAME + '_jdk11_minimal.zip',
+  'jdk11': BASE_LIBRARY_NAME + '_jdk11.zip',
+  'jdk11_nio': BASE_LIBRARY_NAME + '_jdk11_nio.zip'
+}
+
 
 def ParseOptions(argv):
   result = optparse.OptionParser()
   result.add_option('--variant',
-      help='.',
-      choices = ['jdk8', 'jdk11'],
-      default='jdk11')
+      help="Variant(s) to build",
+      metavar=('<variants(s)>'),
+      choices=['jdk8', 'jdk11_legacy', 'jdk11_minimal', 'jdk11', 'jdk11_nio'],
+      default=[],
+      action='append')
   result.add_option('--dry-run', '--dry_run',
       help='Running on bot, use third_party dependency.',
       default=False,
@@ -89,7 +134,7 @@
 def CloneDesugaredLibrary(github_account, checkout_dir):
   git_utils.GitClone(
     'https://github.com/'
-        + github_account + '/' + LIBRARY_NAME, checkout_dir)
+        + github_account + '/' + GITHUB_REPRO, checkout_dir)
 
 def GetJavaEnv():
   java_env = dict(os.environ, JAVA_HOME = jdk.GetJdk11Home())
@@ -98,9 +143,11 @@
   return java_env
 
 
-def BuildDesugaredLibrary(checkout_dir, variant):
-  if (variant != 'jdk8' and variant != 'jdk11'):
-    raise Exception('Variant ' + variant + 'is not supported')
+def BuildDesugaredLibrary(checkout_dir, variant, version = None):
+  if not variant in MAVEN_RELEASE_TARGET_MAP:
+    raise Exception('Variant ' + variant + ' is not supported')
+  if variant != 'jdk8' and variant != 'jdk11_legacy' and version is None:
+    raise Exception('Variant ' + variant + ' require version for undesugaring')
   with utils.ChangedWorkingDirectory(checkout_dir):
     bazel = os.path.join(utils.BAZEL_TOOL, 'lib', 'bazel', 'bin', 'bazel')
     cmd = [
@@ -109,7 +156,7 @@
         'build',
         '--spawn_strategy=local',
         '--verbose_failures',
-        'maven_release' + ('_jdk11' if variant == 'jdk11' else '')]
+        MAVEN_RELEASE_TARGET_MAP[variant]]
     utils.PrintCmd(cmd)
     subprocess.check_call(cmd, env=GetJavaEnv())
     cmd = [bazel, 'shutdown']
@@ -122,19 +169,136 @@
       library_jar = os.path.join(
           checkout_dir, 'bazel-bin', 'src', 'share', 'classes', 'java', 'libjava.jar')
     else:
+      # All JDK11 variants use the same library code.
       library_jar = os.path.join(
           checkout_dir, 'bazel-bin', 'jdk11', 'src', 'd8_java_base_selected_with_addon.jar')
     maven_zip = os.path.join(
       checkout_dir,
       'bazel-bin',
-      LIBRARY_NAME + ('_jdk11' if variant == 'jdk11' else '') +'.zip')
-    return (library_jar, maven_zip)
+      MAVEN_RELEASE_ZIP[variant])
 
+    if variant != 'jdk8' and variant != 'jdk11_legacy':
+      # The undesugaring is temporary...
+      undesugared_maven_zip = os.path.join(checkout_dir, 'undesugared_maven')
+      Undesugar(variant, maven_zip, version, undesugared_maven_zip)
+      undesugared_maven_zip = os.path.join(checkout_dir, 'undesugared_maven.zip')
+      return (library_jar, undesugared_maven_zip)
+    else:
+      return (library_jar, maven_zip)
+
+def hash_for(file, hash):
+  with open(file, 'rb') as f:
+    while True:
+      # Read chunks of 1MB
+      chunk = f.read(2 ** 20)
+      if not chunk:
+        break
+      hash.update(chunk)
+  return hash.hexdigest()
+
+def write_md5_for(file):
+  hexdigest = hash_for(file, hashlib.md5())
+  with (open(file + '.md5', 'w')) as file:
+    file.write(hexdigest)
+
+def write_sha1_for(file):
+  hexdigest = hash_for(file, hashlib.sha1())
+  with (open(file + '.sha1', 'w')) as file:
+    file.write(hexdigest)
+
+def Undesugar(variant, maven_zip, version, undesugared_maven_zip):
+  gradle.RunGradle(['testJar', 'repackageTestDeps'])
+  with utils.TempDir() as tmp:
+    with zipfile.ZipFile(maven_zip, 'r') as zip_ref:
+      zip_ref.extractall(tmp)
+    desugar_jdk_libs_jar = os.path.join(
+          tmp,
+          'com',
+          'android',
+          'tools',
+          LIBRARY_NAME_MAP[variant],
+          version,
+          '%s-%s.jar' % (LIBRARY_NAME_MAP[variant], version))
+    print(desugar_jdk_libs_jar)
+    undesugared_jar = os.path.join(tmp, 'undesugared.jar')
+    buildLibs = os.path.join(defines.REPO_ROOT, 'build', 'libs')
+    cmd = [jdk.GetJavaExecutable(),
+      '-cp',
+      '%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')),
+      'com.android.tools.r8.desugar.desugaredlibrary.jdk11.DesugaredLibraryJDK11Undesugarer',
+      desugar_jdk_libs_jar,
+      undesugared_jar]
+    print(cmd)
+    try:
+      output = subprocess.check_output(cmd, stderr = subprocess.STDOUT).decode('utf-8')
+    except subprocess.CalledProcessError as e:
+      print(e)
+      print(e.output)
+      raise e
+    print(output)
+    # Copy the undesugared jar into place and update the checksums.
+    shutil.copyfile(undesugared_jar, desugar_jdk_libs_jar)
+    write_md5_for(desugar_jdk_libs_jar)
+    write_sha1_for(desugar_jdk_libs_jar)
+    shutil.make_archive(undesugared_maven_zip, 'zip', tmp)
+    print(undesugared_maven_zip)
+    output = subprocess.check_output(['ls', '-l', os.path.dirname(undesugared_maven_zip)], stderr = subprocess.STDOUT).decode('utf-8')
+    print(output)
 
 def MustBeExistingDirectory(path):
   if (not os.path.exists(path) or not os.path.isdir(path)):
     raise Exception(path + ' does not exist or is not a directory')
 
+def BuildAndUpload(options, variant):
+  if options.build_only:
+    with utils.TempDir() as checkout_dir:
+      CloneDesugaredLibrary(options.github_account, checkout_dir)
+      (library_jar, maven_zip) = BuildDesugaredLibrary(checkout_dir, variant)
+      shutil.copyfile(
+        library_jar,
+        os.path.join(options.build_only, os.path.basename(library_jar)))
+      shutil.copyfile(
+        maven_zip,
+        os.path.join(options.build_only, os.path.basename(maven_zip)))
+      return
+
+  # Only handling versioned desugar_jdk_libs.
+  is_main = False
+
+  with utils.TempDir() as checkout_dir:
+    CloneDesugaredLibrary(options.github_account, checkout_dir)
+    version = GetVersion(os.path.join(checkout_dir, VERSION_MAP[variant]))
+
+    destination = archive.GetVersionDestination(
+        'gs://', LIBRARY_NAME_MAP[variant] + '/' + version, is_main)
+    if utils.cloud_storage_exists(destination) and not options.dry_run:
+      raise Exception(
+          'Target archive directory %s already exists' % destination)
+
+    (library_jar, maven_zip) = BuildDesugaredLibrary(checkout_dir, variant, version)
+
+    storage_path = LIBRARY_NAME_MAP[variant] + '/' + version
+    # Upload the jar file with the library.
+    destination = archive.GetUploadDestination(
+        storage_path, LIBRARY_NAME_MAP[variant] + '.jar', is_main)
+    Upload(options, library_jar, storage_path, destination, is_main)
+
+    # Upload the maven zip file with the library.
+    destination = archive.GetUploadDestination(
+        storage_path, MAVEN_RELEASE_ZIP[variant], is_main)
+    Upload(options, maven_zip, storage_path, destination, is_main)
+
+    # Upload the jar file for accessing GCS as a maven repro.
+    maven_destination = archive.GetUploadDestination(
+        utils.get_maven_path('desugar_jdk_libs', version),
+        'desugar_jdk_libs-%s.jar' % version,
+        is_main)
+    if options.dry_run:
+      print('Dry run, not actually creating maven repo')
+    else:
+      utils.upload_file_to_cloud_storage(library_jar, maven_destination)
+      print('Maven repo root available at: %s' % archive.GetMavenUrl(is_main))
+
 def Main(argv):
   (options, args) = ParseOptions(argv)
   if (len(args) > 0):
@@ -154,58 +318,8 @@
   utils.DownloadFromGoogleCloudStorage(utils.JAVA8_SHA_FILE)
   utils.DownloadFromGoogleCloudStorage(utils.JAVA11_SHA_FILE)
 
-  if options.build_only:
-    with utils.TempDir() as checkout_dir:
-      CloneDesugaredLibrary(options.github_account, checkout_dir)
-      (library_jar, maven_zip) = BuildDesugaredLibrary(checkout_dir, options.variant)
-      shutil.copyfile(
-        library_jar,
-        os.path.join(options.build_only, os.path.basename(library_jar)))
-      shutil.copyfile(
-        maven_zip,
-        os.path.join(options.build_only, os.path.basename(maven_zip)))
-      return
-
-  # Only handling versioned desugar_jdk_libs.
-  is_main = False
-
-  with utils.TempDir() as checkout_dir:
-    CloneDesugaredLibrary(options.github_account, checkout_dir)
-    version = GetVersion(
-      os.path.join(
-        checkout_dir,
-        VERSION_FILE_JDK11 if options.variant == 'jdk11' else VERSION_FILE_JDK8))
-
-    destination = archive.GetVersionDestination(
-        'gs://', LIBRARY_NAME + '/' + version, is_main)
-    if utils.cloud_storage_exists(destination) and not options.dry_run:
-      raise Exception(
-          'Target archive directory %s already exists' % destination)
-
-    (library_jar, maven_zip) = BuildDesugaredLibrary(checkout_dir, options.variant)
-
-    storage_path = LIBRARY_NAME + '/' + version
-    # Upload the jar file with the library.
-    destination = archive.GetUploadDestination(
-        storage_path, LIBRARY_NAME + '.jar', is_main)
-    Upload(options, library_jar, storage_path, destination, is_main)
-
-    # Upload the maven zip file with the library.
-    destination = archive.GetUploadDestination(
-        storage_path, LIBRARY_NAME + '.zip', is_main)
-    Upload(options, maven_zip, storage_path, destination, is_main)
-
-    # Upload the jar file for accessing GCS as a maven repro.
-    maven_destination = archive.GetUploadDestination(
-        utils.get_maven_path('desugar_jdk_libs', version),
-        'desugar_jdk_libs-%s.jar' % version,
-        is_main)
-    if options.dry_run:
-      print('Dry run, not actually creating maven repo')
-    else:
-      utils.upload_file_to_cloud_storage(library_jar, maven_destination)
-      print('Maven repo root available at: %s' % archive.GetMavenUrl(is_main))
-
+  for v in options.variant:
+    BuildAndUpload(options, v)
 
 if __name__ == '__main__':
   sys.exit(Main(sys.argv[1:]))
diff --git a/tools/create_maven_release.py b/tools/create_maven_release.py
index 472bd96..fc7eafb 100755
--- a/tools/create_maven_release.py
+++ b/tools/create_maven_release.py
@@ -81,7 +81,7 @@
     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>
   <groupId>com.android.tools</groupId>
-  <artifactId>desugar_jdk_libs_configuration</artifactId>
+  <artifactId>$artifactId</artifactId>
   <version>$version</version>
   <name>D8 configuration to desugar desugar_jdk_libs</name>
   <description>
@@ -260,11 +260,19 @@
   return result
 
 def write_default_r8_pom_file(pom_file, version):
-  write_pom_file(R8_POMTEMPLATE, pom_file, version, generate_dependencies(), '')
+  write_pom_file(R8_POMTEMPLATE, pom_file, version, dependencies=generate_dependencies())
 
-def write_pom_file(template, pom_file, version, dependencies='', library_licenses=''):
-  version_pom = template.substitute(
-      version=version, dependencies=dependencies, library_licenses=library_licenses)
+def write_pom_file(
+    template, pom_file, version, artifact_id=None, dependencies='', library_licenses=''):
+  version_pom = (
+      template.substitute(
+          artifactId=artifact_id,
+          version=version,
+          dependencies=dependencies,
+          library_licenses=library_licenses)
+    if artifact_id else
+      template.substitute(
+          version=version, dependencies=dependencies, library_licenses=library_licenses))
   with open(pom_file, 'w') as file:
     file.write(version_pom)
 
@@ -332,8 +340,8 @@
         R8_POMTEMPLATE,
         pom_file,
         version,
-        "" if is_r8lib else generate_dependencies(),
-        generate_library_licenses() if is_r8lib else "")
+        dependencies='' if is_r8lib else generate_dependencies(),
+        library_licenses=generate_library_licenses() if is_r8lib else '')
     # Write the maven zip file.
     generate_maven_zip(
         'r8',
@@ -383,14 +391,31 @@
     make_archive(destination, 'zip', tmp_dir)
     move(destination + '.zip', destination)
 
+def convert_desugar_configuration(configuration, machine_configuration):
+  cmd = [jdk.GetJavaExecutable(),
+      '-cp',
+      utils.R8_JAR,
+      'com.android.tools.r8.ir.desugar.desugaredlibrary.specificationconversion.DesugaredLibraryConverter',
+      configuration,
+      utils.DESUGAR_IMPLEMENTATION_JDK11,
+      utils.get_android_jar(33),
+      machine_configuration]
+  subprocess.check_call(cmd)
+
 # Generate the maven zip for the configuration to desugar desugar_jdk_libs.
 def generate_desugar_configuration_maven_zip(
     out, configuration, implementation, conversions):
   with utils.TempDir() as tmp_dir:
-    version = utils.desugar_configuration_version(configuration)
+    (name, version) = utils.desugar_configuration_name_and_version(configuration, False)
+
+    if (not version.startswith("1.")):
+      machine_configuration = join(tmp_dir, "machine.json")
+      convert_desugar_configuration(configuration, machine_configuration)
+      configuration = machine_configuration
+
     # Generate the pom file.
     pom_file = join(tmp_dir, 'desugar_configuration.pom')
-    write_pom_file(DESUGAR_CONFIGUATION_POMTEMPLATE, pom_file, version)
+    write_pom_file(DESUGAR_CONFIGUATION_POMTEMPLATE, pom_file, version, artifact_id=name)
     # Generate the jar with the configuration file.
     jar_file = join(tmp_dir, 'desugar_configuration.jar')
     generate_jar_with_desugar_configuration(
@@ -399,8 +424,7 @@
         conversions,
         jar_file)
     # Write the maven zip file.
-    generate_maven_zip(
-        'desugar_jdk_libs_configuration', version, pom_file, jar_file, out)
+    generate_maven_zip(name, version, pom_file, jar_file, out)
 
 def main(argv):
   options = parse_options(argv)
diff --git a/tools/desugar_jdk_libs_repository.py b/tools/desugar_jdk_libs_repository.py
index 55db5b6..4417255 100755
--- a/tools/desugar_jdk_libs_repository.py
+++ b/tools/desugar_jdk_libs_repository.py
@@ -14,9 +14,12 @@
 import utils
 import create_maven_release
 
-class Configuration(Enum):
+class Variant(Enum):
     jdk8 = 'jdk8'
-    jdk11_legacy = 'jdk11-legacy'
+    jdk11_legacy = 'jdk11_legacy'
+    jdk11_minimal = 'jdk11_minimal'
+    jdk11 = 'jdk11'
+    jdk11_nio = 'jdk11_nio'
 
     def __str__(self):
         return self.value
@@ -32,7 +35,7 @@
                       default=False,
                       action='store_true',
                       help='Clear the Maven repository so it only has one version present')
-  parser.add_argument('--configuration', default='jdk8', type=Configuration, choices=list(Configuration))
+  parser.add_argument('--variant', type=Variant, choices=list(Variant))
   parser.add_argument('--desugar-jdk-libs-checkout', '--desugar_jdk_libs_checkout',
                       default=None,
                       metavar=('<path>'),
@@ -56,29 +59,70 @@
 def pom_file(unzip_dir, artifact, version):
   return jar_or_pom_file(unzip_dir, artifact, version, 'pom')
 
-def main():
-  args = parse_options()
-  if args.clear_repo:
-    shutil.rmtree(args.repo_root, ignore_errors=True)
-  utils.makedirs_if_needed(args.repo_root)
-  configuration = (utils.DESUGAR_CONFIGURATION
-                   if args.configuration is Configuration.jdk8
-                   else utils.DESUGAR_CONFIGURATION_JDK11_LEGACY)
-  implementation = (utils.DESUGAR_IMPLEMENTATION
-                    if args.configuration is Configuration.jdk8
-                    else utils.DESUGAR_IMPLEMENTATION_JDK11)
-  version_file = ('VERSION.txt'
-                  if args.configuration is Configuration.jdk8 else
-                  'VERSION_JDK11.txt')
-  with utils.TempDir() as tmp_dir:
-    version = utils.desugar_configuration_version(configuration)
+def run(args):
+  artifact = None
+  configuration_artifact = None
+  configuration = None
+  conversions = None
+  implementation = None
+  version_file = None
+  implementation_build_target = None
+  implementation_build_output = None
+  match args.variant:
+    case Variant.jdk8:
+      artifact = 'desugar_jdk_libs'
+      configuration_artifact = 'desugar_jdk_libs_configuration'
+      configuration = utils.DESUGAR_CONFIGURATION
+      conversions = utils.LIBRARY_DESUGAR_CONVERSIONS_LEGACY_ZIP
+      implementation = utils.DESUGAR_IMPLEMENTATION
+      version_file = 'VERSION.txt'
+      implementation_build_target = ':maven_release'
+      implementation_build_output = join('bazel-bin', 'desugar_jdk_libs.zip')
+    case Variant.jdk11_legacy:
+      artifact = 'desugar_jdk_libs'
+      configuration_artifact = 'desugar_jdk_libs_configuration'
+      configuration = utils.DESUGAR_CONFIGURATION_JDK11_LEGACY
+      conversions = utils.LIBRARY_DESUGAR_CONVERSIONS_LEGACY_ZIP
+      implementation = utils.DESUGAR_IMPLEMENTATION_JDK11
+      version_file = 'VERSION_JDK11_LEGACY.txt'
+      implementation_build_target = ':maven_release_jdk11_legacy'
+      implementation_build_output = join('bazel-bin', 'desugar_jdk_libs_jdk11_legacy.zip')
+    case Variant.jdk11_minimal:
+      artifact = 'desugar_jdk_libs_minimal'
+      configuration_artifact = 'desugar_jdk_libs_configuration_minimal'
+      configuration = utils.DESUGAR_CONFIGURATION_JDK11_MINIMAL
+      conversions = utils.LIBRARY_DESUGAR_CONVERSIONS_ZIP
+      implementation = utils.DESUGAR_IMPLEMENTATION_JDK11
+      version_file = 'VERSION_JDK11_MINIMAL.txt'
+      implementation_build_target = ':maven_release_jdk11_minimal'
+      implementation_build_output = join('bazel-bin', 'desugar_jdk_libs_jdk11_minimal.zip')
+    case Variant.jdk11:
+      artifact = 'desugar_jdk_libs'
+      configuration_artifact = 'desugar_jdk_libs_configuration'
+      configuration = utils.DESUGAR_CONFIGURATION_JDK11
+      conversions = utils.LIBRARY_DESUGAR_CONVERSIONS_ZIP
+      implementation = utils.DESUGAR_IMPLEMENTATION_JDK11
+      version_file = 'VERSION_JDK11.txt'
+      implementation_build_target = ':maven_release_jdk11'
+      implementation_build_output = join('bazel-bin', 'desugar_jdk_libs_jdk11.zip')
+    case Variant.jdk11_nio:
+      artifact = 'desugar_jdk_libs_nio'
+      configuration_artifact = 'desugar_jdk_libs_configuration_nio'
+      configuration = utils.DESUGAR_CONFIGURATION_JDK11_NIO
+      conversions = utils.LIBRARY_DESUGAR_CONVERSIONS_ZIP
+      implementation = utils.DESUGAR_IMPLEMENTATION_JDK11
+      version_file = 'VERSION_JDK11_NIO.txt'
+      implementation_build_target = ':maven_release_jdk11_nio'
+      implementation_build_output = join('bazel-bin', 'desugar_jdk_libs_jdk11_nio.zip')
+  with utils.TempDir(delete=False) as tmp_dir:
+    (name, version) = utils.desugar_configuration_name_and_version(configuration, False)
     # Checkout desugar_jdk_libs from GitHub
     use_existing_checkout = args.desugar_jdk_libs_checkout != None
     checkout_dir = (args.desugar_jdk_libs_checkout
                     if use_existing_checkout
                     else join(tmp_dir, 'desugar_jdk_libs'))
     if (not use_existing_checkout):
-      utils.RunCmd(['git', 'clone', 'https://github.com/google/desugar_jdk_libs.git', checkout_dir])
+      subprocess.check_call(['git', 'clone', 'https://github.com/google/desugar_jdk_libs.git', checkout_dir])
     with utils.ChangedWorkingDirectory(checkout_dir):
       with open(version_file) as version_file:
         version_file_lines = version_file.readlines()
@@ -99,56 +143,51 @@
     create_maven_release.generate_desugar_configuration_maven_zip(
       maven_zip,
       configuration,
-      implementation)
+      implementation,
+      conversions)
     unzip_dir = join(tmp_dir, 'desugar_jdk_libs_configuration_unzipped')
     cmd = ['unzip', '-q', maven_zip, '-d', unzip_dir]
-    utils.RunCmd(cmd)
+    subprocess.check_call(cmd)
     cmd = [
       'mvn',
       'deploy:deploy-file',
       '-Durl=file:' + args.repo_root,
       '-DrepositoryId=someName',
-      '-Dfile=' + jar_file(unzip_dir, 'desugar_jdk_libs_configuration', version),
-      '-DpomFile=' + pom_file(unzip_dir, 'desugar_jdk_libs_configuration', version)]
-    utils.RunCmd(cmd)
+      '-Dfile=' + jar_file(unzip_dir, configuration_artifact, version),
+      '-DpomFile=' + pom_file(unzip_dir, configuration_artifact, version)]
+    subprocess.check_call(cmd)
 
     # Build desugared library.
     print("Building desugared library " + version)
     with utils.ChangedWorkingDirectory(checkout_dir):
-      utils.RunCmd([
+      subprocess.check_call([
           'bazel',
           '--bazelrc=/dev/null',
           'build',
           '--spawn_strategy=local',
           '--verbose_failures',
-          (':maven_release'
-            if args.configuration is Configuration.jdk8
-          else ':maven_release_jdk11')])
+          implementation_build_target])
     unzip_dir = join(tmp_dir, 'desugar_jdk_libs_unzipped')
     cmd = [
         'unzip',
         '-q',
-        join(checkout_dir,
-            'bazel-bin',
-            ('desugar_jdk_libs.zip'
-              if args.configuration is Configuration.jdk8
-              else 'desugar_jdk_libs_jdk11.zip')),
+        join(checkout_dir, implementation_build_output),
         '-d',
         unzip_dir]
-    utils.RunCmd(cmd)
+    subprocess.check_call(cmd)
     cmd = [
       'mvn',
       'deploy:deploy-file',
       '-Durl=file:' + args.repo_root,
       '-DrepositoryId=someName',
-      '-Dfile=' + jar_file(unzip_dir, 'desugar_jdk_libs', version),
-      '-DpomFile=' + pom_file(unzip_dir, 'desugar_jdk_libs', version)]
-    utils.RunCmd(cmd)
+      '-Dfile=' + jar_file(unzip_dir, artifact, version),
+      '-DpomFile=' + pom_file(unzip_dir, artifact, version)]
+    subprocess.check_call(cmd)
 
     print()
     print("Artifacts:")
-    print("  com.android.tools:desugar_jdk_libs_configuration:" + version)
-    print("  com.android.tools:desugar_jdk_libs:" + version)
+    print("  com.android.tools:%s:%s" % (configuration_artifact, version))
+    print("  com.android.tools:%s:%s" % (artifact, version))
     print()
     print("deployed to Maven repository at " + args.repo_root + ".")
     print()
@@ -161,7 +200,7 @@
     print("to dependencyResolutionManagement.repositories in settings.gradle, and use")
     print('the "changing" property of the coreLibraryDesugaring dependency:')
     print()
-    print("  coreLibraryDesugaring('com.android.tools:desugar_jdk_libs:" +  version + "') {")
+    print("  coreLibraryDesugaring('com.android.tools:%s:%s') {" % (artifact, version))
     print("    changing = true")
     print("  }")
     print()
@@ -170,5 +209,17 @@
       + "to ensure the cache is not used when the same version is published."
       + "multiple times.")
 
+def main():
+  args = parse_options()
+  if args.clear_repo:
+    shutil.rmtree(args.repo_root, ignore_errors=True)
+  utils.makedirs_if_needed(args.repo_root)
+  if (args.variant):
+    run(args)
+  else:
+    for v in Variant:
+      args.variant = v
+      run(args)
+
 if __name__ == '__main__':
   sys.exit(main())
diff --git a/tools/test.py b/tools/test.py
index 27c8b6a..5586802 100755
--- a/tools/test.py
+++ b/tools/test.py
@@ -260,7 +260,7 @@
       utils.DownloadFromGoogleCloudStorage(utils.BAZEL_SHA_FILE)
       utils.DownloadFromGoogleCloudStorage(utils.JAVA8_SHA_FILE)
       utils.DownloadFromGoogleCloudStorage(utils.JAVA11_SHA_FILE)
-      (library_jar, maven_zip) = archive_desugar_jdk_libs.BuildDesugaredLibrary(checkout_dir, 'jdk11' if options.desugared_library_configuration == 'jdk11' else 'jdk8')
+      (library_jar, maven_zip) = archive_desugar_jdk_libs.BuildDesugaredLibrary(checkout_dir, 'jdk11_legacy' if options.desugared_library_configuration == 'jdk11' else 'jdk8')
       desugar_jdk_libs = os.path.join(desugar_jdk_libs_dir, os.path.basename(library_jar))
       shutil.copyfile(library_jar, desugar_jdk_libs)
       print('Desugared library for test in ' + desugar_jdk_libs)
diff --git a/tools/utils.py b/tools/utils.py
index 9bd518f..1830f53 100644
--- a/tools/utils.py
+++ b/tools/utils.py
@@ -77,12 +77,24 @@
       'third_party', 'openjdk', 'desugar_jdk_libs', 'desugar_jdk_libs.jar')
 DESUGAR_CONFIGURATION_JDK11_LEGACY = os.path.join(
       'src', 'library_desugar', 'jdk11', 'desugar_jdk_libs_legacy.json')
+DESUGAR_CONFIGURATION_JDK11_MINIMAL = os.path.join(
+      'src', 'library_desugar', 'jdk11', 'desugar_jdk_libs_minimal.json')
+DESUGAR_CONFIGURATION_JDK11 = os.path.join(
+      'src', 'library_desugar', 'jdk11', 'desugar_jdk_libs.json')
+DESUGAR_CONFIGURATION_JDK11_NIO = os.path.join(
+      'src', 'library_desugar', 'jdk11', 'desugar_jdk_libs_nio.json')
 DESUGAR_IMPLEMENTATION_JDK11 = os.path.join(
       'third_party', 'openjdk', 'desugar_jdk_libs_11', 'desugar_jdk_libs.jar')
 DESUGAR_CONFIGURATION_MAVEN_ZIP = os.path.join(
   LIBS, 'desugar_jdk_libs_configuration.zip')
 DESUGAR_CONFIGURATION_JDK11_LEGACY_MAVEN_ZIP = os.path.join(
   LIBS, 'desugar_jdk_libs_configuration_jdk11_legacy.zip')
+DESUGAR_CONFIGURATION_JDK11_MINIMAL_MAVEN_ZIP = os.path.join(
+  LIBS, 'desugar_jdk_libs_configuration_jdk11_minimal.zip')
+DESUGAR_CONFIGURATION_JDK11_MAVEN_ZIP = os.path.join(
+  LIBS, 'desugar_jdk_libs_configuration_jdk11.zip')
+DESUGAR_CONFIGURATION_JDK11_NIO_MAVEN_ZIP = os.path.join(
+  LIBS, 'desugar_jdk_libs_configuration_jdk11_nio.zip')
 GENERATED_LICENSE = os.path.join(GENERATED_LICENSE_DIR, 'LICENSE')
 RT_JAR = os.path.join(REPO_ROOT, 'third_party/openjdk/openjdk-rt-1.8/rt.jar')
 R8LIB_KEEP_RULES = os.path.join(REPO_ROOT, 'src/main/keep.txt')
@@ -626,17 +638,48 @@
   # so we split on '('; clean up tailing spaces; and strip off 'R8 '.
   return output.split('(')[0].strip()[3:]
 
-def desugar_configuration_version(configuration):
+def desugar_configuration_name_and_version(configuration, is_for_maven):
+  name = 'desugar_jdk_libs_configuration'
   with open(configuration, 'r') as f:
     configuration_json = json.loads(f.read())
     configuration_format_version = \
         configuration_json.get('configuration_format_version')
+    if (not configuration_format_version):
+        raise Exception(
+            'No "configuration_format_version" found in ' + configuration)
+    if (configuration_format_version != 3
+        and configuration_format_version != 5
+        and configuration_format_version != (200 if is_for_maven else 100)):
+          raise Exception(
+              'Unsupported "configuration_format_version" "%s" found in %s'
+              % (configuration_format_version, configuration))
     version = configuration_json.get('version')
     if not version:
-      raise Exception(
-          'No "version" found in ' + configuration)
-    check_basic_semver_version(version, 'in ' + configuration, allowPrerelease = True)
-    return version
+      if configuration_format_version == (200 if is_for_maven else 100):
+        identifier = configuration_json.get('identifier')
+        if not identifier:
+          raise Exception(
+              'No "identifier" found in ' + configuration)
+        identifier_split = identifier.split(':')
+        if (len(identifier_split) != 3):
+          raise Exception('Invalid "identifier" found in ' + configuration)
+        if (identifier_split[0] != 'com.tools.android'):
+          raise Exception('Invalid "identifier" found in ' + configuration)
+        if not identifier_split[1].startswith('desugar_jdk_libs_configuration'):
+          raise Exception('Invalid "identifier" found in ' + configuration)
+        name = identifier_split[1]
+        version = identifier_split[2]
+      else:
+        raise Exception(
+            'No "version" found in ' + configuration)
+    else:
+      if configuration_format_version == (200 if is_for_maven else 100):
+        raise Exception(
+            'No "version" expected in ' + configuration)
+    # Disallow prerelease, as older R8 versions cannot parse it causing hard to
+    # understand errors.
+    check_basic_semver_version(version, 'in ' + configuration, allowPrerelease = False)
+    return (name, version)
 
 class SemanticVersion:
   def __init__(self, major, minor, patch, prerelease):