OLD | NEW |
---|---|
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # | 2 # |
3 # Copyright 2012 the V8 project authors. All rights reserved. | 3 # Copyright 2012 the V8 project authors. All rights reserved. |
4 # Redistribution and use in source and binary forms, with or without | 4 # Redistribution and use in source and binary forms, with or without |
5 # modification, are permitted provided that the following conditions are | 5 # modification, are permitted provided that the following conditions are |
6 # met: | 6 # met: |
7 # | 7 # |
8 # * Redistributions of source code must retain the above copyright | 8 # * Redistributions of source code must retain the above copyright |
9 # notice, this list of conditions and the following disclaimer. | 9 # notice, this list of conditions and the following disclaimer. |
10 # * Redistributions in binary form must reproduce the above | 10 # * Redistributions in binary form must reproduce the above |
(...skipping 322 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
333 """ | 333 """ |
334 | 334 |
335 | 335 |
336 def BuildFilterChain(macro_filename, message_template_file): | 336 def BuildFilterChain(macro_filename, message_template_file): |
337 """Build the chain of filter functions to be applied to the sources. | 337 """Build the chain of filter functions to be applied to the sources. |
338 | 338 |
339 Args: | 339 Args: |
340 macro_filename: Name of the macro file, if any. | 340 macro_filename: Name of the macro file, if any. |
341 | 341 |
342 Returns: | 342 Returns: |
343 A function (string -> string) that reads a source file and processes it. | 343 A function (string -> string) that processes a source file. |
344 """ | 344 """ |
345 filter_chain = [ReadFile] | 345 filter_chain = [] |
346 | 346 |
347 if macro_filename: | 347 if macro_filename: |
348 (consts, macros) = ReadMacros(ReadFile(macro_filename)) | 348 (consts, macros) = ReadMacros(ReadFile(macro_filename)) |
349 filter_chain.append(lambda l: ExpandConstants(l, consts)) | 349 filter_chain.append(lambda l: ExpandConstants(l, consts)) |
350 filter_chain.append(lambda l: ExpandMacros(l, macros)) | 350 filter_chain.append(lambda l: ExpandMacros(l, macros)) |
351 | 351 |
352 if message_template_file: | 352 if message_template_file: |
353 message_templates = ReadMessageTemplates(ReadFile(message_template_file)) | 353 message_templates = ReadMessageTemplates(ReadFile(message_template_file)) |
354 filter_chain.append(lambda l: ExpandConstants(l, message_templates)) | 354 filter_chain.append(lambda l: ExpandConstants(l, message_templates)) |
355 | 355 |
356 filter_chain.extend([ | 356 filter_chain.extend([ |
357 RemoveCommentsAndTrailingWhitespace, | 357 RemoveCommentsAndTrailingWhitespace, |
358 ExpandInlineMacros, | 358 ExpandInlineMacros, |
359 ExpandInlineConstants, | 359 ExpandInlineConstants, |
360 Validate, | 360 Validate, |
361 jsmin.JavaScriptMinifier().JSMinify | 361 jsmin.JavaScriptMinifier().JSMinify |
362 ]) | 362 ]) |
363 | 363 |
364 def chain(f1, f2): | 364 def chain(f1, f2): |
365 return lambda x: f2(f1(x)) | 365 return lambda x: f2(f1(x)) |
366 | 366 |
367 return reduce(chain, filter_chain) | 367 return reduce(chain, filter_chain) |
368 | 368 |
369 def BuildExtraFilterChain(): | 369 def BuildExtraFilterChain(): |
370 return lambda x: RemoveCommentsAndTrailingWhitespace(Validate(ReadFile(x))) | 370 return lambda x: RemoveCommentsAndTrailingWhitespace(Validate(x)) |
371 | 371 |
372 class Sources: | 372 class Sources: |
373 def __init__(self): | 373 def __init__(self): |
374 self.names = [] | 374 self.names = [] |
375 self.modules = [] | 375 self.modules = [] |
376 self.is_debugger_id = [] | 376 self.is_debugger_id = [] |
377 | 377 |
378 | 378 |
379 def IsDebuggerFile(filename): | 379 def IsDebuggerFile(filename): |
380 return filename.endswith("-debugger.js") | 380 return filename.endswith("-debugger.js") |
381 | 381 |
382 def IsMacroFile(filename): | 382 def IsMacroFile(filename): |
383 return filename.endswith("macros.py") | 383 return filename.endswith("macros.py") |
384 | 384 |
385 def IsMessageTemplateFile(filename): | 385 def IsMessageTemplateFile(filename): |
386 return filename.endswith("messages.h") | 386 return filename.endswith("messages.h") |
387 | 387 |
388 | 388 |
389 def PrepareSources(source_files, extra_files, emit_js): | 389 def PrepareSources(source_files, native_type, emit_js): |
390 """Read, prepare and assemble the list of source files. | 390 """Read, prepare and assemble the list of source files. |
391 | 391 |
392 Args: | 392 Args: |
393 source_files: List of JavaScript-ish source files. A file named macros.py | 393 source_files: List of JavaScript-ish source files. A file named macros.py |
394 will be treated as a list of macros. | 394 will be treated as a list of macros. |
395 extra_files: List of JavaScript-ish extra source files, passed in | 395 native_type: String corresponding to a NativeType enum value, allowing us |
396 externally from V8. Will not be minified or macro-ified. | 396 to treat different types of sources differently. |
397 emit_js: True if we should skip the byte conversion and just leave the | 397 emit_js: True if we should skip the byte conversion and just leave the |
398 sources as JS strings. | 398 sources as JS strings. |
399 | 399 |
400 Returns: | 400 Returns: |
401 An instance of Sources. | 401 An instance of Sources. |
402 """ | 402 """ |
403 macro_file = None | 403 macro_file = None |
404 macro_files = filter(IsMacroFile, source_files) | 404 macro_files = filter(IsMacroFile, source_files) |
405 assert len(macro_files) in [0, 1] | 405 assert len(macro_files) in [0, 1] |
406 if macro_files: | 406 if macro_files: |
407 source_files.remove(macro_files[0]) | 407 source_files.remove(macro_files[0]) |
408 macro_file = macro_files[0] | 408 macro_file = macro_files[0] |
409 | 409 |
410 message_template_file = None | 410 message_template_file = None |
411 message_template_files = filter(IsMessageTemplateFile, source_files) | 411 message_template_files = filter(IsMessageTemplateFile, source_files) |
412 assert len(message_template_files) in [0, 1] | 412 assert len(message_template_files) in [0, 1] |
413 if message_template_files: | 413 if message_template_files: |
414 source_files.remove(message_template_files[0]) | 414 source_files.remove(message_template_files[0]) |
415 message_template_file = message_template_files[0] | 415 message_template_file = message_template_files[0] |
416 | 416 |
417 filters = BuildFilterChain(macro_file, message_template_file) | 417 filters = BuildExtraFilterChain if native_type == "EXTRA" else BuildFilterChai n(macro_file, message_template_file) |
Yang
2015/05/06 13:59:54
Can we have a normal if-else here please? Would al
| |
418 extra_filters = BuildExtraFilterChain() | |
419 | 418 |
420 # Sort 'debugger' sources first. | 419 # Sort 'debugger' sources first. |
421 source_files = sorted(source_files, | 420 source_files = sorted(source_files, |
422 lambda l,r: IsDebuggerFile(r) - IsDebuggerFile(l)) | 421 lambda l,r: IsDebuggerFile(r) - IsDebuggerFile(l)) |
423 | 422 |
423 source_files_and_contents = [(f, ReadFile(f)) for f in source_files] | |
424 | |
425 # Have a single not-quite-empty source file if there are none present; | |
426 # otherwise you get errors trying to compile an empty C++ array. | |
427 if not source_files_and_contents: | |
428 source_files_and_contents = [("dummy.js", " ")] | |
429 | |
424 result = Sources() | 430 result = Sources() |
425 | 431 |
426 for source in source_files: | 432 for (source, contents) in source_files_and_contents: |
427 try: | 433 try: |
428 lines = filters(source) | 434 lines = filters(contents) |
429 except Error as e: | 435 except Error as e: |
430 raise Error("In file %s:\n%s" % (source, str(e))) | 436 raise Error("In file %s:\n%s" % (source, str(e))) |
431 | 437 |
432 result.modules.append(lines) | 438 result.modules.append(lines) |
433 | 439 |
434 is_debugger = IsDebuggerFile(source) | 440 is_debugger = IsDebuggerFile(source) |
435 result.is_debugger_id.append(is_debugger) | 441 result.is_debugger_id.append(is_debugger) |
436 | 442 |
437 name = os.path.basename(source)[:-3] | 443 name = os.path.basename(source)[:-3] |
438 result.names.append(name if not is_debugger else name[:-9]) | 444 result.names.append(name if not is_debugger else name[:-9]) |
439 | 445 |
440 for extra in extra_files: | |
441 try: | |
442 lines = extra_filters(extra) | |
443 except Error as e: | |
444 raise Error("In file %s:\n%s" % (extra, str(e))) | |
445 | |
446 result.modules.append(lines) | |
447 name = os.path.basename(extra)[:-3] | |
448 result.names.append(name) | |
449 | |
450 return result | 446 return result |
451 | 447 |
452 | 448 |
453 def BuildMetadata(sources, source_bytes, native_type): | 449 def BuildMetadata(sources, source_bytes, native_type): |
454 """Build the meta data required to generate a libaries file. | 450 """Build the meta data required to generate a libaries file. |
455 | 451 |
456 Args: | 452 Args: |
457 sources: A Sources instance with the prepared sources. | 453 sources: A Sources instance with the prepared sources. |
458 source_bytes: A list of source bytes. | 454 source_bytes: A list of source bytes. |
459 (The concatenation of all sources; might be compressed.) | 455 (The concatenation of all sources; might be compressed.) |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
543 PutStr(output, sources.modules[i]); | 539 PutStr(output, sources.modules[i]); |
544 | 540 |
545 PutInt(output, len(sources.names) - debug_sources) | 541 PutInt(output, len(sources.names) - debug_sources) |
546 for i in xrange(debug_sources, len(sources.names)): | 542 for i in xrange(debug_sources, len(sources.names)): |
547 PutStr(output, sources.names[i]); | 543 PutStr(output, sources.names[i]); |
548 PutStr(output, sources.modules[i]); | 544 PutStr(output, sources.modules[i]); |
549 | 545 |
550 output.close() | 546 output.close() |
551 | 547 |
552 | 548 |
553 def JS2C(sources, extra_sources, target, native_type, raw_file, startup_blob, em itJS): | 549 def JS2C(sources, target, native_type, raw_file, startup_blob, emit_js): |
554 prepared_sources = PrepareSources(sources, extra_sources, emitJS) | 550 prepared_sources = PrepareSources(sources, native_type, emit_js) |
555 sources_output = "".join(prepared_sources.modules) | 551 sources_output = "".join(prepared_sources.modules) |
556 metadata = BuildMetadata(prepared_sources, sources_output, native_type) | 552 metadata = BuildMetadata(prepared_sources, sources_output, native_type) |
557 | 553 |
558 # Optionally emit raw file. | 554 # Optionally emit raw file. |
559 if raw_file: | 555 if raw_file: |
560 output = open(raw_file, "w") | 556 output = open(raw_file, "w") |
561 output.write(sources_output) | 557 output.write(sources_output) |
562 output.close() | 558 output.close() |
563 | 559 |
564 if startup_blob: | 560 if startup_blob: |
565 WriteStartupBlob(prepared_sources, startup_blob) | 561 WriteStartupBlob(prepared_sources, startup_blob) |
566 | 562 |
567 # Emit resulting source file. | 563 # Emit resulting source file. |
568 output = open(target, "w") | 564 output = open(target, "w") |
569 if emitJS: | 565 if emit_js: |
570 output.write(sources_output) | 566 output.write(sources_output) |
571 else: | 567 else: |
572 output.write(HEADER_TEMPLATE % metadata) | 568 output.write(HEADER_TEMPLATE % metadata) |
573 output.close() | 569 output.close() |
574 | 570 |
575 | 571 |
576 def main(): | 572 def main(): |
577 parser = argparse.ArgumentParser() | 573 parser = argparse.ArgumentParser() |
578 parser.add_argument("out.cc", | 574 parser.add_argument("out.cc", |
579 help="output filename") | 575 help="output filename") |
580 parser.add_argument("type", | 576 parser.add_argument("type", |
581 help="type parameter for NativesCollection template") | 577 help="type parameter for NativesCollection template (see N ativeType enum)") |
Yang
2015/05/06 13:59:54
keeping 80 char limit would be nice.
| |
582 parser.add_argument("sources.js", | 578 parser.add_argument("sources.js", |
583 help="JS internal sources or macros.py.", | 579 help="JS internal sources or macros.py.", |
584 nargs="+") | 580 nargs="*") |
585 parser.add_argument("--raw", | 581 parser.add_argument("--raw", |
586 help="file to write the processed sources array to.") | 582 help="file to write the processed sources array to.") |
587 parser.add_argument("--startup_blob", | 583 parser.add_argument("--startup_blob", |
588 help="file to write the startup blob to.") | 584 help="file to write the startup blob to.") |
589 parser.add_argument("--extra", | |
590 help="extra JS sources.", | |
591 nargs="*") | |
592 parser.add_argument("--js", | 585 parser.add_argument("--js", |
593 help="writes a JS file output instead of a C file", | 586 help="writes a JS file output instead of a C file", |
594 action="store_true") | 587 action="store_true") |
595 | 588 |
596 args = vars(parser.parse_args()) | 589 args = vars(parser.parse_args()) |
597 JS2C(args["sources.js"], args["extra"] or [], args["out.cc"], args["type"], ar gs["raw"], args["startup_blob"], | 590 JS2C(args["sources.js"], args["out.cc"], args["type"], args["raw"], args["star tup_blob"], args["js"]) |
598 args["js"]) | |
599 | 591 |
600 | 592 |
601 if __name__ == "__main__": | 593 if __name__ == "__main__": |
602 main() | 594 main() |
OLD | NEW |