OLD | NEW |
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # | 2 # |
3 # Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 4 # Use of this source code is governed by a BSD-style license that can be |
5 # found in the LICENSE file. | 5 # found in the LICENSE file. |
6 | 6 |
7 """Writes a build_config file. | 7 """Writes a build_config file. |
8 | 8 |
9 The build_config file for a target is a json file containing information about | 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 | 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, | 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 | 12 etc. It also includes the information needed to create the build_config for |
13 other targets that depend on that one. | 13 other targets that depend on that one. |
14 | 14 |
15 Android build scripts should not refer to the build_config directly, and the | 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 | 16 build specification should instead pass information in using the special |
17 file-arg syntax (see build_utils.py:ExpandFileArgs). That syntax allows passing | 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: | 18 of values in a json dict in a file and looks like this: |
19 --python-arg=@FileArg(build_config_path:javac:classpath) | 19 --python-arg=@FileArg(build_config_path:javac:classpath) |
20 | 20 |
21 Note: If paths to input files are passed in this way, it is important that: | 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 | 22 1. inputs/deps of the action ensure that the files are available the first |
23 time the action runs. | 23 time the action runs. |
24 2. Either (a) or (b) | 24 2. Either (a) or (b) |
25 a. inputs/deps ensure that the action runs whenever one of the files changes | 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 | 26 b. the files are added to the action's depfile |
27 """ | 27 """ |
28 | 28 |
| 29 import itertools |
29 import optparse | 30 import optparse |
30 import os | 31 import os |
31 import sys | 32 import sys |
32 import xml.dom.minidom | 33 import xml.dom.minidom |
33 | 34 |
34 from util import build_utils | 35 from util import build_utils |
35 from util import md5_check | 36 from util import md5_check |
36 | 37 |
37 import write_ordered_libraries | 38 import write_ordered_libraries |
38 | 39 |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
101 | 102 |
102 def Direct(self, wanted_type=None): | 103 def Direct(self, wanted_type=None): |
103 if wanted_type is None: | 104 if wanted_type is None: |
104 return self.direct_deps_configs | 105 return self.direct_deps_configs |
105 return DepsOfType(wanted_type, self.direct_deps_configs) | 106 return DepsOfType(wanted_type, self.direct_deps_configs) |
106 | 107 |
107 def AllConfigPaths(self): | 108 def AllConfigPaths(self): |
108 return self.all_deps_config_paths | 109 return self.all_deps_config_paths |
109 | 110 |
110 | 111 |
| 112 def _MergeAssets(all_assets): |
| 113 """Merges all assets from the given deps. |
| 114 |
| 115 Returns: |
| 116 A tuple of lists: (compressed, uncompressed) |
| 117 Each tuple entry is a list of "srcPath:zipPath". srcPath is the path of the |
| 118 asset to add, and zipPath is the location within the zip (excluding assets/ |
| 119 prefix) |
| 120 """ |
| 121 compressed = {} |
| 122 uncompressed = {} |
| 123 for asset_dep in all_assets: |
| 124 entry = asset_dep['assets'] |
| 125 disable_compression = entry.get('disable_compression', False) |
| 126 dest_map = uncompressed if disable_compression else compressed |
| 127 other_map = compressed if disable_compression else uncompressed |
| 128 outputs = entry.get('outputs', []) |
| 129 for src, dest in itertools.izip_longest(entry['sources'], outputs): |
| 130 if not dest: |
| 131 dest = os.path.basename(src) |
| 132 # Merge so that each path shows up in only one of the lists, and that |
| 133 # deps of the same target override previous ones. |
| 134 other_map.pop(dest, 0) |
| 135 dest_map[dest] = src |
| 136 |
| 137 def create_list(asset_map): |
| 138 ret = ['%s:%s' % (src, dest) for dest, src in asset_map.iteritems()] |
| 139 # Sort to ensure deterministic ordering. |
| 140 ret.sort() |
| 141 return ret |
| 142 |
| 143 return create_list(compressed), create_list(uncompressed) |
| 144 |
| 145 |
111 def main(argv): | 146 def main(argv): |
112 parser = optparse.OptionParser() | 147 parser = optparse.OptionParser() |
113 build_utils.AddDepfileOption(parser) | 148 build_utils.AddDepfileOption(parser) |
114 parser.add_option('--build-config', help='Path to build_config output.') | 149 parser.add_option('--build-config', help='Path to build_config output.') |
115 parser.add_option( | 150 parser.add_option( |
116 '--type', | 151 '--type', |
117 help='Type of this target (e.g. android_library).') | 152 help='Type of this target (e.g. android_library).') |
118 parser.add_option( | 153 parser.add_option( |
119 '--possible-deps-configs', | 154 '--possible-deps-configs', |
120 help='List of paths for dependency\'s build_config files. Some ' | 155 help='List of paths for dependency\'s build_config files. Some ' |
121 'dependencies may not write build_config files. Missing build_config ' | 156 'dependencies may not write build_config files. Missing build_config ' |
122 'files are handled differently based on the type of this target.') | 157 'files are handled differently based on the type of this target.') |
123 | 158 |
124 # android_resources options | 159 # android_resources options |
125 parser.add_option('--srcjar', help='Path to target\'s resources srcjar.') | 160 parser.add_option('--srcjar', help='Path to target\'s resources srcjar.') |
126 parser.add_option('--resources-zip', help='Path to target\'s resources zip.') | 161 parser.add_option('--resources-zip', help='Path to target\'s resources zip.') |
127 parser.add_option('--r-text', help='Path to target\'s R.txt file.') | 162 parser.add_option('--r-text', help='Path to target\'s R.txt file.') |
128 parser.add_option('--package-name', | 163 parser.add_option('--package-name', |
129 help='Java package name for these resources.') | 164 help='Java package name for these resources.') |
130 parser.add_option('--android-manifest', help='Path to android manifest.') | 165 parser.add_option('--android-manifest', help='Path to android manifest.') |
131 | 166 |
| 167 # android_assets options |
| 168 parser.add_option('--asset-sources', help='List of asset sources.') |
| 169 parser.add_option('--asset-renaming-sources', |
| 170 help='List of asset sources with custom destinations.') |
| 171 parser.add_option('--asset-renaming-destinations', |
| 172 help='List of asset custom destinations.') |
| 173 parser.add_option('--disable-asset-compression', action='store_true', |
| 174 help='Whether to disable asset compression.') |
| 175 |
132 # java library options | 176 # java library options |
133 parser.add_option('--jar-path', help='Path to target\'s jar output.') | 177 parser.add_option('--jar-path', help='Path to target\'s jar output.') |
134 parser.add_option('--supports-android', action='store_true', | 178 parser.add_option('--supports-android', action='store_true', |
135 help='Whether this library supports running on the Android platform.') | 179 help='Whether this library supports running on the Android platform.') |
136 parser.add_option('--requires-android', action='store_true', | 180 parser.add_option('--requires-android', action='store_true', |
137 help='Whether this library requires running on the Android platform.') | 181 help='Whether this library requires running on the Android platform.') |
138 parser.add_option('--bypass-platform-checks', action='store_true', | 182 parser.add_option('--bypass-platform-checks', action='store_true', |
139 help='Bypass checks for support/require Android platform.') | 183 help='Bypass checks for support/require Android platform.') |
140 | 184 |
141 # android library options | 185 # android library options |
142 parser.add_option('--dex-path', help='Path to target\'s dex output.') | 186 parser.add_option('--dex-path', help='Path to target\'s dex output.') |
143 | 187 |
144 # native library options | 188 # native library options |
145 parser.add_option('--native-libs', help='List of top-level native libs.') | 189 parser.add_option('--native-libs', help='List of top-level native libs.') |
146 parser.add_option('--readelf-path', help='Path to toolchain\'s readelf.') | 190 parser.add_option('--readelf-path', help='Path to toolchain\'s readelf.') |
147 | 191 |
148 parser.add_option('--tested-apk-config', | 192 parser.add_option('--tested-apk-config', |
149 help='Path to the build config of the tested apk (for an instrumentation ' | 193 help='Path to the build config of the tested apk (for an instrumentation ' |
150 'test apk).') | 194 'test apk).') |
151 | 195 |
152 options, args = parser.parse_args(argv) | 196 options, args = parser.parse_args(argv) |
153 | 197 |
154 if args: | 198 if args: |
155 parser.error('No positional arguments should be given.') | 199 parser.error('No positional arguments should be given.') |
156 | 200 |
157 | 201 required_options_map = { |
158 if not options.type in [ | 202 'java_library': ['build_config', 'jar_path'], |
159 'java_library', 'android_resources', 'android_apk', 'deps_dex']: | 203 'android_assets': ['build_config'], |
| 204 'android_resources': ['build_config', 'resources_zip'], |
| 205 'android_apk': ['build_config', 'jar_path', 'dex_path', 'resources_zip'], |
| 206 'deps_dex': ['build_config', 'dex_path'] |
| 207 } |
| 208 required_options = required_options_map.get(options.type) |
| 209 if not required_options: |
160 raise Exception('Unknown type: <%s>' % options.type) | 210 raise Exception('Unknown type: <%s>' % options.type) |
161 | 211 |
162 required_options = ['build_config'] + { | |
163 'java_library': ['jar_path'], | |
164 'android_resources': ['resources_zip'], | |
165 'android_apk': ['jar_path', 'dex_path', 'resources_zip'], | |
166 'deps_dex': ['dex_path'] | |
167 }[options.type] | |
168 | |
169 if options.native_libs: | 212 if options.native_libs: |
170 required_options.append('readelf_path') | 213 required_options.append('readelf_path') |
171 | 214 |
172 build_utils.CheckOptions(options, parser, required_options) | 215 build_utils.CheckOptions(options, parser, required_options) |
173 | 216 |
174 if options.type == 'java_library': | 217 if options.type == 'java_library': |
175 if options.supports_android and not options.dex_path: | 218 if options.supports_android and not options.dex_path: |
176 raise Exception('java_library that supports Android requires a dex path.') | 219 raise Exception('java_library that supports Android requires a dex path.') |
177 | 220 |
178 if options.requires_android and not options.supports_android: | 221 if options.requires_android and not options.supports_android: |
179 raise Exception( | 222 raise Exception( |
180 '--supports-android is required when using --requires-android') | 223 '--supports-android is required when using --requires-android') |
181 | 224 |
182 possible_deps_config_paths = build_utils.ParseGypList( | 225 possible_deps_config_paths = build_utils.ParseGypList( |
183 options.possible_deps_configs) | 226 options.possible_deps_configs) |
184 | 227 |
185 allow_unknown_deps = (options.type == 'android_apk' or | 228 allow_unknown_deps = (options.type in |
186 options.type == 'android_resources') | 229 ('android_apk', 'android_assets', 'android_resources')) |
187 unknown_deps = [ | 230 unknown_deps = [ |
188 c for c in possible_deps_config_paths if not os.path.exists(c)] | 231 c for c in possible_deps_config_paths if not os.path.exists(c)] |
189 if unknown_deps and not allow_unknown_deps: | 232 if unknown_deps and not allow_unknown_deps: |
190 raise Exception('Unknown deps: ' + str(unknown_deps)) | 233 raise Exception('Unknown deps: ' + str(unknown_deps)) |
191 | 234 |
192 direct_deps_config_paths = [ | 235 direct_deps_config_paths = [ |
193 c for c in possible_deps_config_paths if not c in unknown_deps] | 236 c for c in possible_deps_config_paths if not c in unknown_deps] |
194 | 237 |
195 deps = Deps(direct_deps_config_paths) | 238 deps = Deps(direct_deps_config_paths) |
196 direct_library_deps = deps.Direct('java_library') | 239 direct_library_deps = deps.Direct('java_library') |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
255 # srcjar_deps). A resource's srcjar contains the R.java file for those | 298 # srcjar_deps). A resource's srcjar contains the R.java file for those |
256 # resources, and (like Android's default build system) we allow a library to | 299 # resources, and (like Android's default build system) we allow a library to |
257 # refer to the resources in any of its dependents. | 300 # refer to the resources in any of its dependents. |
258 config['javac']['srcjars'] = [ | 301 config['javac']['srcjars'] = [ |
259 c['srcjar'] for c in direct_resources_deps if 'srcjar' in c] | 302 c['srcjar'] for c in direct_resources_deps if 'srcjar' in c] |
260 | 303 |
261 if options.type == 'android_apk': | 304 if options.type == 'android_apk': |
262 # Apks will get their resources srcjar explicitly passed to the java step. | 305 # Apks will get their resources srcjar explicitly passed to the java step. |
263 config['javac']['srcjars'] = [] | 306 config['javac']['srcjars'] = [] |
264 | 307 |
| 308 if options.type == 'android_assets': |
| 309 all_asset_sources = [] |
| 310 if options.asset_renaming_sources: |
| 311 all_asset_sources.extend( |
| 312 build_utils.ParseGypList(options.asset_renaming_sources)) |
| 313 if options.asset_sources: |
| 314 all_asset_sources.extend(build_utils.ParseGypList(options.asset_sources)) |
| 315 |
| 316 deps_info['assets'] = { |
| 317 'sources': all_asset_sources |
| 318 } |
| 319 if options.asset_renaming_destinations: |
| 320 deps_info['assets']['outputs'] = ( |
| 321 build_utils.ParseGypList(options.asset_renaming_destinations)) |
| 322 if options.disable_asset_compression: |
| 323 deps_info['assets']['disable_compression'] = True |
| 324 |
265 if options.type == 'android_resources': | 325 if options.type == 'android_resources': |
266 deps_info['resources_zip'] = options.resources_zip | 326 deps_info['resources_zip'] = options.resources_zip |
267 if options.srcjar: | 327 if options.srcjar: |
268 deps_info['srcjar'] = options.srcjar | 328 deps_info['srcjar'] = options.srcjar |
269 if options.android_manifest: | 329 if options.android_manifest: |
270 manifest = AndroidManifest(options.android_manifest) | 330 manifest = AndroidManifest(options.android_manifest) |
271 deps_info['package_name'] = manifest.GetPackageName() | 331 deps_info['package_name'] = manifest.GetPackageName() |
272 if options.package_name: | 332 if options.package_name: |
273 deps_info['package_name'] = options.package_name | 333 deps_info['package_name'] = options.package_name |
274 if options.r_text: | 334 if options.r_text: |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
351 if not library_paths: | 411 if not library_paths: |
352 prev_config = build_utils.ReadJson(options.build_config) | 412 prev_config = build_utils.ReadJson(options.build_config) |
353 java_libraries_list_holder[0] = ( | 413 java_libraries_list_holder[0] = ( |
354 prev_config['native']['java_libraries_list']) | 414 prev_config['native']['java_libraries_list']) |
355 library_paths.extend(prev_config['native']['libraries']) | 415 library_paths.extend(prev_config['native']['libraries']) |
356 | 416 |
357 config['native'] = { | 417 config['native'] = { |
358 'libraries': library_paths, | 418 'libraries': library_paths, |
359 'java_libraries_list': java_libraries_list_holder[0], | 419 'java_libraries_list': java_libraries_list_holder[0], |
360 } | 420 } |
| 421 config['assets'], config['uncompressed_assets'] = ( |
| 422 _MergeAssets(deps.All('android_assets'))) |
361 | 423 |
362 build_utils.WriteJson(config, options.build_config, only_if_changed=True) | 424 build_utils.WriteJson(config, options.build_config, only_if_changed=True) |
363 | 425 |
364 if options.depfile: | 426 if options.depfile: |
365 build_utils.WriteDepfile( | 427 build_utils.WriteDepfile( |
366 options.depfile, | 428 options.depfile, |
367 deps.AllConfigPaths() + build_utils.GetPythonDependencies()) | 429 deps.AllConfigPaths() + build_utils.GetPythonDependencies()) |
368 | 430 |
369 | 431 |
370 if __name__ == '__main__': | 432 if __name__ == '__main__': |
371 sys.exit(main(sys.argv[1:])) | 433 sys.exit(main(sys.argv[1:])) |
OLD | NEW |