blob: 43fef824ca4b1140b1a87b780ba4ae800f2e31a4 [file] [log] [blame]
Ingemar Ådahl6ada47b2017-07-10 17:14:011#!/usr/bin/env python
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
9import argparse
10import contextlib
11import os
12import sys
13import tempfile
14import xml.dom.minidom as minidom
15
16from util import build_utils
17
18# Tools library directory - relative to Android SDK root
19SDK_TOOLS_LIB_DIR = os.path.join('tools', 'lib')
20
21MANIFEST_MERGER_MAIN_CLASS = 'com.android.manifmerger.Merger'
22MANIFEST_MERGER_JARS = [
23 'common{suffix}.jar',
24 'manifest-merger{suffix}.jar',
25 'sdk-common{suffix}.jar',
26 'sdklib{suffix}.jar',
27]
28
29TOOLS_NAMESPACE_PREFIX = 'tools'
30TOOLS_NAMESPACE = 'http://schemas.android.com/tools'
31
32
33@contextlib.contextmanager
34def _PatchedManifest(manifest_path):
35 """Patches an Android manifest to always include the 'tools' namespace
36 declaration, as it is not propagated by the manifest merger from the SDK.
37
38 See https://issuetracker.google.com/issues/63411481
39 """
40 doc = minidom.parse(manifest_path)
41 manifests = doc.getElementsByTagName('manifest')
42 assert len(manifests) == 1
43 manifest = manifests[0]
44
45 manifest.setAttribute('xmlns:%s' % TOOLS_NAMESPACE_PREFIX, TOOLS_NAMESPACE)
46
47 tmp_prefix = os.path.basename(manifest_path)
48 with tempfile.NamedTemporaryFile(prefix=tmp_prefix) as patched_manifest:
49 doc.writexml(patched_manifest)
50 patched_manifest.flush()
51 yield patched_manifest.name
52
53
54def _BuildManifestMergerClasspath(build_vars):
55 return ':'.join([
56 os.path.join(
57 build_vars['android_sdk_root'],
58 SDK_TOOLS_LIB_DIR,
59 jar.format(suffix=build_vars['android_sdk_tools_version_suffix']))
60 for jar in MANIFEST_MERGER_JARS
61 ])
62
63
64def main(argv):
65 argv = build_utils.ExpandFileArgs(argv)
66 parser = argparse.ArgumentParser(description=__doc__)
Andrew Grieve9ce44b92017-07-25 02:43:0567 build_utils.AddDepfileOption(parser)
Ingemar Ådahl6ada47b2017-07-10 17:14:0168 parser.add_argument('--build-vars',
69 help='Path to GN build vars file',
70 required=True)
71 parser.add_argument('--root-manifest',
72 help='Root manifest which to merge into',
73 required=True)
74 parser.add_argument('--output', help='Output manifest path', required=True)
75 parser.add_argument('--extras',
76 help='GN list of additional manifest to merge')
77 args = parser.parse_args(argv)
78
Andrew Grieve9ce44b92017-07-25 02:43:0579 classpath = _BuildManifestMergerClasspath(
80 build_utils.ReadBuildVars(args.build_vars))
Ingemar Ådahl6ada47b2017-07-10 17:14:0181 cmd = [
82 'java',
83 '-cp',
Andrew Grieve9ce44b92017-07-25 02:43:0584 classpath,
Ingemar Ådahl6ada47b2017-07-10 17:14:0185 MANIFEST_MERGER_MAIN_CLASS,
86 '--out', args.output,
87 ]
88
89 extras = build_utils.ParseGnList(args.extras)
90 if extras:
91 cmd += ['--libs', ':'.join(extras)]
92
93 with _PatchedManifest(args.root_manifest) as root_manifest:
94 cmd += ['--main', root_manifest]
95 build_utils.CheckOutput(cmd,
96 # https://issuetracker.google.com/issues/63514300: The merger doesn't set
97 # a nonzero exit code for failures.
98 fail_func=lambda returncode, stderr: returncode != 0 or
99 build_utils.IsTimeStale(args.output, [root_manifest] + extras))
Andrew Grieve9ce44b92017-07-25 02:43:05100 if args.depfile:
101 inputs = extras + classpath.split(':')
102 build_utils.WriteDepfile(args.depfile, args.output, inputs=inputs)
Ingemar Ådahl6ada47b2017-07-10 17:14:01103
104
105if __name__ == '__main__':
106 main(sys.argv[1:])