Chromium Code Reviews| 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 |