Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(158)

Side by Side Diff: build/android/gyp/write_build_config.py

Issue 2392643003: Removes files from //build that we don't need (Closed)
Patch Set: Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « build/android/gyp/util/proguard_util.py ('k') | build/android/gyp/write_ordered_libraries.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 #!/usr/bin/env python
2 #
3 # Copyright 2014 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 """Writes a build_config file.
8
9 The build_config file for a target is a json file containing information about
10 how to build that target based on the target's dependencies. This includes
11 things like: the javac classpath, the list of android resources dependencies,
12 etc. It also includes the information needed to create the build_config for
13 other targets that depend on that one.
14
15 Android build scripts should not refer to the build_config directly, and the
16 build specification should instead pass information in using the special
17 file-arg syntax (see build_utils.py:ExpandFileArgs). That syntax allows passing
18 of values in a json dict in a file and looks like this:
19 --python-arg=@FileArg(build_config_path:javac:classpath)
20
21 Note: If paths to input files are passed in this way, it is important that:
22 1. inputs/deps of the action ensure that the files are available the first
23 time the action runs.
24 2. Either (a) or (b)
25 a. inputs/deps ensure that the action runs whenever one of the files changes
26 b. the files are added to the action's depfile
27 """
28
29 import optparse
30 import os
31 import sys
32 import xml.dom.minidom
33
34 from util import build_utils
35
36 import write_ordered_libraries
37
38 class AndroidManifest(object):
39 def __init__(self, path):
40 self.path = path
41 dom = xml.dom.minidom.parse(path)
42 manifests = dom.getElementsByTagName('manifest')
43 assert len(manifests) == 1
44 self.manifest = manifests[0]
45
46 def GetInstrumentation(self):
47 instrumentation_els = self.manifest.getElementsByTagName('instrumentation')
48 if len(instrumentation_els) == 0:
49 return None
50 if len(instrumentation_els) != 1:
51 raise Exception(
52 'More than one <instrumentation> element found in %s' % self.path)
53 return instrumentation_els[0]
54
55 def CheckInstrumentation(self, expected_package):
56 instr = self.GetInstrumentation()
57 if not instr:
58 raise Exception('No <instrumentation> elements found in %s' % self.path)
59 instrumented_package = instr.getAttributeNS(
60 'http://schemas.android.com/apk/res/android', 'targetPackage')
61 if instrumented_package != expected_package:
62 raise Exception(
63 'Wrong instrumented package. Expected %s, got %s'
64 % (expected_package, instrumented_package))
65
66 def GetPackageName(self):
67 return self.manifest.getAttribute('package')
68
69
70 dep_config_cache = {}
71 def GetDepConfig(path):
72 if not path in dep_config_cache:
73 dep_config_cache[path] = build_utils.ReadJson(path)['deps_info']
74 return dep_config_cache[path]
75
76
77 def DepsOfType(wanted_type, configs):
78 return [c for c in configs if c['type'] == wanted_type]
79
80
81 def GetAllDepsConfigsInOrder(deps_config_paths):
82 def GetDeps(path):
83 return set(GetDepConfig(path)['deps_configs'])
84 return build_utils.GetSortedTransitiveDependencies(deps_config_paths, GetDeps)
85
86
87 class Deps(object):
88 def __init__(self, direct_deps_config_paths):
89 self.all_deps_config_paths = GetAllDepsConfigsInOrder(
90 direct_deps_config_paths)
91 self.direct_deps_configs = [
92 GetDepConfig(p) for p in direct_deps_config_paths]
93 self.all_deps_configs = [
94 GetDepConfig(p) for p in self.all_deps_config_paths]
95
96 def All(self, wanted_type=None):
97 if type is None:
98 return self.all_deps_configs
99 return DepsOfType(wanted_type, self.all_deps_configs)
100
101 def Direct(self, wanted_type=None):
102 if wanted_type is None:
103 return self.direct_deps_configs
104 return DepsOfType(wanted_type, self.direct_deps_configs)
105
106 def AllConfigPaths(self):
107 return self.all_deps_config_paths
108
109
110 def main(argv):
111 parser = optparse.OptionParser()
112 build_utils.AddDepfileOption(parser)
113 parser.add_option('--build-config', help='Path to build_config output.')
114 parser.add_option(
115 '--type',
116 help='Type of this target (e.g. android_library).')
117 parser.add_option(
118 '--possible-deps-configs',
119 help='List of paths for dependency\'s build_config files. Some '
120 'dependencies may not write build_config files. Missing build_config '
121 'files are handled differently based on the type of this target.')
122
123 # android_resources options
124 parser.add_option('--srcjar', help='Path to target\'s resources srcjar.')
125 parser.add_option('--resources-zip', help='Path to target\'s resources zip.')
126 parser.add_option('--r-text', help='Path to target\'s R.txt file.')
127 parser.add_option('--package-name',
128 help='Java package name for these resources.')
129 parser.add_option('--android-manifest', help='Path to android manifest.')
130
131 # java library options
132 parser.add_option('--jar-path', help='Path to target\'s jar output.')
133 parser.add_option('--supports-android', action='store_true',
134 help='Whether this library supports running on the Android platform.')
135 parser.add_option('--requires-android', action='store_true',
136 help='Whether this library requires running on the Android platform.')
137 parser.add_option('--bypass-platform-checks', action='store_true',
138 help='Bypass checks for support/require Android platform.')
139
140 # android library options
141 parser.add_option('--dex-path', help='Path to target\'s dex output.')
142
143 # native library options
144 parser.add_option('--native-libs', help='List of top-level native libs.')
145 parser.add_option('--readelf-path', help='Path to toolchain\'s readelf.')
146
147 parser.add_option('--tested-apk-config',
148 help='Path to the build config of the tested apk (for an instrumentation '
149 'test apk).')
150
151 options, args = parser.parse_args(argv)
152
153 if args:
154 parser.error('No positional arguments should be given.')
155
156
157 if not options.type in [
158 'java_library', 'android_resources', 'android_apk', 'deps_dex']:
159 raise Exception('Unknown type: <%s>' % options.type)
160
161 required_options = ['build_config'] + {
162 'java_library': ['jar_path'],
163 'android_resources': ['resources_zip'],
164 'android_apk': ['jar_path', 'dex_path', 'resources_zip'],
165 'deps_dex': ['dex_path']
166 }[options.type]
167
168 if options.native_libs:
169 required_options.append('readelf_path')
170
171 build_utils.CheckOptions(options, parser, required_options)
172
173 if options.type == 'java_library':
174 if options.supports_android and not options.dex_path:
175 raise Exception('java_library that supports Android requires a dex path.')
176
177 if options.requires_android and not options.supports_android:
178 raise Exception(
179 '--supports-android is required when using --requires-android')
180
181 possible_deps_config_paths = build_utils.ParseGypList(
182 options.possible_deps_configs)
183
184 allow_unknown_deps = (options.type == 'android_apk' or
185 options.type == 'android_resources')
186 unknown_deps = [
187 c for c in possible_deps_config_paths if not os.path.exists(c)]
188 if unknown_deps and not allow_unknown_deps:
189 raise Exception('Unknown deps: ' + str(unknown_deps))
190
191 direct_deps_config_paths = [
192 c for c in possible_deps_config_paths if not c in unknown_deps]
193
194 deps = Deps(direct_deps_config_paths)
195 direct_library_deps = deps.Direct('java_library')
196 all_library_deps = deps.All('java_library')
197
198 direct_resources_deps = deps.Direct('android_resources')
199 all_resources_deps = deps.All('android_resources')
200 # Resources should be ordered with the highest-level dependency first so that
201 # overrides are done correctly.
202 all_resources_deps.reverse()
203
204 if options.type == 'android_apk' and options.tested_apk_config:
205 tested_apk_deps = Deps([options.tested_apk_config])
206 tested_apk_resources_deps = tested_apk_deps.All('android_resources')
207 all_resources_deps = [
208 d for d in all_resources_deps if not d in tested_apk_resources_deps]
209
210 # Initialize some common config.
211 config = {
212 'deps_info': {
213 'name': os.path.basename(options.build_config),
214 'path': options.build_config,
215 'type': options.type,
216 'deps_configs': direct_deps_config_paths,
217 }
218 }
219 deps_info = config['deps_info']
220
221 if options.type == 'java_library' and not options.bypass_platform_checks:
222 deps_info['requires_android'] = options.requires_android
223 deps_info['supports_android'] = options.supports_android
224
225 deps_require_android = (all_resources_deps +
226 [d['name'] for d in all_library_deps if d['requires_android']])
227 deps_not_support_android = (
228 [d['name'] for d in all_library_deps if not d['supports_android']])
229
230 if deps_require_android and not options.requires_android:
231 raise Exception('Some deps require building for the Android platform: ' +
232 str(deps_require_android))
233
234 if deps_not_support_android and options.supports_android:
235 raise Exception('Not all deps support the Android platform: ' +
236 str(deps_not_support_android))
237
238 if options.type in ['java_library', 'android_apk']:
239 javac_classpath = [c['jar_path'] for c in direct_library_deps]
240 java_full_classpath = [c['jar_path'] for c in all_library_deps]
241 deps_info['resources_deps'] = [c['path'] for c in all_resources_deps]
242 deps_info['jar_path'] = options.jar_path
243 if options.type == 'android_apk' or options.supports_android:
244 deps_info['dex_path'] = options.dex_path
245 config['javac'] = {
246 'classpath': javac_classpath,
247 }
248 config['java'] = {
249 'full_classpath': java_full_classpath
250 }
251
252 if options.type == 'java_library':
253 # Only resources might have srcjars (normal srcjar targets are listed in
254 # srcjar_deps). A resource's srcjar contains the R.java file for those
255 # resources, and (like Android's default build system) we allow a library to
256 # refer to the resources in any of its dependents.
257 config['javac']['srcjars'] = [
258 c['srcjar'] for c in direct_resources_deps if 'srcjar' in c]
259
260 if options.type == 'android_apk':
261 # Apks will get their resources srcjar explicitly passed to the java step.
262 config['javac']['srcjars'] = []
263
264 if options.type == 'android_resources':
265 deps_info['resources_zip'] = options.resources_zip
266 if options.srcjar:
267 deps_info['srcjar'] = options.srcjar
268 if options.android_manifest:
269 manifest = AndroidManifest(options.android_manifest)
270 deps_info['package_name'] = manifest.GetPackageName()
271 if options.package_name:
272 deps_info['package_name'] = options.package_name
273 if options.r_text:
274 deps_info['r_text'] = options.r_text
275
276 if options.type == 'android_resources' or options.type == 'android_apk':
277 config['resources'] = {}
278 config['resources']['dependency_zips'] = [
279 c['resources_zip'] for c in all_resources_deps]
280 config['resources']['extra_package_names'] = []
281 config['resources']['extra_r_text_files'] = []
282
283 if options.type == 'android_apk':
284 config['resources']['extra_package_names'] = [
285 c['package_name'] for c in all_resources_deps if 'package_name' in c]
286 config['resources']['extra_r_text_files'] = [
287 c['r_text'] for c in all_resources_deps if 'r_text' in c]
288
289 if options.type in ['android_apk', 'deps_dex']:
290 deps_dex_files = [c['dex_path'] for c in all_library_deps]
291
292 # An instrumentation test apk should exclude the dex files that are in the apk
293 # under test.
294 if options.type == 'android_apk' and options.tested_apk_config:
295 tested_apk_deps = Deps([options.tested_apk_config])
296 tested_apk_library_deps = tested_apk_deps.All('java_library')
297 tested_apk_deps_dex_files = [c['dex_path'] for c in tested_apk_library_deps]
298 deps_dex_files = [
299 p for p in deps_dex_files if not p in tested_apk_deps_dex_files]
300
301 tested_apk_config = GetDepConfig(options.tested_apk_config)
302 expected_tested_package = tested_apk_config['package_name']
303 AndroidManifest(options.android_manifest).CheckInstrumentation(
304 expected_tested_package)
305
306 # Dependencies for the final dex file of an apk or a 'deps_dex'.
307 if options.type in ['android_apk', 'deps_dex']:
308 config['final_dex'] = {}
309 dex_config = config['final_dex']
310 # TODO(cjhopman): proguard version
311 dex_config['dependency_dex_files'] = deps_dex_files
312
313 if options.type == 'android_apk':
314 config['dist_jar'] = {
315 'dependency_jars': [
316 c['jar_path'] for c in all_library_deps
317 ]
318 }
319 manifest = AndroidManifest(options.android_manifest)
320 deps_info['package_name'] = manifest.GetPackageName()
321 if not options.tested_apk_config and manifest.GetInstrumentation():
322 # This must then have instrumentation only for itself.
323 manifest.CheckInstrumentation(manifest.GetPackageName())
324
325 library_paths = []
326 java_libraries_list = []
327 if options.native_libs:
328 libraries = build_utils.ParseGypList(options.native_libs)
329 if libraries:
330 libraries_dir = os.path.dirname(libraries[0])
331 write_ordered_libraries.SetReadelfPath(options.readelf_path)
332 write_ordered_libraries.SetLibraryDirs([libraries_dir])
333 all_native_library_deps = (
334 write_ordered_libraries.GetSortedTransitiveDependenciesForBinaries(
335 libraries))
336 # Create a java literal array with the "base" library names:
337 # e.g. libfoo.so -> foo
338 java_libraries_list = '{%s}' % ','.join(
339 ['"%s"' % s[3:-3] for s in all_native_library_deps])
340 library_paths = map(
341 write_ordered_libraries.FullLibraryPath, all_native_library_deps)
342
343 config['native'] = {
344 'libraries': library_paths,
345 'java_libraries_list': java_libraries_list
346 }
347
348 build_utils.WriteJson(config, options.build_config, only_if_changed=True)
349
350 if options.depfile:
351 build_utils.WriteDepfile(
352 options.depfile,
353 deps.AllConfigPaths() + build_utils.GetPythonDependencies())
354
355
356 if __name__ == '__main__':
357 sys.exit(main(sys.argv[1:]))
OLDNEW
« no previous file with comments | « build/android/gyp/util/proguard_util.py ('k') | build/android/gyp/write_ordered_libraries.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698