Andrew Grieve | 7dd4aaf | 2021-04-27 21:47:08 | [diff] [blame] | 1 | #!/usr/bin/env python3 |
Ingemar Ådahl | 6ada47b | 2017-07-10 17:14:01 | [diff] [blame] | 2 | |
| 3 | # Copyright 2017 The Chromium Authors. All rights reserved. |
| 4 | # Use of this source code is governed by a BSD-style license that can be |
| 5 | # found in the LICENSE file. |
| 6 | |
| 7 | """Merges dependency Android manifests into a root manifest.""" |
| 8 | |
| 9 | import argparse |
| 10 | import contextlib |
| 11 | import os |
| 12 | import sys |
| 13 | import tempfile |
Eric Stevenson | 8045827 | 2019-02-04 20:57:58 | [diff] [blame] | 14 | import xml.etree.ElementTree as ElementTree |
Ingemar Ådahl | 6ada47b | 2017-07-10 17:14:01 | [diff] [blame] | 15 | |
| 16 | from util import build_utils |
Tibor Goldschwendt | 228bd4c | 2019-06-17 20:32:02 | [diff] [blame] | 17 | from util import manifest_utils |
Ingemar Ådahl | 6ada47b | 2017-07-10 17:14:01 | [diff] [blame] | 18 | |
Eric Stevenson | 8045827 | 2019-02-04 20:57:58 | [diff] [blame] | 19 | _MANIFEST_MERGER_MAIN_CLASS = 'com.android.manifmerger.Merger' |
| 20 | _MANIFEST_MERGER_JARS = [ |
Sam Maier | 226aef9 | 2020-02-07 22:39:40 | [diff] [blame] | 21 | os.path.join('build-system', 'manifest-merger.jar'), |
| 22 | os.path.join('common', 'common.jar'), |
| 23 | os.path.join('sdk-common', 'sdk-common.jar'), |
| 24 | os.path.join('sdklib', 'sdklib.jar'), |
Peter Wen | 059f2e4 | 2021-09-20 18:05:30 | [diff] [blame] | 25 | os.path.join('external', 'com', 'google', 'guava', 'guava', '30.1-jre', |
| 26 | 'guava-30.1-jre.jar'), |
Sam Maier | 226aef9 | 2020-02-07 22:39:40 | [diff] [blame] | 27 | os.path.join('external', 'kotlin-plugin-ij', 'Kotlin', 'kotlinc', 'lib', |
| 28 | 'kotlin-stdlib.jar'), |
Torne (Richard Coles) | ff4b382 | 2021-07-22 20:09:55 | [diff] [blame] | 29 | os.path.join('external', 'com', 'google', 'code', 'gson', 'gson', '2.8.6', |
| 30 | 'gson-2.8.6.jar'), |
Ingemar Ådahl | 6ada47b | 2017-07-10 17:14:01 | [diff] [blame] | 31 | ] |
| 32 | |
Ingemar Ådahl | 6ada47b | 2017-07-10 17:14:01 | [diff] [blame] | 33 | |
| 34 | @contextlib.contextmanager |
Tibor Goldschwendt | fda1594 | 2019-06-24 21:57:47 | [diff] [blame] | 35 | def _ProcessManifest(manifest_path, min_sdk_version, target_sdk_version, |
Tibor Goldschwendt | 1760440 | 2019-07-11 14:44:10 | [diff] [blame] | 36 | max_sdk_version, manifest_package): |
Sam Maier | 5e58530 | 2020-01-29 15:54:21 | [diff] [blame] | 37 | """Patches an Android manifest's package and performs assertions to ensure |
| 38 | correctness for the manifest. |
Ingemar Ådahl | 6ada47b | 2017-07-10 17:14:01 | [diff] [blame] | 39 | """ |
Tibor Goldschwendt | 228bd4c | 2019-06-17 20:32:02 | [diff] [blame] | 40 | doc, manifest, _ = manifest_utils.ParseManifest(manifest_path) |
Tibor Goldschwendt | 1760440 | 2019-07-11 14:44:10 | [diff] [blame] | 41 | manifest_utils.AssertUsesSdk(manifest, min_sdk_version, target_sdk_version, |
| 42 | max_sdk_version) |
Tibor Goldschwendt | fda1594 | 2019-06-24 21:57:47 | [diff] [blame] | 43 | assert manifest_utils.GetPackage(manifest) or manifest_package, \ |
| 44 | 'Must set manifest package in GN or in AndroidManifest.xml' |
| 45 | manifest_utils.AssertPackage(manifest, manifest_package) |
| 46 | if manifest_package: |
| 47 | manifest.set('package', manifest_package) |
Ingemar Ådahl | 6ada47b | 2017-07-10 17:14:01 | [diff] [blame] | 48 | tmp_prefix = os.path.basename(manifest_path) |
| 49 | with tempfile.NamedTemporaryFile(prefix=tmp_prefix) as patched_manifest: |
Tibor Goldschwendt | 228bd4c | 2019-06-17 20:32:02 | [diff] [blame] | 50 | manifest_utils.SaveManifest(doc, patched_manifest.name) |
Tibor Goldschwendt | fda1594 | 2019-06-24 21:57:47 | [diff] [blame] | 51 | yield patched_manifest.name, manifest_utils.GetPackage(manifest) |
Ingemar Ådahl | 6ada47b | 2017-07-10 17:14:01 | [diff] [blame] | 52 | |
| 53 | |
Sam Maier | 9760d5b | 2022-04-22 21:04:05 | [diff] [blame^] | 54 | @contextlib.contextmanager |
| 55 | def _SetTargetApi(manifest_path, target_sdk_version): |
| 56 | """Patches an Android manifest's TargetApi if not set. |
| 57 | |
| 58 | We do this to avoid the manifest merger assuming we have a targetSdkVersion |
| 59 | of 1 and inserting unnecessary permission requests into our merged manifests. |
| 60 | See b/222331337 for more details. |
| 61 | """ |
| 62 | doc, manifest, _ = manifest_utils.ParseManifest(manifest_path) |
| 63 | manifest_utils.SetTargetApiIfUnset(manifest, target_sdk_version) |
| 64 | tmp_prefix = os.path.basename(manifest_path) |
| 65 | with tempfile.NamedTemporaryFile(prefix=tmp_prefix) as patched_manifest: |
| 66 | manifest_utils.SaveManifest(doc, patched_manifest.name) |
| 67 | yield patched_manifest.name |
| 68 | |
| 69 | |
Sam Maier | 226aef9 | 2020-02-07 22:39:40 | [diff] [blame] | 70 | def _BuildManifestMergerClasspath(android_sdk_cmdline_tools): |
Ingemar Ådahl | 6ada47b | 2017-07-10 17:14:01 | [diff] [blame] | 71 | return ':'.join([ |
Sam Maier | 226aef9 | 2020-02-07 22:39:40 | [diff] [blame] | 72 | os.path.join(android_sdk_cmdline_tools, 'lib', jar) |
Eric Stevenson | 8045827 | 2019-02-04 20:57:58 | [diff] [blame] | 73 | for jar in _MANIFEST_MERGER_JARS |
Ingemar Ådahl | 6ada47b | 2017-07-10 17:14:01 | [diff] [blame] | 74 | ]) |
| 75 | |
| 76 | |
| 77 | def main(argv): |
| 78 | argv = build_utils.ExpandFileArgs(argv) |
| 79 | parser = argparse.ArgumentParser(description=__doc__) |
Andrew Grieve | 9ce44b9 | 2017-07-25 02:43:05 | [diff] [blame] | 80 | build_utils.AddDepfileOption(parser) |
Sam Maier | d7e900a | 2020-01-30 16:37:34 | [diff] [blame] | 81 | parser.add_argument( |
Sam Maier | 226aef9 | 2020-02-07 22:39:40 | [diff] [blame] | 82 | '--android-sdk-cmdline-tools', |
| 83 | help='Path to SDK\'s cmdline-tools folder.', |
Sam Maier | d7e900a | 2020-01-30 16:37:34 | [diff] [blame] | 84 | required=True) |
Ingemar Ådahl | 6ada47b | 2017-07-10 17:14:01 | [diff] [blame] | 85 | parser.add_argument('--root-manifest', |
| 86 | help='Root manifest which to merge into', |
| 87 | required=True) |
| 88 | parser.add_argument('--output', help='Output manifest path', required=True) |
| 89 | parser.add_argument('--extras', |
| 90 | help='GN list of additional manifest to merge') |
Tibor Goldschwendt | 228bd4c | 2019-06-17 20:32:02 | [diff] [blame] | 91 | parser.add_argument( |
| 92 | '--min-sdk-version', |
| 93 | required=True, |
| 94 | help='android:minSdkVersion for merging.') |
| 95 | parser.add_argument( |
| 96 | '--target-sdk-version', |
| 97 | required=True, |
| 98 | help='android:targetSdkVersion for merging.') |
Tibor Goldschwendt | fda1594 | 2019-06-24 21:57:47 | [diff] [blame] | 99 | parser.add_argument( |
Tibor Goldschwendt | 1760440 | 2019-07-11 14:44:10 | [diff] [blame] | 100 | '--max-sdk-version', help='android:maxSdkVersion for merging.') |
| 101 | parser.add_argument( |
Tibor Goldschwendt | fda1594 | 2019-06-24 21:57:47 | [diff] [blame] | 102 | '--manifest-package', |
| 103 | help='Package name of the merged AndroidManifest.xml.') |
Andrew Grieve | e9cae1e | 2020-08-21 18:34:16 | [diff] [blame] | 104 | parser.add_argument('--warnings-as-errors', |
| 105 | action='store_true', |
| 106 | help='Treat all warnings as errors.') |
Ingemar Ådahl | 6ada47b | 2017-07-10 17:14:01 | [diff] [blame] | 107 | args = parser.parse_args(argv) |
| 108 | |
Sam Maier | 226aef9 | 2020-02-07 22:39:40 | [diff] [blame] | 109 | classpath = _BuildManifestMergerClasspath(args.android_sdk_cmdline_tools) |
Ingemar Ådahl | 6ada47b | 2017-07-10 17:14:01 | [diff] [blame] | 110 | |
Eric Stevenson | 8045827 | 2019-02-04 20:57:58 | [diff] [blame] | 111 | with build_utils.AtomicOutput(args.output) as output: |
Andrew Grieve | e9cae1e | 2020-08-21 18:34:16 | [diff] [blame] | 112 | cmd = build_utils.JavaCmd(args.warnings_as_errors) + [ |
Eric Stevenson | 8045827 | 2019-02-04 20:57:58 | [diff] [blame] | 113 | '-cp', |
| 114 | classpath, |
| 115 | _MANIFEST_MERGER_MAIN_CLASS, |
| 116 | '--out', |
| 117 | output.name, |
Tibor Goldschwendt | 1760440 | 2019-07-11 14:44:10 | [diff] [blame] | 118 | '--property', |
| 119 | 'MIN_SDK_VERSION=' + args.min_sdk_version, |
| 120 | '--property', |
| 121 | 'TARGET_SDK_VERSION=' + args.target_sdk_version, |
Takuto Ikuta | 61fee73 | 2018-07-06 05:44:45 | [diff] [blame] | 122 | ] |
Ingemar Ådahl | 6ada47b | 2017-07-10 17:14:01 | [diff] [blame] | 123 | |
Tibor Goldschwendt | 1760440 | 2019-07-11 14:44:10 | [diff] [blame] | 124 | if args.max_sdk_version: |
| 125 | cmd += [ |
| 126 | '--property', |
| 127 | 'MAX_SDK_VERSION=' + args.max_sdk_version, |
| 128 | ] |
| 129 | |
Takuto Ikuta | 61fee73 | 2018-07-06 05:44:45 | [diff] [blame] | 130 | extras = build_utils.ParseGnList(args.extras) |
Takuto Ikuta | 61fee73 | 2018-07-06 05:44:45 | [diff] [blame] | 131 | |
Sam Maier | 9760d5b | 2022-04-22 21:04:05 | [diff] [blame^] | 132 | with contextlib.ExitStack() as stack: |
| 133 | root_manifest, package = stack.enter_context( |
| 134 | _ProcessManifest(args.root_manifest, args.min_sdk_version, |
| 135 | args.target_sdk_version, args.max_sdk_version, |
| 136 | args.manifest_package)) |
| 137 | if extras: |
| 138 | extras_processed = [ |
| 139 | stack.enter_context(_SetTargetApi(e, args.target_sdk_version)) |
| 140 | for e in extras |
| 141 | ] |
| 142 | cmd += ['--libs', ':'.join(extras_processed)] |
Tibor Goldschwendt | 228bd4c | 2019-06-17 20:32:02 | [diff] [blame] | 143 | cmd += [ |
| 144 | '--main', |
| 145 | root_manifest, |
| 146 | '--property', |
| 147 | 'PACKAGE=' + package, |
Mohamed Heikal | 9ec8d82 | 2021-05-11 19:18:20 | [diff] [blame] | 148 | '--remove-tools-declarations', |
Tibor Goldschwendt | 228bd4c | 2019-06-17 20:32:02 | [diff] [blame] | 149 | ] |
Andrew Grieve | e9cae1e | 2020-08-21 18:34:16 | [diff] [blame] | 150 | build_utils.CheckOutput( |
| 151 | cmd, |
| 152 | # https://issuetracker.google.com/issues/63514300: |
| 153 | # The merger doesn't set a nonzero exit code for failures. |
| 154 | fail_func=lambda returncode, stderr: returncode != 0 or build_utils. |
| 155 | IsTimeStale(output.name, [root_manifest] + extras), |
| 156 | fail_on_output=args.warnings_as_errors) |
Eric Stevenson | 59bf3c6 | 2019-01-23 23:30:49 | [diff] [blame] | 157 | |
Tibor Goldschwendt | 520e1a4 | 2019-06-24 21:45:33 | [diff] [blame] | 158 | # Check for correct output. |
| 159 | _, manifest, _ = manifest_utils.ParseManifest(output.name) |
| 160 | manifest_utils.AssertUsesSdk(manifest, args.min_sdk_version, |
| 161 | args.target_sdk_version) |
Tibor Goldschwendt | fda1594 | 2019-06-24 21:57:47 | [diff] [blame] | 162 | manifest_utils.AssertPackage(manifest, package) |
Eric Stevenson | 59bf3c6 | 2019-01-23 23:30:49 | [diff] [blame] | 163 | |
Andrew Grieve | 9ce44b9 | 2017-07-25 02:43:05 | [diff] [blame] | 164 | if args.depfile: |
| 165 | inputs = extras + classpath.split(':') |
Andrew Grieve | 8582295 | 2020-06-25 18:06:00 | [diff] [blame] | 166 | build_utils.WriteDepfile(args.depfile, args.output, inputs=inputs) |
Ingemar Ådahl | 6ada47b | 2017-07-10 17:14:01 | [diff] [blame] | 167 | |
| 168 | |
| 169 | if __name__ == '__main__': |
| 170 | main(sys.argv[1:]) |