• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python3
2#
3# Copyright (C) 2022 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"""Utility functions to produce module or module type dependency graphs using json-module-graph or queryview."""
17
18import json
19import os
20import os.path
21import subprocess
22import xml.etree.ElementTree
23
24# This list of module types are omitted from the report and graph
25# for brevity and simplicity. Presence in this list doesn't mean
26# that they shouldn't be converted, but that they are not that useful
27# to be recorded in the graph or report currently.
28IGNORED_KINDS = set([
29    "license_kind",
30    "license",
31    "cc_defaults",
32    "cc_prebuilt_object",
33    "cc_prebuilt_library_headers",
34    "cc_prebuilt_library_shared",
35    "cc_prebuilt_library_static",
36    "cc_prebuilt_library_static",
37    "cc_prebuilt_library",
38    "java_defaults",
39    "ndk_prebuilt_static_stl",
40    "ndk_library",
41])
42
43SRC_ROOT_DIR = os.path.abspath(__file__ + "/../../../../..")
44
45
46def _build_with_soong(target):
47  subprocess.check_output(
48      [
49          "build/soong/soong_ui.bash",
50          "--make-mode",
51          "--skip-soong-tests",
52          target,
53      ],
54      cwd=SRC_ROOT_DIR,
55      env={
56          # Use aosp_arm as the canonical target product.
57          "TARGET_PRODUCT": "aosp_arm",
58          "TARGET_BUILD_VARIANT": "userdebug",
59      },
60  )
61
62
63def get_queryview_module_info(module):
64  """Returns the list of transitive dependencies of input module as built by queryview."""
65  _build_with_soong("queryview")
66
67  result = subprocess.check_output(
68      [
69          "tools/bazel", "query", "--config=ci", "--config=queryview",
70          "--output=xml",
71          'deps(attr("soong_module_name", "^{}$", //...))'.format(module)
72      ],
73      cwd=SRC_ROOT_DIR,
74  )
75  return xml.etree.ElementTree.fromstring(result)
76
77
78def get_json_module_info(module):
79  """Returns the list of transitive dependencies of input module as provided by Soong's json module graph."""
80  _build_with_soong("json-module-graph")
81  # Run query.sh on the module graph for the top level module
82  result = subprocess.check_output(
83      [
84          "build/bazel/json_module_graph/query.sh", "fullTransitiveDeps",
85          "out/soong/module-graph.json", module
86      ],
87      cwd=SRC_ROOT_DIR,
88  )
89  return json.loads(result)
90
91
92def get_bp2build_converted_modules():
93  """ Returns the list of modules that bp2build can currently convert. """
94  _build_with_soong("bp2build")
95  # Parse the list of converted module names from bp2build
96  with open(
97      os.path.join(
98          SRC_ROOT_DIR,
99          "out/soong/soong_injection/metrics/converted_modules.txt")) as f:
100    # Read line by line, excluding comments.
101    # Each line is a module name.
102    ret = [line.strip() for line in f.readlines() if not line.startswith("#")]
103  return set(ret)
104
105
106def get_json_module_type_info(module_type):
107  """Returns the combined transitive dependency closures of all modules of module_type."""
108  _build_with_soong("json-module-graph")
109  # Run query.sh on the module graph for the top level module type
110  result = subprocess.check_output(
111      [
112          "build/bazel/json_module_graph/query.sh",
113          "fullTransitiveModuleTypeDeps", "out/soong/module-graph.json",
114          module_type
115      ],
116      cwd=SRC_ROOT_DIR,
117  )
118  return json.loads(result)
119
120
121def is_windows_variation(module):
122  """Returns True if input module's variant is Windows.
123
124  Args:
125    module: an entry parsed from Soong's json-module-graph
126  """
127  dep_variations = module.get("Variations")
128  dep_variation_os = ""
129  if dep_variations != None:
130    dep_variation_os = dep_variations.get("os")
131  return dep_variation_os == "windows"
132
133
134def ignore_kind(kind):
135  return kind in IGNORED_KINDS or "defaults" in kind
136