blob: 6f6306e3b67b677f5660761dec19ced6c996dea7 [file] [log] [blame]
Laszlo Csomor527ff1f2017-10-24 14:37:07 +02001# pylint: disable=g-direct-third-party-import
Adam Michael6a87bd42016-10-25 19:37:41 +00002# Copyright 2016 The Bazel Authors. All rights reserved.
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15
16"""A tool for extracting native libs from an AAR into a zip.
17
18The native libs for the requested cpu will be extracted into a zip. The paths
19are converted from the AAR directory structure of /jni/<cpu>/foo.so to the APK
20directory structure of /lib/<cpu>/foo.so.
21"""
22
Laszlo Csomor527ff1f2017-10-24 14:37:07 +020023import os
Adam Michael6a87bd42016-10-25 19:37:41 +000024import re
25import sys
26import zipfile
27
laszlocsomord93a1462019-11-04 09:14:39 -080028# Do not edit this line. Copybara replaces it with PY2 migration helper.
29from absl import app
30from absl import flags
laszlocsomord93a1462019-11-04 09:14:39 -080031
Googler74bc0462023-08-17 13:39:43 -070032from tools.android import json_worker_wrapper
Laszlo Csomor527ff1f2017-10-24 14:37:07 +020033from tools.android import junction
Adam Michael6a87bd42016-10-25 19:37:41 +000034
laszlocsomord93a1462019-11-04 09:14:39 -080035FLAGS = flags.FLAGS
Adam Michael6a87bd42016-10-25 19:37:41 +000036
laszlocsomord93a1462019-11-04 09:14:39 -080037flags.DEFINE_string("input_aar", None, "Input AAR")
38flags.mark_flag_as_required("input_aar")
39flags.DEFINE_string("cpu", None, "CPU architecture to include")
40flags.mark_flag_as_required("cpu")
41flags.DEFINE_string("output_zip", None, "Output ZIP of native libs")
42flags.mark_flag_as_required("output_zip")
Adam Michael6a87bd42016-10-25 19:37:41 +000043
44
Googlerd0620d12023-08-04 12:47:24 -070045class UnsupportedArchitectureError(Exception):
Laszlo Csomor527ff1f2017-10-24 14:37:07 +020046 """Exception thrown when an AAR does not support the requested CPU."""
Adam Michael6a87bd42016-10-25 19:37:41 +000047 pass
48
49
50def CreateNativeLibsZip(aar, cpu, native_libs_zip):
Googlerd0620d12023-08-04 12:47:24 -070051 """Creates a zip containing native libs for the requested CPU.
52
53 Args:
54 aar: aar file to extract
55 cpu: The requested CPU architecture
56 native_libs_zip: The zip file to package native libs into.
57
58 Raises:
59 UnsupportedArchitectureError: CPU architecture is invalid.
60 """
Adam Michael6a87bd42016-10-25 19:37:41 +000061 native_lib_pattern = re.compile("^jni/.+/.+\\.so$")
62 if any(native_lib_pattern.match(filename) for filename in aar.namelist()):
Googler56195ef2022-08-22 08:31:18 -070063 cpu_pattern = re.compile("^jni/" + cpu + "/.+\\.so$")
Adam Michael6a87bd42016-10-25 19:37:41 +000064 libs = [name for name in aar.namelist() if cpu_pattern.match(name)]
65 if not libs:
Googlerd0620d12023-08-04 12:47:24 -070066 raise UnsupportedArchitectureError()
Adam Michael6a87bd42016-10-25 19:37:41 +000067 for lib in libs:
68 # Only replaces the first instance of jni, in case the AAR contains
69 # something like /jni/x86/jni.so.
70 new_filename = lib.replace("jni", "lib", 1)
Nick Korostelev85ab3742020-12-03 14:53:39 -080071 # To guarantee reproducible zips we must specify a new zipinfo.
72 # From writestr docs: "If its a name, the date and time is set to the
73 # current date and time." which will break the HASH calculation and result
74 # in a cache miss.
75 old_zipinfo = aar.getinfo(lib)
76 new_zipinfo = zipfile.ZipInfo(filename=new_filename)
77 new_zipinfo.date_time = old_zipinfo.date_time
78 new_zipinfo.compress_type = old_zipinfo.compress_type
79
80 native_libs_zip.writestr(new_zipinfo, aar.read(lib))
Adam Michael6a87bd42016-10-25 19:37:41 +000081
82
Laszlo Csomor527ff1f2017-10-24 14:37:07 +020083def Main(input_aar_path, output_zip_path, cpu, input_aar_path_for_error_msg):
84 with zipfile.ZipFile(input_aar_path, "r") as input_aar:
85 with zipfile.ZipFile(output_zip_path, "w") as native_libs_zip:
Adam Michael6a87bd42016-10-25 19:37:41 +000086 try:
Laszlo Csomor527ff1f2017-10-24 14:37:07 +020087 CreateNativeLibsZip(input_aar, cpu, native_libs_zip)
Googlerd0620d12023-08-04 12:47:24 -070088 except UnsupportedArchitectureError:
Googler56195ef2022-08-22 08:31:18 -070089 print("AAR " + input_aar_path_for_error_msg +
laszlocsomord93a1462019-11-04 09:14:39 -080090 " missing native libs for requested architecture: " +
Googler56195ef2022-08-22 08:31:18 -070091 cpu)
Adam Michael6a87bd42016-10-25 19:37:41 +000092 sys.exit(1)
93
94
laszlocsomord93a1462019-11-04 09:14:39 -080095def main(unused_argv):
Laszlo Csomor527ff1f2017-10-24 14:37:07 +020096 if os.name == "nt":
97 with junction.TempJunction(os.path.dirname(FLAGS.input_aar)) as j_in:
98 with junction.TempJunction(os.path.dirname(FLAGS.output_zip)) as j_out:
99 Main(
100 os.path.join(j_in, os.path.basename(FLAGS.input_aar)),
101 os.path.join(j_out, os.path.basename(FLAGS.output_zip)), FLAGS.cpu,
102 FLAGS.input_aar)
103 else:
104 Main(FLAGS.input_aar, FLAGS.output_zip, FLAGS.cpu, FLAGS.input_aar)
105
106
Adam Michael6a87bd42016-10-25 19:37:41 +0000107if __name__ == "__main__":
Googler74bc0462023-08-17 13:39:43 -0700108 json_worker_wrapper.wrap_worker(FLAGS, main, app.run)