xref: /aosp_15_r20/external/angle/build/android/gyp/merge_manifest.py (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1*8975f5c5SAndroid Build Coastguard Worker#!/usr/bin/env python3
2*8975f5c5SAndroid Build Coastguard Worker
3*8975f5c5SAndroid Build Coastguard Worker# Copyright 2017 The Chromium Authors
4*8975f5c5SAndroid Build Coastguard Worker# Use of this source code is governed by a BSD-style license that can be
5*8975f5c5SAndroid Build Coastguard Worker# found in the LICENSE file.
6*8975f5c5SAndroid Build Coastguard Worker
7*8975f5c5SAndroid Build Coastguard Worker"""Merges dependency Android manifests into a root manifest."""
8*8975f5c5SAndroid Build Coastguard Worker
9*8975f5c5SAndroid Build Coastguard Workerimport argparse
10*8975f5c5SAndroid Build Coastguard Workerimport collections
11*8975f5c5SAndroid Build Coastguard Workerimport contextlib
12*8975f5c5SAndroid Build Coastguard Workerimport os
13*8975f5c5SAndroid Build Coastguard Workerimport sys
14*8975f5c5SAndroid Build Coastguard Workerimport tempfile
15*8975f5c5SAndroid Build Coastguard Workerimport xml.etree.ElementTree as ElementTree
16*8975f5c5SAndroid Build Coastguard Worker
17*8975f5c5SAndroid Build Coastguard Workerfrom util import build_utils
18*8975f5c5SAndroid Build Coastguard Workerfrom util import manifest_utils
19*8975f5c5SAndroid Build Coastguard Workerimport action_helpers  # build_utils adds //build to sys.path.
20*8975f5c5SAndroid Build Coastguard Worker
21*8975f5c5SAndroid Build Coastguard Worker_MANIFEST_MERGER_MAIN_CLASS = 'com.android.manifmerger.Merger'
22*8975f5c5SAndroid Build Coastguard Worker
23*8975f5c5SAndroid Build Coastguard Worker
24*8975f5c5SAndroid Build Coastguard Worker@contextlib.contextmanager
25*8975f5c5SAndroid Build Coastguard Workerdef _ProcessMainManifest(manifest_path, min_sdk_version, target_sdk_version,
26*8975f5c5SAndroid Build Coastguard Worker                         max_sdk_version, manifest_package):
27*8975f5c5SAndroid Build Coastguard Worker  """Patches the main Android manifest"""
28*8975f5c5SAndroid Build Coastguard Worker  doc, manifest, _ = manifest_utils.ParseManifest(manifest_path)
29*8975f5c5SAndroid Build Coastguard Worker  manifest_utils.SetUsesSdk(manifest, target_sdk_version, min_sdk_version,
30*8975f5c5SAndroid Build Coastguard Worker                            max_sdk_version)
31*8975f5c5SAndroid Build Coastguard Worker  assert manifest_utils.GetPackage(manifest) or manifest_package, \
32*8975f5c5SAndroid Build Coastguard Worker            'Must set manifest package in GN or in AndroidManifest.xml'
33*8975f5c5SAndroid Build Coastguard Worker  if manifest_package:
34*8975f5c5SAndroid Build Coastguard Worker    manifest.set('package', manifest_package)
35*8975f5c5SAndroid Build Coastguard Worker  tmp_prefix = manifest_path.replace(os.path.sep, '-')
36*8975f5c5SAndroid Build Coastguard Worker  with tempfile.NamedTemporaryFile(prefix=tmp_prefix) as patched_manifest:
37*8975f5c5SAndroid Build Coastguard Worker    manifest_utils.SaveManifest(doc, patched_manifest.name)
38*8975f5c5SAndroid Build Coastguard Worker    yield patched_manifest.name, manifest_utils.GetPackage(manifest)
39*8975f5c5SAndroid Build Coastguard Worker
40*8975f5c5SAndroid Build Coastguard Worker
41*8975f5c5SAndroid Build Coastguard Worker@contextlib.contextmanager
42*8975f5c5SAndroid Build Coastguard Workerdef _ProcessOtherManifest(manifest_path, min_sdk_version, target_sdk_version,
43*8975f5c5SAndroid Build Coastguard Worker                          seen_package_names):
44*8975f5c5SAndroid Build Coastguard Worker  """Patches non-main AndroidManifest.xml if necessary."""
45*8975f5c5SAndroid Build Coastguard Worker  # 1. Ensure targetSdkVersion is set to the expected value to avoid
46*8975f5c5SAndroid Build Coastguard Worker  #    spurious permissions being added (b/222331337).
47*8975f5c5SAndroid Build Coastguard Worker  # 2. Ensure all manifests have a unique package name so that the merger
48*8975f5c5SAndroid Build Coastguard Worker  #    does not fail when this happens.
49*8975f5c5SAndroid Build Coastguard Worker  doc, manifest, _ = manifest_utils.ParseManifest(manifest_path)
50*8975f5c5SAndroid Build Coastguard Worker
51*8975f5c5SAndroid Build Coastguard Worker  changed_api = manifest_utils.SetTargetApiIfUnset(manifest, target_sdk_version)
52*8975f5c5SAndroid Build Coastguard Worker
53*8975f5c5SAndroid Build Coastguard Worker  package_name = manifest_utils.GetPackage(manifest)
54*8975f5c5SAndroid Build Coastguard Worker  # Ignore minSdkVersion from androidx.pdf library. The client code will ensure
55*8975f5c5SAndroid Build Coastguard Worker  # not to call into the library API on older Android versions.
56*8975f5c5SAndroid Build Coastguard Worker  if package_name.startswith('androidx.pdf'):
57*8975f5c5SAndroid Build Coastguard Worker    manifest_utils.OverrideMinSdkVersionIfPresent(manifest, min_sdk_version)
58*8975f5c5SAndroid Build Coastguard Worker    changed_api = True
59*8975f5c5SAndroid Build Coastguard Worker  package_count = seen_package_names[package_name]
60*8975f5c5SAndroid Build Coastguard Worker  seen_package_names[package_name] += 1
61*8975f5c5SAndroid Build Coastguard Worker  if package_count > 0:
62*8975f5c5SAndroid Build Coastguard Worker    manifest.set('package', f'{package_name}_{package_count}')
63*8975f5c5SAndroid Build Coastguard Worker
64*8975f5c5SAndroid Build Coastguard Worker  if package_count > 0 or changed_api:
65*8975f5c5SAndroid Build Coastguard Worker    tmp_prefix = manifest_path.replace(os.path.sep, '-')
66*8975f5c5SAndroid Build Coastguard Worker    with tempfile.NamedTemporaryFile(prefix=tmp_prefix) as patched_manifest:
67*8975f5c5SAndroid Build Coastguard Worker      manifest_utils.SaveManifest(doc, patched_manifest.name)
68*8975f5c5SAndroid Build Coastguard Worker      yield patched_manifest.name
69*8975f5c5SAndroid Build Coastguard Worker  else:
70*8975f5c5SAndroid Build Coastguard Worker    yield manifest_path
71*8975f5c5SAndroid Build Coastguard Worker
72*8975f5c5SAndroid Build Coastguard Worker
73*8975f5c5SAndroid Build Coastguard Workerdef main(argv):
74*8975f5c5SAndroid Build Coastguard Worker  argv = build_utils.ExpandFileArgs(argv)
75*8975f5c5SAndroid Build Coastguard Worker  parser = argparse.ArgumentParser(description=__doc__)
76*8975f5c5SAndroid Build Coastguard Worker  action_helpers.add_depfile_arg(parser)
77*8975f5c5SAndroid Build Coastguard Worker  parser.add_argument('--manifest-merger-jar',
78*8975f5c5SAndroid Build Coastguard Worker                      help='Path to SDK\'s manifest merger jar.',
79*8975f5c5SAndroid Build Coastguard Worker                      required=True)
80*8975f5c5SAndroid Build Coastguard Worker  parser.add_argument('--root-manifest',
81*8975f5c5SAndroid Build Coastguard Worker                      help='Root manifest which to merge into',
82*8975f5c5SAndroid Build Coastguard Worker                      required=True)
83*8975f5c5SAndroid Build Coastguard Worker  parser.add_argument('--output', help='Output manifest path', required=True)
84*8975f5c5SAndroid Build Coastguard Worker  parser.add_argument('--extras',
85*8975f5c5SAndroid Build Coastguard Worker                      help='GN list of additional manifest to merge')
86*8975f5c5SAndroid Build Coastguard Worker  parser.add_argument(
87*8975f5c5SAndroid Build Coastguard Worker      '--min-sdk-version',
88*8975f5c5SAndroid Build Coastguard Worker      required=True,
89*8975f5c5SAndroid Build Coastguard Worker      help='android:minSdkVersion for merging.')
90*8975f5c5SAndroid Build Coastguard Worker  parser.add_argument(
91*8975f5c5SAndroid Build Coastguard Worker      '--target-sdk-version',
92*8975f5c5SAndroid Build Coastguard Worker      required=True,
93*8975f5c5SAndroid Build Coastguard Worker      help='android:targetSdkVersion for merging.')
94*8975f5c5SAndroid Build Coastguard Worker  parser.add_argument(
95*8975f5c5SAndroid Build Coastguard Worker      '--max-sdk-version', help='android:maxSdkVersion for merging.')
96*8975f5c5SAndroid Build Coastguard Worker  parser.add_argument(
97*8975f5c5SAndroid Build Coastguard Worker      '--manifest-package',
98*8975f5c5SAndroid Build Coastguard Worker      help='Package name of the merged AndroidManifest.xml.')
99*8975f5c5SAndroid Build Coastguard Worker  parser.add_argument('--warnings-as-errors',
100*8975f5c5SAndroid Build Coastguard Worker                      action='store_true',
101*8975f5c5SAndroid Build Coastguard Worker                      help='Treat all warnings as errors.')
102*8975f5c5SAndroid Build Coastguard Worker  args = parser.parse_args(argv)
103*8975f5c5SAndroid Build Coastguard Worker
104*8975f5c5SAndroid Build Coastguard Worker  with action_helpers.atomic_output(args.output) as output:
105*8975f5c5SAndroid Build Coastguard Worker    cmd = build_utils.JavaCmd() + [
106*8975f5c5SAndroid Build Coastguard Worker        '-cp',
107*8975f5c5SAndroid Build Coastguard Worker        args.manifest_merger_jar,
108*8975f5c5SAndroid Build Coastguard Worker        _MANIFEST_MERGER_MAIN_CLASS,
109*8975f5c5SAndroid Build Coastguard Worker        '--out',
110*8975f5c5SAndroid Build Coastguard Worker        output.name,
111*8975f5c5SAndroid Build Coastguard Worker        '--property',
112*8975f5c5SAndroid Build Coastguard Worker        'MIN_SDK_VERSION=' + args.min_sdk_version,
113*8975f5c5SAndroid Build Coastguard Worker        '--property',
114*8975f5c5SAndroid Build Coastguard Worker        'TARGET_SDK_VERSION=' + args.target_sdk_version,
115*8975f5c5SAndroid Build Coastguard Worker    ]
116*8975f5c5SAndroid Build Coastguard Worker
117*8975f5c5SAndroid Build Coastguard Worker    if args.max_sdk_version:
118*8975f5c5SAndroid Build Coastguard Worker      cmd += [
119*8975f5c5SAndroid Build Coastguard Worker          '--property',
120*8975f5c5SAndroid Build Coastguard Worker          'MAX_SDK_VERSION=' + args.max_sdk_version,
121*8975f5c5SAndroid Build Coastguard Worker      ]
122*8975f5c5SAndroid Build Coastguard Worker
123*8975f5c5SAndroid Build Coastguard Worker    extras = action_helpers.parse_gn_list(args.extras)
124*8975f5c5SAndroid Build Coastguard Worker
125*8975f5c5SAndroid Build Coastguard Worker    with contextlib.ExitStack() as stack:
126*8975f5c5SAndroid Build Coastguard Worker      root_manifest, package = stack.enter_context(
127*8975f5c5SAndroid Build Coastguard Worker          _ProcessMainManifest(args.root_manifest, args.min_sdk_version,
128*8975f5c5SAndroid Build Coastguard Worker                               args.target_sdk_version, args.max_sdk_version,
129*8975f5c5SAndroid Build Coastguard Worker                               args.manifest_package))
130*8975f5c5SAndroid Build Coastguard Worker      if extras:
131*8975f5c5SAndroid Build Coastguard Worker        seen_package_names = collections.Counter()
132*8975f5c5SAndroid Build Coastguard Worker        extras_processed = [
133*8975f5c5SAndroid Build Coastguard Worker            stack.enter_context(
134*8975f5c5SAndroid Build Coastguard Worker                _ProcessOtherManifest(e, args.min_sdk_version,
135*8975f5c5SAndroid Build Coastguard Worker                                      args.target_sdk_version,
136*8975f5c5SAndroid Build Coastguard Worker                                      seen_package_names)) for e in extras
137*8975f5c5SAndroid Build Coastguard Worker        ]
138*8975f5c5SAndroid Build Coastguard Worker        cmd += ['--libs', ':'.join(extras_processed)]
139*8975f5c5SAndroid Build Coastguard Worker      cmd += [
140*8975f5c5SAndroid Build Coastguard Worker          '--main',
141*8975f5c5SAndroid Build Coastguard Worker          root_manifest,
142*8975f5c5SAndroid Build Coastguard Worker          '--property',
143*8975f5c5SAndroid Build Coastguard Worker          'PACKAGE=' + package,
144*8975f5c5SAndroid Build Coastguard Worker          '--remove-tools-declarations',
145*8975f5c5SAndroid Build Coastguard Worker      ]
146*8975f5c5SAndroid Build Coastguard Worker      build_utils.CheckOutput(
147*8975f5c5SAndroid Build Coastguard Worker          cmd,
148*8975f5c5SAndroid Build Coastguard Worker          # https://issuetracker.google.com/issues/63514300:
149*8975f5c5SAndroid Build Coastguard Worker          # The merger doesn't set a nonzero exit code for failures.
150*8975f5c5SAndroid Build Coastguard Worker          fail_func=lambda returncode, stderr: returncode != 0 or build_utils.
151*8975f5c5SAndroid Build Coastguard Worker          IsTimeStale(output.name, [root_manifest] + extras),
152*8975f5c5SAndroid Build Coastguard Worker          fail_on_output=args.warnings_as_errors)
153*8975f5c5SAndroid Build Coastguard Worker
154*8975f5c5SAndroid Build Coastguard Worker  if args.depfile:
155*8975f5c5SAndroid Build Coastguard Worker    action_helpers.write_depfile(args.depfile, args.output, inputs=extras)
156*8975f5c5SAndroid Build Coastguard Worker
157*8975f5c5SAndroid Build Coastguard Worker
158*8975f5c5SAndroid Build Coastguard Workerif __name__ == '__main__':
159*8975f5c5SAndroid Build Coastguard Worker  main(sys.argv[1:])
160