xref: /aosp_15_r20/build/bazel/scripts/difftool/collect.py (revision 7594170e27e0732bc44b93d1440d87a54b6ffe7c)
1#!/usr/bin/env python3
2#
3# Copyright (C) 2021 The Android Open Source Project
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9#   http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16
17"""Copies ninja file information to another directory for processing.
18
19Usage:
20  ./collect.py [ninja_file] [dest_directory]
21
22This script should be used as in preparation for further analysis
23using difftool.py. See directory-level README for details.
24"""
25
26import argparse
27import os
28import pathlib
29import shutil
30
31
32COLLECTION_INFO_FILENAME = "collection_info"
33
34
35def subninja_files(ninja_file_path):
36  result = []
37  with ninja_file_path.open() as f:
38    for line in f:
39      if line.startswith("subninja "):
40        result += [line[len("subninja "):].strip()]
41  return result
42
43
44def main():
45  parser = argparse.ArgumentParser(description="")
46  parser.add_argument("ninja_file",
47                      help="the path to the root ninja file of the build " +
48                           "to be analyzed. Ex: out/combined-aosp_flame.ninja")
49  parser.add_argument("dest_directory",
50                      help="directory to copy build-related information for " +
51                           "later difftool comparison. Ex: /tmp/buildArtifacts")
52  # TODO(usta): enable multiple files or even a glob to be specified
53  parser.add_argument("--file", dest="output_file", default=None,
54                      help="the path to the output artifact to be analyzed. " +
55                           "Ex: out/path/to/foo.so")
56  args = parser.parse_args()
57  dest = args.dest_directory
58
59  if not os.path.isdir(dest):
60    raise Exception("invalid destination directory " + dest)
61
62  collection_info_filepath = ""
63  if args.output_file is not None:
64    output_file = pathlib.Path(args.output_file)
65    if not output_file.is_file():
66      raise Exception("Expected file %s was not found. " % output_file)
67    output_file_dest = pathlib.Path(dest).joinpath(output_file)
68    output_file_dest.parent.mkdir(parents=True, exist_ok=True)
69    shutil.copy2(output_file, output_file_dest)
70    collection_info_filepath = str(output_file)
71
72  ninja_file = pathlib.Path(args.ninja_file)
73  main_ninja_basename = ninja_file.name
74  shutil.copy2(args.ninja_file, os.path.join(dest, main_ninja_basename))
75
76  for subninja_file in subninja_files(ninja_file):
77    parent_dir = pathlib.Path(subninja_file).parent
78    dest_dir = os.path.join(dest, parent_dir)
79    pathlib.Path(dest_dir).mkdir(parents=True, exist_ok=True)
80    shutil.copy2(subninja_file, os.path.join(dest, subninja_file))
81
82  collection_info = main_ninja_basename + "\n" + collection_info_filepath
83  pathlib.Path(dest).joinpath(COLLECTION_INFO_FILENAME).write_text(collection_info)
84
85
86if __name__ == "__main__":
87  main()
88