# pylint: disable=g-direct-third-party-import # Copyright 2016 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """A tool for extracting all jar files from an AAR. An AAR may contain JARs at /classes.jar and /libs/*.jar. This tool extracts all of the jars and creates a param file for singlejar to merge them into one jar. """ import os import re import sys import zipfile from tools.android import junction from third_party.py import gflags FLAGS = gflags.FLAGS gflags.DEFINE_string("input_aar", None, "Input AAR") gflags.MarkFlagAsRequired("input_aar") gflags.DEFINE_string( "output_singlejar_param_file", None, "Output parameter file for singlejar") gflags.MarkFlagAsRequired("output_singlejar_param_file") gflags.DEFINE_string("output_dir", None, "Output directory to extract jars in") gflags.MarkFlagAsRequired("output_dir") def ExtractEmbeddedJars(aar, singlejar_param_file, output_dir, output_dir_orig=None): if not output_dir_orig: output_dir_orig = output_dir jar_pattern = re.compile("^(classes|libs/.+)\\.jar$") singlejar_param_file.write(b"--exclude_build_data\n") for name in aar.namelist(): if jar_pattern.match(name): singlejar_param_file.write(b"--sources\n") # output_dir may be a temporary junction, so write the original # (unshortened) path to the params file singlejar_param_file.write( (output_dir_orig + "/" + name + "\n").encode("utf-8")) aar.extract(name, output_dir) def _Main(input_aar, output_singlejar_param_file, output_dir, output_dir_orig=None): if not output_dir_orig: output_dir_orig = output_dir with zipfile.ZipFile(input_aar, "r") as aar: with open(output_singlejar_param_file, "wb") as singlejar_param_file: ExtractEmbeddedJars(aar, singlejar_param_file, output_dir, output_dir_orig) def main(): if os.name == "nt": # Shorten paths unconditionally, because the extracted paths in # ExtractEmbeddedJars (which we cannot yet predict, because they depend on # the names of the Zip entries) may be longer than MAX_PATH. aar_long = os.path.abspath(FLAGS.input_aar) params_long = os.path.abspath(FLAGS.output_singlejar_param_file) out_long = os.path.abspath(FLAGS.output_dir) with junction.TempJunction(os.path.dirname(aar_long)) as aar_junc: with junction.TempJunction(os.path.dirname(params_long)) as params_junc: with junction.TempJunction(os.path.dirname(out_long)) as out_junc: _Main( os.path.join(aar_junc, os.path.basename(aar_long)), os.path.join(params_junc, os.path.basename(params_long)), os.path.join(out_junc, os.path.basename(out_long)), FLAGS.output_dir) else: _Main(FLAGS.input_aar, FLAGS.output_singlejar_param_file, FLAGS.output_dir) if __name__ == "__main__": FLAGS(sys.argv) main()