| # 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() |