aboutsummaryrefslogtreecommitdiff
path: root/rules/staging_dir_builder.py
diff options
context:
space:
mode:
authorJingwen Chen <jingwen@google.com>2022-11-03 10:47:48 +0000
committerJingwen Chen <jingwen@google.com>2022-11-07 10:54:33 +0000
commita9d9eb6acd5a5aea80985a01344140b95a1ee3ab (patch)
tree9b752d56e4e8f4f793d5ab397f9f955220eed86d /rules/staging_dir_builder.py
parentbab6ebf390310f3a33436b11267de84790f02316 (diff)
downloadbazel-a9d9eb6acd5a5aea80985a01344140b95a1ee3ab.tar.gz
bazel apex: add support for generating _using.txt file.
This file contains NDK function symbols dynamically used by an APEX's shared libraries. The shared cc_stub_library should be linked with the --version-script argument with the stub map file created by ndkstubgen, but isn't currently done, so the generated stub so had unversioned symbols. This CL passes the stub map into the linker args and additional linker inputs for the cc_shared_library action. Additionally, the using.txt generation script operates on a staging directory, so this CL extends the staging dir builder action to also return a directory (TreeArtifact) to be used as an input to the script. Mixed builds integration to come in a follow up CL. Test: new golden test Test: analysis test Test: presubmit Bug: 239081455 Bug: 257226023 Fixes: 257226023 Change-Id: I5e83caa43ad50646db0e7d25eed5f2d75b47535a
Diffstat (limited to 'rules/staging_dir_builder.py')
-rw-r--r--rules/staging_dir_builder.py137
1 files changed, 73 insertions, 64 deletions
diff --git a/rules/staging_dir_builder.py b/rules/staging_dir_builder.py
index 6961c760..a5bcee9e 100644
--- a/rules/staging_dir_builder.py
+++ b/rules/staging_dir_builder.py
@@ -19,32 +19,26 @@ import os
import shutil
import subprocess
import sys
-import tempfile
+import argparse
-def main(argv):
- '''Build a staging directory, and then call a custom command.
+def build_staging_dir(file_mapping_path, staging_dir_path, command_argv):
+ '''Create a staging dir with provided file mapping and apply the command in the dir.
- The first argument to this script must be the path to a file containing a json
- dictionary mapping paths in the staging directory to paths to files that should
- be copied there. The rest of the arguments will be run as a separate command.
- At least one other argument must be "STAGING_DIR_PLACEHOLDER", which will be
- replaced with the path to the staging directory.
+ At least
- Example:
- staging_dir_builder file_mapping.json path/to/apexer --various-apexer-flags STAGING_DIR_PLACEHOLDER path/to/out.apex.unsigned
+ Args:
+ file_mapping_path (str): path to the file mapping json
+ staging_dir_path (str): path to the staging directory
+ command_argv (str list): the command to be executed, with the first arg as the executable
'''
- if len(argv) < 2:
- sys.exit('usage: staging_dir_builder MAPPING_FILE COMMAND...')
- if "STAGING_DIR_PLACEHOLDER" not in argv[1:]:
- sys.exit('At least one argument must be "STAGING_DIR_PLACEHOLDER"')
try:
- with open(argv[0], 'r') as f:
+ with open(file_mapping_path, 'r') as f:
file_mapping = json.load(f)
except OSError as e:
sys.exit(str(e))
except json.JSONDecodeError as e:
- sys.exit(argv[0] + ": JSON decode error: " + str(e))
+ sys.exit(file_mapping_path + ": JSON decode error: " + str(e))
# Validate and clean the file_mapping. This consists of:
# - Making sure it's a dict[str, str]
@@ -53,10 +47,10 @@ def main(argv):
# - Making sure no paths use .. to break out of the staging dir
cleaned_file_mapping = {}
if not isinstance(file_mapping, dict):
- sys.exit(argv[0] + ": expected a JSON dict[str, str]")
+ sys.exit(file_mapping_path + ": expected a JSON dict[str, str]")
for path_in_staging_dir, path_in_bazel in file_mapping.items():
if not isinstance(path_in_staging_dir, str) or not isinstance(path_in_bazel, str):
- sys.exit(argv[0] + ": expected a JSON dict[str, str]")
+ sys.exit(file_mapping_path + ": expected a JSON dict[str, str]")
path_in_staging_dir = os.path.normpath(path_in_staging_dir).lstrip('/')
if path_in_staging_dir in cleaned_file_mapping:
sys.exit("Staging dir path repeated twice: " + path_in_staging_dir)
@@ -65,57 +59,72 @@ def main(argv):
cleaned_file_mapping[path_in_staging_dir] = path_in_bazel
file_mapping = cleaned_file_mapping
- argv = argv[1:]
-
- with tempfile.TemporaryDirectory() as staging_dir:
- for path_in_staging_dir, path_in_bazel in file_mapping.items():
- path_in_staging_dir = os.path.join(staging_dir, path_in_staging_dir)
-
- # Because Bazel execution root is a symlink forest, all the input files are symlinks, these
- # include the dependency files declared in the BUILD files as well as the files declared
- # and created in the bzl files. For sandbox runs the former are two or more level symlinks and
- # latter are one level symlinks. For non-sandbox runs, the former are one level symlinks
- # and the latter are actual files. Here are some examples:
- #
- # Two level symlinks:
- # system/timezone/output_data/version/tz_version ->
- # /usr/local/google/home/...out/bazel/output_user_root/b1ed7e1e9af3ebbd1403e9cf794e4884/
- # execroot/__main__/system/timezone/output_data/version/tz_version ->
- # /usr/local/google/home/.../system/timezone/output_data/version/tz_version
- #
- # Three level symlinks:
- # bazel-out/android_x86_64-fastbuild-ST-4ecd5e98bfdd/bin/external/boringssl/libcrypto.so ->
- # /usr/local/google/home/yudiliu/android/aosp/master/out/bazel/output_user_root/b1ed7e1e9af3ebbd1403e9cf794e4884/
- # execroot/__main__/bazel-out/android_x86_64-fastbuild-ST-4ecd5e98bfdd/bin/external/boringssl/libcrypto.so ->
- # /usr/local/google/home/yudiliu/android/aosp/master/out/bazel/output_user_root/b1ed7e1e9af3ebbd1403e9cf794e4884/
- # execroot/__main__/bazel-out/android_x86_64-fastbuild-ST-4ecd5e98bfdd/bin/external/boringssl/
- # liblibcrypto_stripped.so ->
- # /usr/local/google/home/yudiliu/android/aosp/master/out/bazel/output_user_root/b1ed7e1e9af3ebbd1403e9cf794e4884/
- # execroot/__main__/bazel-out/android_x86_64-fastbuild-ST-4ecd5e98bfdd/bin/external/boringssl/
- # liblibcrypto_unstripped.so
- #
- # One level symlinks:
- # bazel-out/android_target-fastbuild/bin/system/timezone/apex/apex_manifest.pb ->
- # /usr/local/google/home/.../out/bazel/output_user_root/b1ed7e1e9af3ebbd1403e9cf794e4884/
- # execroot/__main__/bazel-out/android_target-fastbuild/bin/system/timezone/apex/
- # apex_manifest.pb
- if os.path.islink(path_in_bazel):
- path_in_bazel = os.readlink(path_in_bazel)
+ for path_in_staging_dir, path_in_bazel in file_mapping.items():
+ path_in_staging_dir = os.path.join(staging_dir_path, path_in_staging_dir)
- # For sandbox run these are the 2nd level symlinks and we need to resolve
- while os.path.islink(path_in_bazel) and 'execroot/__main__' in path_in_bazel:
- path_in_bazel = os.readlink(path_in_bazel)
+ # Because Bazel execution root is a symlink forest, all the input files are symlinks, these
+ # include the dependency files declared in the BUILD files as well as the files declared
+ # and created in the bzl files. For sandbox runs the former are two or more level symlinks and
+ # latter are one level symlinks. For non-sandbox runs, the former are one level symlinks
+ # and the latter are actual files. Here are some examples:
+ #
+ # Two level symlinks:
+ # system/timezone/output_data/version/tz_version ->
+ # /usr/local/google/home/...out/bazel/output_user_root/b1ed7e1e9af3ebbd1403e9cf794e4884/
+ # execroot/__main__/system/timezone/output_data/version/tz_version ->
+ # /usr/local/google/home/.../system/timezone/output_data/version/tz_version
+ #
+ # Three level symlinks:
+ # bazel-out/android_x86_64-fastbuild-ST-4ecd5e98bfdd/bin/external/boringssl/libcrypto.so ->
+ # /usr/local/google/home/yudiliu/android/aosp/master/out/bazel/output_user_root/b1ed7e1e9af3ebbd1403e9cf794e4884/
+ # execroot/__main__/bazel-out/android_x86_64-fastbuild-ST-4ecd5e98bfdd/bin/external/boringssl/libcrypto.so ->
+ # /usr/local/google/home/yudiliu/android/aosp/master/out/bazel/output_user_root/b1ed7e1e9af3ebbd1403e9cf794e4884/
+ # execroot/__main__/bazel-out/android_x86_64-fastbuild-ST-4ecd5e98bfdd/bin/external/boringssl/
+ # liblibcrypto_stripped.so ->
+ # /usr/local/google/home/yudiliu/android/aosp/master/out/bazel/output_user_root/b1ed7e1e9af3ebbd1403e9cf794e4884/
+ # execroot/__main__/bazel-out/android_x86_64-fastbuild-ST-4ecd5e98bfdd/bin/external/boringssl/
+ # liblibcrypto_unstripped.so
+ #
+ # One level symlinks:
+ # bazel-out/android_target-fastbuild/bin/system/timezone/apex/apex_manifest.pb ->
+ # /usr/local/google/home/.../out/bazel/output_user_root/b1ed7e1e9af3ebbd1403e9cf794e4884/
+ # execroot/__main__/bazel-out/android_target-fastbuild/bin/system/timezone/apex/
+ # apex_manifest.pb
+ if os.path.islink(path_in_bazel):
+ path_in_bazel = os.readlink(path_in_bazel)
- os.makedirs(os.path.dirname(path_in_staging_dir), exist_ok=True)
- shutil.copyfile(path_in_bazel, path_in_staging_dir, follow_symlinks=False)
+ # For sandbox run these are the 2nd level symlinks and we need to resolve
+ while os.path.islink(path_in_bazel) and 'execroot/__main__' in path_in_bazel:
+ path_in_bazel = os.readlink(path_in_bazel)
- for i in range(len(argv)):
- if argv[i] == 'STAGING_DIR_PLACEHOLDER':
- argv[i] = staging_dir
+ os.makedirs(os.path.dirname(path_in_staging_dir), exist_ok=True)
+ shutil.copyfile(path_in_bazel, path_in_staging_dir, follow_symlinks=False)
- result = subprocess.run(argv)
+ result = subprocess.run(command_argv)
sys.exit(result.returncode)
+def main():
+ '''Build a staging directory, and then call a custom command.
+
+ The first argument to this script must be the path to a file containing a json
+ dictionary mapping paths in the staging directory to paths to files that should
+ be copied there. The rest of the arguments will be run as a separate command.
+
+ Example:
+ staging_dir_builder file_mapping.json path/to/staging_dir path/to/apexer --various-apexer-flags path/to/out.apex.unsigned
+ '''
+ parser = argparse.ArgumentParser()
+ parser.add_argument(
+ "file_mapping_path",
+ help="Path to the <staging dir path>:<bazel input path> file mapping JSON.",
+ )
+ parser.add_argument(
+ "staging_dir_path",
+ help="Path to a directory to store the staging directory content.",
+ )
+ args, command_argv = parser.parse_known_args()
+ build_staging_dir(args.file_mapping_path, args.staging_dir_path, command_argv)
+
if __name__ == '__main__':
- main(sys.argv[1:])
+ main()