OLD | NEW |
---|---|
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # | 2 # |
3 # Copyright 2013 The Chromium Authors. All rights reserved. | 3 # Copyright 2013 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 import optparse | 7 import optparse |
8 import os | 8 import os |
9 import shutil | 9 import shutil |
10 import re | 10 import re |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
62 | 62 |
63 | 63 |
64 def _FilterJavaFiles(paths, filters): | 64 def _FilterJavaFiles(paths, filters): |
65 return [f for f in paths | 65 return [f for f in paths |
66 if not filters or build_utils.MatchesGlob(f, filters)] | 66 if not filters or build_utils.MatchesGlob(f, filters)] |
67 | 67 |
68 | 68 |
69 _MAX_MANIFEST_LINE_LEN = 72 | 69 _MAX_MANIFEST_LINE_LEN = 72 |
70 | 70 |
71 | 71 |
72 def _CreateManifest(manifest_path, classpath, main_class=None, | |
73 manifest_entries=None): | |
74 """Creates a manifest file with the given parameters. | |
75 | |
76 This generates a manifest file that compiles with the spec found at | |
77 http://docs.oracle.com/javase/7/docs/technotes/guides/jar/jar.html#JAR_Manifes t | |
78 | |
79 Args: | |
80 manifest_path: The path to the manifest file that should be created. | |
81 classpath: The JAR files that should be listed on the manifest file's | |
82 classpath. | |
83 main_class: If present, the class containing the main() function. | |
84 manifest_entries: If present, a list of (key, value) pairs to add to | |
85 the manifest. | |
86 | |
87 """ | |
88 output = ['Manifest-Version: 1.0'] | |
89 if main_class: | |
90 output.append('Main-Class: %s' % main_class) | |
91 if manifest_entries: | |
92 for k, v in manifest_entries: | |
93 output.append('%s: %s' % (k, v)) | |
94 if classpath: | |
95 sanitized_paths = [] | |
96 for path in classpath: | |
97 sanitized_paths.append(os.path.basename(path.strip('"'))) | |
98 output.append('Class-Path: %s' % ' '.join(sanitized_paths)) | |
99 output.append('Created-By: ') | |
100 output.append('') | |
101 | |
102 wrapper = textwrap.TextWrapper(break_long_words=True, | |
103 drop_whitespace=False, | |
104 subsequent_indent=' ', | |
105 width=_MAX_MANIFEST_LINE_LEN - 2) | |
106 output = '\r\n'.join(w for l in output for w in wrapper.wrap(l)) | |
107 | |
108 with open(manifest_path, 'w') as f: | |
109 f.write(output) | |
110 | |
111 | |
112 def _ExtractClassFiles(jar_path, dest_dir, java_files): | 72 def _ExtractClassFiles(jar_path, dest_dir, java_files): |
113 """Extracts all .class files not corresponding to |java_files|.""" | 73 """Extracts all .class files not corresponding to |java_files|.""" |
114 # Two challenges exist here: | 74 # Two challenges exist here: |
115 # 1. |java_files| have prefixes that are not represented in the the jar paths. | 75 # 1. |java_files| have prefixes that are not represented in the the jar paths. |
116 # 2. A single .java file results in multiple .class files when it contains | 76 # 2. A single .java file results in multiple .class files when it contains |
117 # nested classes. | 77 # nested classes. |
118 # Here's an example: | 78 # Here's an example: |
119 # source path: ../../base/android/java/src/org/chromium/Foo.java | 79 # source path: ../../base/android/java/src/org/chromium/Foo.java |
120 # jar paths: org/chromium/Foo.class, org/chromium/Foo$Inner.class | 80 # jar paths: org/chromium/Foo.class, org/chromium/Foo$Inner.class |
121 # To extract only .class files not related to the given .java files, we strip | 81 # To extract only .class files not related to the given .java files, we strip |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
153 def _FixTempPathsInIncrementalMetadata(pdb_path, temp_dir): | 113 def _FixTempPathsInIncrementalMetadata(pdb_path, temp_dir): |
154 # The .pdb records absolute paths. Fix up paths within /tmp (srcjars). | 114 # The .pdb records absolute paths. Fix up paths within /tmp (srcjars). |
155 if os.path.exists(pdb_path): | 115 if os.path.exists(pdb_path): |
156 # Although its a binary file, search/replace still seems to work fine. | 116 # Although its a binary file, search/replace still seems to work fine. |
157 with open(pdb_path) as fileobj: | 117 with open(pdb_path) as fileobj: |
158 pdb_data = fileobj.read() | 118 pdb_data = fileobj.read() |
159 with open(pdb_path, 'w') as fileobj: | 119 with open(pdb_path, 'w') as fileobj: |
160 fileobj.write(re.sub(r'/tmp/[^/]*', temp_dir, pdb_data)) | 120 fileobj.write(re.sub(r'/tmp/[^/]*', temp_dir, pdb_data)) |
161 | 121 |
162 | 122 |
163 def _OnStaleMd5(changes, options, javac_cmd, java_files, classpath_inputs, | 123 def _OnStaleMd5(changes, options, javac_cmd, java_files, classpath_inputs): |
164 runtime_classpath): | |
165 with build_utils.TempDir() as temp_dir: | 124 with build_utils.TempDir() as temp_dir: |
166 srcjars = options.java_srcjars | 125 srcjars = options.java_srcjars |
167 # The .excluded.jar contains .class files excluded from the main jar. | 126 # The .excluded.jar contains .class files excluded from the main jar. |
168 # It is used for incremental compiles. | 127 # It is used for incremental compiles. |
169 excluded_jar_path = options.jar_path.replace('.jar', '.excluded.jar') | 128 excluded_jar_path = options.jar_path.replace('.jar', '.excluded.jar') |
170 | 129 |
171 classes_dir = os.path.join(temp_dir, 'classes') | 130 classes_dir = os.path.join(temp_dir, 'classes') |
172 os.makedirs(classes_dir) | 131 os.makedirs(classes_dir) |
173 | 132 |
174 changed_paths = None | 133 changed_paths = None |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
256 if 'project database corrupted' not in e.output: | 215 if 'project database corrupted' not in e.output: |
257 raise | 216 raise |
258 print ('Applying work-around for jmake project database corrupted ' | 217 print ('Applying work-around for jmake project database corrupted ' |
259 '(http://crbug.com/551449).') | 218 '(http://crbug.com/551449).') |
260 os.unlink(pdb_path) | 219 os.unlink(pdb_path) |
261 attempt_build() | 220 attempt_build() |
262 elif options.incremental: | 221 elif options.incremental: |
263 # Make sure output exists. | 222 # Make sure output exists. |
264 build_utils.Touch(pdb_path) | 223 build_utils.Touch(pdb_path) |
265 | 224 |
266 if options.main_class or options.manifest_entry: | |
267 entries = [] | |
268 if options.manifest_entry: | |
269 entries = [e.split(':') for e in options.manifest_entry] | |
270 manifest_file = os.path.join(temp_dir, 'manifest') | |
271 _CreateManifest(manifest_file, runtime_classpath, options.main_class, | |
272 entries) | |
273 else: | |
274 manifest_file = None | |
275 | |
276 glob = options.jar_excluded_classes | 225 glob = options.jar_excluded_classes |
277 inclusion_predicate = lambda f: not build_utils.MatchesGlob(f, glob) | 226 inclusion_predicate = lambda f: not build_utils.MatchesGlob(f, glob) |
278 exclusion_predicate = lambda f: not inclusion_predicate(f) | 227 exclusion_predicate = lambda f: not inclusion_predicate(f) |
279 | 228 |
280 jar.JarDirectory(classes_dir, | 229 jar.JarDirectory(classes_dir, |
281 options.jar_path, | 230 options.jar_path, |
282 manifest_file=manifest_file, | |
283 predicate=inclusion_predicate) | 231 predicate=inclusion_predicate) |
284 jar.JarDirectory(classes_dir, | 232 jar.JarDirectory(classes_dir, |
285 excluded_jar_path, | 233 excluded_jar_path, |
286 predicate=exclusion_predicate) | 234 predicate=exclusion_predicate) |
287 | 235 |
288 | 236 |
289 def _ParseOptions(argv): | 237 def _ParseOptions(argv): |
290 parser = optparse.OptionParser() | 238 parser = optparse.OptionParser() |
291 build_utils.AddDepfileOption(parser) | 239 build_utils.AddDepfileOption(parser) |
292 | 240 |
(...skipping 10 matching lines...) Expand all Loading... | |
303 action='append', | 251 action='append', |
304 default=[], | 252 default=[], |
305 help='Boot classpath for javac. If this is specified multiple times, ' | 253 help='Boot classpath for javac. If this is specified multiple times, ' |
306 'they will all be appended to construct the classpath.') | 254 'they will all be appended to construct the classpath.') |
307 parser.add_option( | 255 parser.add_option( |
308 '--classpath', | 256 '--classpath', |
309 action='append', | 257 action='append', |
310 help='Classpath for javac. If this is specified multiple times, they ' | 258 help='Classpath for javac. If this is specified multiple times, they ' |
311 'will all be appended to construct the classpath.') | 259 'will all be appended to construct the classpath.') |
312 parser.add_option( | 260 parser.add_option( |
313 '--use-ijars', | |
314 action='store_true', | |
315 help='Whether to use interface jars (.interface.jar) when compiling') | |
316 parser.add_option( | |
317 '--incremental', | 261 '--incremental', |
318 action='store_true', | 262 action='store_true', |
319 help='Whether to re-use .class files rather than recompiling them ' | 263 help='Whether to re-use .class files rather than recompiling them ' |
320 '(when possible).') | 264 '(when possible).') |
321 parser.add_option( | 265 parser.add_option( |
322 '--javac-includes', | 266 '--javac-includes', |
323 default='', | 267 default='', |
324 help='A list of file patterns. If provided, only java files that match' | 268 help='A list of file patterns. If provided, only java files that match' |
325 'one of the patterns will be compiled.') | 269 'one of the patterns will be compiled.') |
326 parser.add_option( | 270 parser.add_option( |
327 '--jar-excluded-classes', | 271 '--jar-excluded-classes', |
328 default='', | 272 default='', |
329 help='List of .class file patterns to exclude from the jar.') | 273 help='List of .class file patterns to exclude from the jar.') |
330 | |
331 parser.add_option( | 274 parser.add_option( |
332 '--chromium-code', | 275 '--chromium-code', |
333 type='int', | 276 type='int', |
334 help='Whether code being compiled should be built with stricter ' | 277 help='Whether code being compiled should be built with stricter ' |
335 'warnings for chromium code.') | 278 'warnings for chromium code.') |
336 | |
337 parser.add_option( | 279 parser.add_option( |
338 '--use-errorprone-path', | 280 '--use-errorprone-path', |
339 help='Use the Errorprone compiler at this path.') | 281 help='Use the Errorprone compiler at this path.') |
340 | |
341 parser.add_option('--jar-path', help='Jar output path.') | 282 parser.add_option('--jar-path', help='Jar output path.') |
342 parser.add_option( | |
jbudorick
2016/04/01 04:37:43
Does removing this break junit tests on gyp? https
agrieve
2016/04/01 17:39:03
Hrm, my codesearch skills failed me on this one I
| |
343 '--main-class', | |
344 help='The class containing the main method.') | |
345 parser.add_option( | |
346 '--manifest-entry', | |
347 action='append', | |
348 help='Key:value pairs to add to the .jar manifest.') | |
349 | |
350 parser.add_option('--stamp', help='Path to touch on success.') | 283 parser.add_option('--stamp', help='Path to touch on success.') |
351 | 284 |
352 options, args = parser.parse_args(argv) | 285 options, args = parser.parse_args(argv) |
353 build_utils.CheckOptions(options, parser, required=('jar_path',)) | 286 build_utils.CheckOptions(options, parser, required=('jar_path',)) |
354 | 287 |
355 bootclasspath = [] | 288 bootclasspath = [] |
356 for arg in options.bootclasspath: | 289 for arg in options.bootclasspath: |
357 bootclasspath += build_utils.ParseGypList(arg) | 290 bootclasspath += build_utils.ParseGypList(arg) |
358 options.bootclasspath = bootclasspath | 291 options.bootclasspath = bootclasspath |
359 | 292 |
(...skipping 20 matching lines...) Expand all Loading... | |
380 colorama.init() | 313 colorama.init() |
381 | 314 |
382 argv = build_utils.ExpandFileArgs(argv) | 315 argv = build_utils.ExpandFileArgs(argv) |
383 options, java_files = _ParseOptions(argv) | 316 options, java_files = _ParseOptions(argv) |
384 | 317 |
385 if options.src_gendirs: | 318 if options.src_gendirs: |
386 java_files += build_utils.FindInDirectories(options.src_gendirs, '*.java') | 319 java_files += build_utils.FindInDirectories(options.src_gendirs, '*.java') |
387 | 320 |
388 java_files = _FilterJavaFiles(java_files, options.javac_includes) | 321 java_files = _FilterJavaFiles(java_files, options.javac_includes) |
389 | 322 |
390 runtime_classpath = options.classpath | |
391 compile_classpath = runtime_classpath | |
392 if options.use_ijars: | |
393 ijar_re = re.compile(r'\.jar$') | |
394 compile_classpath = ( | |
395 [ijar_re.sub('.interface.jar', p) for p in runtime_classpath]) | |
396 | |
397 javac_cmd = ['javac'] | 323 javac_cmd = ['javac'] |
398 if options.use_errorprone_path: | 324 if options.use_errorprone_path: |
399 javac_cmd = [options.use_errorprone_path] + ERRORPRONE_OPTIONS | 325 javac_cmd = [options.use_errorprone_path] + ERRORPRONE_OPTIONS |
400 | 326 |
401 javac_cmd.extend(( | 327 javac_cmd.extend(( |
402 '-g', | 328 '-g', |
403 # Chromium only allows UTF8 source files. Being explicit avoids | 329 # Chromium only allows UTF8 source files. Being explicit avoids |
404 # javac pulling a default encoding from the user's environment. | 330 # javac pulling a default encoding from the user's environment. |
405 '-encoding', 'UTF-8', | 331 '-encoding', 'UTF-8', |
406 '-classpath', ':'.join(compile_classpath), | 332 '-classpath', ':'.join(options.classpath), |
407 # Prevent compiler from compiling .java files not listed as inputs. | 333 # Prevent compiler from compiling .java files not listed as inputs. |
408 # See: http://blog.ltgt.net/most-build-tools-misuse-javac/ | 334 # See: http://blog.ltgt.net/most-build-tools-misuse-javac/ |
409 '-sourcepath', '' | 335 '-sourcepath', '' |
410 )) | 336 )) |
411 | 337 |
412 if options.bootclasspath: | 338 if options.bootclasspath: |
413 javac_cmd.extend([ | 339 javac_cmd.extend([ |
414 '-bootclasspath', ':'.join(options.bootclasspath), | 340 '-bootclasspath', ':'.join(options.bootclasspath), |
415 '-source', '1.7', | 341 '-source', '1.7', |
416 '-target', '1.7', | 342 '-target', '1.7', |
417 ]) | 343 ]) |
418 | 344 |
419 if options.chromium_code: | 345 if options.chromium_code: |
420 javac_cmd.extend(['-Xlint:unchecked', '-Xlint:deprecation']) | 346 javac_cmd.extend(['-Xlint:unchecked', '-Xlint:deprecation']) |
421 else: | 347 else: |
422 # XDignore.symbol.file makes javac compile against rt.jar instead of | 348 # XDignore.symbol.file makes javac compile against rt.jar instead of |
423 # ct.sym. This means that using a java internal package/class will not | 349 # ct.sym. This means that using a java internal package/class will not |
424 # trigger a compile warning or error. | 350 # trigger a compile warning or error. |
425 javac_cmd.extend(['-XDignore.symbol.file']) | 351 javac_cmd.extend(['-XDignore.symbol.file']) |
426 | 352 |
427 classpath_inputs = options.bootclasspath | 353 classpath_inputs = options.bootclasspath |
428 # TODO(agrieve): Remove this .TOC heuristic once GYP is no more. | 354 # TODO(agrieve): Remove this .TOC heuristic once GYP is no more. |
429 if options.use_ijars: | 355 if options.classpath and not options.classpath[0].endswith('.interface.jar'): |
430 classpath_inputs.extend(compile_classpath) | 356 for path in options.classpath: |
431 else: | |
432 for path in compile_classpath: | |
433 if os.path.exists(path + '.TOC'): | 357 if os.path.exists(path + '.TOC'): |
434 classpath_inputs.append(path + '.TOC') | 358 classpath_inputs.append(path + '.TOC') |
435 else: | 359 else: |
436 classpath_inputs.append(path) | 360 classpath_inputs.append(path) |
437 | 361 |
438 # Compute the list of paths that when changed, we need to rebuild. | 362 # Compute the list of paths that when changed, we need to rebuild. |
439 input_paths = classpath_inputs + options.java_srcjars + java_files | 363 input_paths = classpath_inputs + options.java_srcjars + java_files |
440 | 364 |
441 output_paths = [ | 365 output_paths = [ |
442 options.jar_path, | 366 options.jar_path, |
443 options.jar_path.replace('.jar', '.excluded.jar'), | 367 options.jar_path.replace('.jar', '.excluded.jar'), |
444 ] | 368 ] |
445 if options.incremental: | 369 if options.incremental: |
446 output_paths.append(options.jar_path + '.pdb') | 370 output_paths.append(options.jar_path + '.pdb') |
447 | 371 |
448 # An escape hatch to be able to check if incremental compiles are causing | 372 # An escape hatch to be able to check if incremental compiles are causing |
449 # problems. | 373 # problems. |
450 force = int(os.environ.get('DISABLE_INCREMENTAL_JAVAC', 0)) | 374 force = int(os.environ.get('DISABLE_INCREMENTAL_JAVAC', 0)) |
451 | 375 |
452 # List python deps in input_strings rather than input_paths since the contents | 376 # List python deps in input_strings rather than input_paths since the contents |
453 # of them does not change what gets written to the depsfile. | 377 # of them does not change what gets written to the depsfile. |
454 build_utils.CallAndWriteDepfileIfStale( | 378 build_utils.CallAndWriteDepfileIfStale( |
455 lambda changes: _OnStaleMd5(changes, options, javac_cmd, java_files, | 379 lambda changes: _OnStaleMd5(changes, options, javac_cmd, java_files, |
456 classpath_inputs, runtime_classpath), | 380 classpath_inputs), |
457 options, | 381 options, |
458 input_paths=input_paths, | 382 input_paths=input_paths, |
459 input_strings=javac_cmd, | 383 input_strings=javac_cmd, |
460 output_paths=output_paths, | 384 output_paths=output_paths, |
461 force=force, | 385 force=force, |
462 pass_changes=True) | 386 pass_changes=True) |
463 | 387 |
464 | 388 |
465 if __name__ == '__main__': | 389 if __name__ == '__main__': |
466 sys.exit(main(sys.argv[1:])) | 390 sys.exit(main(sys.argv[1:])) |
OLD | NEW |