xref: /aosp_15_r20/external/cronet/build/android/pylib/utils/device_dependencies.py (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1# Copyright 2016 The Chromium Authors
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5import os
6import re
7
8from pylib import constants
9
10_EXCLUSIONS = [
11    # Misc files that exist to document directories
12    re.compile(r'.*METADATA'),
13    re.compile(r'.*OWNERS'),
14    re.compile(r'.*\.md'),
15    re.compile(r'.*\.crx'),  # Chrome extension zip files.
16    re.compile(r'.*/\.git.*'),  # Any '.git*' directories/files.
17    re.compile(r'.*\.so'),  # Libraries packed into .apk.
18    re.compile(r'.*Mojo.*manifest\.json'),  # Some source_set()s pull these in.
19    re.compile(r'.*\.py'),  # Some test_support targets include python deps.
20    re.compile(r'.*\.apk'),  # Should be installed separately.
21    re.compile(r'.*\.jar'),  # Never need java intermediates.
22    re.compile(r'.*\.crx'),  # Used by download_from_google_storage.
23    re.compile(r'.*\.wpr'),  # Web-page-relay files needed only on host.
24    re.compile(r'.*lib.java/.*'),  # Never need java intermediates.
25
26    # Test filter files:
27    re.compile(r'.*/testing/buildbot/filters/.*'),
28
29    # Chrome external extensions config file.
30    re.compile(r'.*external_extensions\.json'),
31
32    # v8's blobs and icu data get packaged into APKs.
33    re.compile(r'.*snapshot_blob.*\.bin'),
34    re.compile(r'.*icudtl\.bin'),
35
36    # Scripts that are needed by swarming, but not on devices:
37    re.compile(r'.*llvm-symbolizer'),
38    re.compile(r'.*md5sum_(?:bin|dist)'),
39    re.compile(r'.*/development/scripts/stack'),
40    re.compile(r'.*/build/android/pylib/symbols'),
41    re.compile(r'.*/build/android/stacktrace'),
42
43    # Required for java deobfuscation on the host:
44    re.compile(r'.*build/android/stacktrace/.*'),
45    re.compile(r'.*third_party/jdk/.*'),
46    re.compile(r'.*third_party/proguard/.*'),
47
48    # Our tests don't need these.
49    re.compile(r'.*/devtools-frontend/.*front_end/.*'),
50
51    # Build artifacts:
52    re.compile(r'.*\.stamp'),
53    re.compile(r'.*\.pak\.info'),
54    re.compile(r'.*\.build_config.json'),
55    re.compile(r'.*\.incremental\.json'),
56]
57
58
59def _FilterDataDeps(abs_host_files):
60  exclusions = _EXCLUSIONS + [
61      re.compile(os.path.join(constants.GetOutDirectory(), 'bin'))
62  ]
63  return [p for p in abs_host_files if not any(r.match(p) for r in exclusions)]
64
65
66def DevicePathComponentsFor(host_path, output_directory=None):
67  """Returns the device path components for a given host path.
68
69  This returns the device path as a list of joinable path components,
70  with None as the first element to indicate that the path should be
71  rooted at $EXTERNAL_STORAGE.
72
73  e.g., given
74
75    '$RUNTIME_DEPS_ROOT_DIR/foo/bar/baz.txt'
76
77  this would return
78
79    [None, 'foo', 'bar', 'baz.txt']
80
81  This handles a couple classes of paths differently than it otherwise would:
82    - All .pak files get mapped to top-level paks/
83    - All other dependencies get mapped to the top level directory
84        - If a file is not in the output directory then it's relative path to
85          the output directory will start with .. strings, so we remove those
86          and then the path gets mapped to the top-level directory
87        - If a file is in the output directory then the relative path to the
88          output directory gets mapped to the top-level directory
89
90  e.g. given
91
92    '$RUNTIME_DEPS_ROOT_DIR/out/Release/icu_fake_dir/icudtl.dat'
93
94  this would return
95
96    [None, 'icu_fake_dir', 'icudtl.dat']
97
98  Args:
99    host_path: The absolute path to the host file.
100  Returns:
101    A list of device path components.
102  """
103  output_directory = output_directory or constants.GetOutDirectory()
104  if (host_path.startswith(output_directory) and
105      os.path.splitext(host_path)[1] == '.pak'):
106    return [None, 'paks', os.path.basename(host_path)]
107
108  rel_host_path = os.path.relpath(host_path, output_directory)
109
110  device_path_components = [None]
111  p = rel_host_path
112  while p:
113    p, d = os.path.split(p)
114    # The relative path from the output directory to a file under the runtime
115    # deps root directory may start with multiple .. strings, so they need to
116    # be skipped.
117    if d and d != os.pardir:
118      device_path_components.insert(1, d)
119  return device_path_components
120
121
122def GetDataDependencies(runtime_deps_path):
123  """Returns a list of device data dependencies.
124
125  Args:
126    runtime_deps_path: A str path to the .runtime_deps file.
127  Returns:
128    A list of (host_path, device_path) tuples.
129  """
130  if not runtime_deps_path:
131    return []
132
133  with open(runtime_deps_path, 'r') as runtime_deps_file:
134    # .runtime_deps can contain duplicates.
135    rel_host_files = sorted({l.strip() for l in runtime_deps_file if l})
136
137  output_directory = constants.GetOutDirectory()
138  abs_host_files = [
139      os.path.abspath(os.path.join(output_directory, r))
140      for r in rel_host_files]
141  filtered_abs_host_files = _FilterDataDeps(abs_host_files)
142  # TODO(crbug.com/752610): Filter out host executables, and investigate
143  # whether other files could be filtered as well.
144  return [(f, DevicePathComponentsFor(f, output_directory))
145          for f in filtered_abs_host_files]
146