summaryrefslogtreecommitdiff
path: root/deps/v8/build/config/fuchsia/prepare_package_inputs.py
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/build/config/fuchsia/prepare_package_inputs.py')
-rw-r--r--deps/v8/build/config/fuchsia/prepare_package_inputs.py220
1 files changed, 220 insertions, 0 deletions
diff --git a/deps/v8/build/config/fuchsia/prepare_package_inputs.py b/deps/v8/build/config/fuchsia/prepare_package_inputs.py
new file mode 100644
index 0000000000..078c3cb266
--- /dev/null
+++ b/deps/v8/build/config/fuchsia/prepare_package_inputs.py
@@ -0,0 +1,220 @@
+# Copyright 2018 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Creates a archive manifest used for Fuchsia package generation."""
+
+import argparse
+import json
+import os
+import re
+import subprocess
+import sys
+import tempfile
+
+
+def MakePackagePath(file_path, roots):
+ """Computes a path for |file_path| that is relative to one of the directory
+ paths in |roots|.
+
+ file_path: The file path to relativize.
+ roots: A list of directory paths which may serve as a relative root
+ for |file_path|.
+
+ Examples:
+
+ >>> MakePackagePath('/foo/bar.txt', ['/foo/'])
+ 'bar.txt'
+
+ >>> MakePackagePath('/foo/dir/bar.txt', ['/foo/'])
+ 'dir/bar.txt'
+
+ >>> MakePackagePath('/foo/out/Debug/bar.exe', ['/foo/', '/foo/out/Debug/'])
+ 'bar.exe'
+ """
+
+ # Prevents greedily matching against a shallow path when a deeper, better
+ # matching path exists.
+ roots.sort(key=len, reverse=True)
+
+ for next_root in roots:
+ if not next_root.endswith(os.sep):
+ next_root += os.sep
+
+ if file_path.startswith(next_root):
+ relative_path = file_path[len(next_root):]
+
+ return relative_path
+
+ return file_path
+
+
+def _GetStrippedPath(bin_path):
+ """Finds the stripped version of the binary |bin_path| in the build
+ output directory."""
+
+ return bin_path.replace('lib.unstripped/', 'lib/').replace(
+ 'exe.unstripped/', '')
+
+
+def _IsBinary(path):
+ """Checks if the file at |path| is an ELF executable by inspecting its FourCC
+ header."""
+
+ with open(path, 'rb') as f:
+ file_tag = f.read(4)
+ return file_tag == '\x7fELF'
+
+
+def _WriteBuildIdsTxt(binary_paths, ids_txt_path):
+ """Writes an index text file that maps build IDs to the paths of unstripped
+ binaries."""
+
+ READELF_FILE_PREFIX = 'File: '
+ READELF_BUILD_ID_PREFIX = 'Build ID: '
+
+ # List of binaries whose build IDs are awaiting processing by readelf.
+ # Entries are removed as readelf's output is parsed.
+ unprocessed_binary_paths = {os.path.basename(p): p for p in binary_paths}
+
+ with open(ids_txt_path, 'w') as ids_file:
+ readelf_stdout = subprocess.check_output(
+ ['readelf', '-n'] + map(_GetStrippedPath, binary_paths))
+
+ if len(binary_paths) == 1:
+ # Readelf won't report a binary's path if only one was provided to the
+ # tool.
+ binary_shortname = os.path.basename(binary_paths[0])
+ else:
+ binary_shortname = None
+
+ for line in readelf_stdout.split('\n'):
+ line = line.strip()
+
+ if line.startswith(READELF_FILE_PREFIX):
+ binary_shortname = os.path.basename(line[len(READELF_FILE_PREFIX):])
+ assert binary_shortname in unprocessed_binary_paths
+
+ elif line.startswith(READELF_BUILD_ID_PREFIX):
+ # Paths to the unstripped executables listed in "ids.txt" are specified
+ # as relative paths to that file.
+ unstripped_rel_path = os.path.relpath(
+ os.path.abspath(unprocessed_binary_paths[binary_shortname]),
+ os.path.dirname(os.path.abspath(ids_txt_path)))
+
+ build_id = line[len(READELF_BUILD_ID_PREFIX):]
+ ids_file.write(build_id + ' ' + unstripped_rel_path + '\n')
+ del unprocessed_binary_paths[binary_shortname]
+
+ # Did readelf forget anything? Make sure that all binaries are accounted for.
+ assert not unprocessed_binary_paths
+
+
+def BuildManifest(args):
+ binaries = []
+ with open(args.manifest_path, 'w') as manifest, \
+ open(args.depfile_path, 'w') as depfile:
+ # Process the runtime deps file for file paths, recursively walking
+ # directories as needed.
+ # MakePackagePath() may relativize to either the source root or output
+ # directory.
+ # runtime_deps may contain duplicate paths, so use a set for
+ # de-duplication.
+ expanded_files = set()
+ for next_path in open(args.runtime_deps_file, 'r'):
+ next_path = next_path.strip()
+ if os.path.isdir(next_path):
+ for root, _, files in os.walk(next_path):
+ for current_file in files:
+ if current_file.startswith('.'):
+ continue
+ expanded_files.add(
+ os.path.join(root, current_file))
+ else:
+ expanded_files.add(next_path)
+
+ # Format and write out the manifest contents.
+ gen_dir = os.path.normpath(os.path.join(args.out_dir, "gen"))
+ app_found = False
+ excluded_files_set = set(args.exclude_file)
+ for current_file in expanded_files:
+ if _IsBinary(current_file):
+ binaries.append(current_file)
+ current_file = _GetStrippedPath(current_file)
+
+ in_package_path = MakePackagePath(current_file,
+ [gen_dir, args.root_dir, args.out_dir])
+ if in_package_path == args.app_filename:
+ app_found = True
+
+ if in_package_path in excluded_files_set:
+ excluded_files_set.remove(in_package_path)
+ continue
+
+ manifest.write('%s=%s\n' % (in_package_path, current_file))
+
+ if len(excluded_files_set) > 0:
+ raise Exception('Some files were excluded with --exclude-file, but '
+ 'not found in the deps list: %s' %
+ ', '.join(excluded_files_set));
+
+ if not app_found:
+ raise Exception('Could not locate executable inside runtime_deps.')
+
+ # Write meta/package manifest file.
+ with open(os.path.join(os.path.dirname(args.manifest_path), 'package'),
+ 'w') as package_json:
+ json.dump({'version': '0', 'name': args.app_name}, package_json)
+ manifest.write('meta/package=%s\n' %
+ os.path.relpath(package_json.name, args.out_dir))
+
+ # Write component manifest file.
+ cmx_file_path = os.path.join(os.path.dirname(args.manifest_path),
+ args.app_name + '.cmx')
+ with open(cmx_file_path, 'w') as component_manifest_file:
+ component_manifest = {
+ 'program': { 'binary': args.app_filename },
+ 'sandbox': json.load(open(args.sandbox_policy_path, 'r')),
+ }
+ json.dump(component_manifest, component_manifest_file)
+
+ manifest.write('meta/%s=%s\n' %
+ (os.path.basename(component_manifest_file.name),
+ os.path.relpath(cmx_file_path, args.out_dir)))
+
+ depfile.write(
+ "%s: %s" % (os.path.relpath(args.manifest_path, args.out_dir),
+ " ".join([os.path.relpath(f, args.out_dir)
+ for f in expanded_files])))
+
+ _WriteBuildIdsTxt(binaries, args.build_ids_file)
+
+ return 0
+
+
+def main():
+ parser = argparse.ArgumentParser()
+ parser.add_argument('--root-dir', required=True, help='Build root directory')
+ parser.add_argument('--out-dir', required=True, help='Build output directory')
+ parser.add_argument('--app-name', required=True, help='Package name')
+ parser.add_argument('--app-filename', required=True,
+ help='Path to the main application binary relative to the output dir.')
+ parser.add_argument('--sandbox-policy-path', required=True,
+ help='Path to the sandbox policy file relative to the output dir.')
+ parser.add_argument('--runtime-deps-file', required=True,
+ help='File with the list of runtime dependencies.')
+ parser.add_argument('--depfile-path', required=True,
+ help='Path to write GN deps file.')
+ parser.add_argument('--exclude-file', action='append', default=[],
+ help='Package-relative file path to exclude from the package.')
+ parser.add_argument('--manifest-path', required=True,
+ help='Manifest output path.')
+ parser.add_argument('--build-ids-file', required=True,
+ help='Debug symbol index path.')
+
+ args = parser.parse_args()
+
+ return BuildManifest(args)
+
+if __name__ == '__main__':
+ sys.exit(main())