OLD | NEW |
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
5 | 5 |
6 """Tool for automatically creating .nmf files from .nexe/.pexe/.bc executables. | 6 """Tool for automatically creating .nmf files from .nexe/.pexe/.bc executables. |
7 | 7 |
8 As well as creating the nmf file this tool can also find and stage | 8 As well as creating the nmf file this tool can also find and stage |
9 any shared libraries dependencies that the executables might have. | 9 any shared libraries dependencies that the executables might have. |
10 """ | 10 """ |
11 | 11 |
| 12 import argparse |
12 import errno | 13 import errno |
13 import json | 14 import json |
14 import optparse | |
15 import os | 15 import os |
16 import posixpath | 16 import posixpath |
17 import shutil | 17 import shutil |
18 import sys | 18 import sys |
19 | 19 |
20 import getos | 20 import getos |
21 | 21 |
22 if sys.version_info < (2, 7, 0): | 22 if sys.version_info < (2, 7, 0): |
23 sys.stderr.write("python 2.7 or later is required run this script\n") | 23 sys.stderr.write("python 2.7 or later is required run this script\n") |
24 sys.exit(1) | 24 sys.exit(1) |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
151 path: Full path to this file on the build system | 151 path: Full path to this file on the build system |
152 arch: Architecture of this file (e.g., x86-32) | 152 arch: Architecture of this file (e.g., x86-32) |
153 url: Relative path to file in the staged web directory. | 153 url: Relative path to file in the staged web directory. |
154 Used for specifying the "url" attribute in the nmf file.""" | 154 Used for specifying the "url" attribute in the nmf file.""" |
155 | 155 |
156 def __init__(self, name, path, url=None, arch=None): | 156 def __init__(self, name, path, url=None, arch=None): |
157 self.name = name | 157 self.name = name |
158 self.path = path | 158 self.path = path |
159 self.url = url | 159 self.url = url |
160 self.arch = arch | 160 self.arch = arch |
161 if not arch: | 161 if arch is None: |
162 self.arch = ParseElfHeader(path)[0] | 162 self.arch = ParseElfHeader(path)[0] |
163 | 163 |
164 def __repr__(self): | 164 def __repr__(self): |
165 return '<ArchFile %s>' % self.path | 165 return '<ArchFile %s>' % self.path |
166 | 166 |
167 def __str__(self): | 167 def __str__(self): |
168 """Return the file path when invoked with the str() function""" | 168 """Return the file path when invoked with the str() function""" |
169 return self.path | 169 return self.path |
170 | 170 |
171 | 171 |
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
395 name = MAIN_NEXE | 395 name = MAIN_NEXE |
396 | 396 |
397 name = self.remap.get(name, name) | 397 name = self.remap.get(name, name) |
398 fileinfo = manifest[FILES_KEY].get(name, {}) | 398 fileinfo = manifest[FILES_KEY].get(name, {}) |
399 fileinfo[archinfo.arch] = urlinfo | 399 fileinfo[archinfo.arch] = urlinfo |
400 manifest[FILES_KEY][name] = fileinfo | 400 manifest[FILES_KEY][name] = fileinfo |
401 self.manifest = manifest | 401 self.manifest = manifest |
402 | 402 |
403 def GetManifest(self): | 403 def GetManifest(self): |
404 """Returns a JSON-formatted dict containing the NaCl dependencies""" | 404 """Returns a JSON-formatted dict containing the NaCl dependencies""" |
405 if not self.manifest: | 405 if self.manifest is None: |
406 if self.pnacl: | 406 if self.pnacl: |
407 self._GeneratePNaClManifest() | 407 self._GeneratePNaClManifest() |
408 else: | 408 else: |
409 self._GenerateManifest() | 409 self._GenerateManifest() |
410 return self.manifest | 410 return self.manifest |
411 | 411 |
412 def GetJson(self): | 412 def GetJson(self): |
413 """Returns the Manifest as a JSON-formatted string""" | 413 """Returns the Manifest as a JSON-formatted string""" |
414 pretty_string = json.dumps(self.GetManifest(), indent=2) | 414 pretty_string = json.dumps(self.GetManifest(), indent=2) |
415 # json.dumps sometimes returns trailing whitespace and does not put | 415 # json.dumps sometimes returns trailing whitespace and does not put |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
534 libpath += [ | 534 libpath += [ |
535 '%s/arm-nacl/lib' % bionic_dir, | 535 '%s/arm-nacl/lib' % bionic_dir, |
536 '%s/arm-nacl/usr/lib' % bionic_dir, | 536 '%s/arm-nacl/usr/lib' % bionic_dir, |
537 'lib/bionic_arm/%s' % config, | 537 'lib/bionic_arm/%s' % config, |
538 ] | 538 ] |
539 libpath = [os.path.normpath(p) for p in libpath] | 539 libpath = [os.path.normpath(p) for p in libpath] |
540 libpath = [os.path.join(sdk_root, p) for p in libpath] | 540 libpath = [os.path.join(sdk_root, p) for p in libpath] |
541 return libpath | 541 return libpath |
542 | 542 |
543 | 543 |
544 def main(argv): | 544 def main(args): |
545 parser = optparse.OptionParser( | 545 parser = argparse.ArgumentParser(description=__doc__) |
546 usage='Usage: %prog [options] nexe [extra_libs...]', description=__doc__) | 546 parser.add_argument('-o', '--output', dest='output', |
547 parser.add_option('-o', '--output', dest='output', | 547 help='Write manifest file to FILE (default is stdout)', |
548 help='Write manifest file to FILE (default is stdout)', | 548 metavar='FILE') |
549 metavar='FILE') | 549 parser.add_argument('-D', '--objdump', dest='objdump', |
550 parser.add_option('-D', '--objdump', dest='objdump', | 550 help='Override the default "objdump" tool used to find ' |
551 help='Override the default "objdump" tool used to find ' | 551 'shared object dependencies', |
552 'shared object dependencies', | 552 metavar='TOOL') |
553 metavar='TOOL') | 553 parser.add_argument('--no-default-libpath', action='store_true', |
554 parser.add_option('--no-default-libpath', action='store_true', | 554 help="Don't include the SDK default library paths") |
555 help="Don't include the SDK default library paths") | 555 parser.add_argument('--debug-libs', action='store_true', |
556 parser.add_option('--debug-libs', action='store_true', | 556 help='Use debug library paths when constructing default ' |
557 help='Use debug library paths when constructing default ' | 557 'library path.') |
558 'library path.') | 558 parser.add_argument('-L', '--library-path', dest='lib_path', |
559 parser.add_option('-L', '--library-path', dest='lib_path', | 559 action='append', default=[], |
560 action='append', default=[], | 560 help='Add DIRECTORY to library search path', |
561 help='Add DIRECTORY to library search path', | 561 metavar='DIRECTORY') |
562 metavar='DIRECTORY') | 562 parser.add_argument('-P', '--path-prefix', dest='path_prefix', default='', |
563 parser.add_option('-P', '--path-prefix', dest='path_prefix', default='', | 563 help='Deprecated. An alias for --lib-prefix.', |
564 help='Deprecated. An alias for --lib-prefix.', | 564 metavar='DIRECTORY') |
565 metavar='DIRECTORY') | 565 parser.add_argument('-p', '--lib-prefix', dest='lib_prefix', default='', |
566 parser.add_option('-p', '--lib-prefix', dest='lib_prefix', default='', | 566 help='A path to prepend to shared libraries in the .nmf', |
567 help='A path to prepend to shared libraries in the .nmf', | 567 metavar='DIRECTORY') |
568 metavar='DIRECTORY') | 568 parser.add_argument('-N', '--nexe-prefix', dest='nexe_prefix', default='', |
569 parser.add_option('-N', '--nexe-prefix', dest='nexe_prefix', default='', | 569 help='A path to prepend to nexes in the .nmf', |
570 help='A path to prepend to nexes in the .nmf', | 570 metavar='DIRECTORY') |
571 metavar='DIRECTORY') | 571 parser.add_argument('-s', '--stage-dependencies', dest='stage_dependencies', |
572 parser.add_option('-s', '--stage-dependencies', dest='stage_dependencies', | 572 help='Destination directory for staging libraries', |
573 help='Destination directory for staging libraries', | 573 metavar='DIRECTORY') |
574 metavar='DIRECTORY') | 574 parser.add_argument('--no-arch-prefix', action='store_true', |
575 parser.add_option('--no-arch-prefix', action='store_true', | 575 help='Don\'t put shared libraries in the lib32/lib64 ' |
576 help='Don\'t put shared libraries in the lib32/lib64 ' | 576 'directories. Instead, they will be put in the same ' |
577 'directories. Instead, they will be put in the same ' | 577 'directory as the .nexe that matches its architecture.') |
578 'directory as the .nexe that matches its architecture.') | 578 parser.add_argument('-t', '--toolchain', help='Legacy option, do not use') |
579 parser.add_option('-t', '--toolchain', help='Legacy option, do not use') | 579 parser.add_argument('-n', '--name', dest='name', |
580 parser.add_option('-n', '--name', dest='name', | 580 help='Rename FOO as BAR', |
581 help='Rename FOO as BAR', | 581 action='append', default=[], metavar='FOO,BAR') |
582 action='append', default=[], metavar='FOO,BAR') | 582 parser.add_argument('-x', '--extra-files', |
583 parser.add_option('-x', '--extra-files', | 583 help=('Add extra key:file tuple to the "files"' + |
584 help=('Add extra key:file tuple to the "files"' + | 584 ' section of the .nmf'), |
585 ' section of the .nmf'), | 585 action='append', default=[], metavar='FILE') |
586 action='append', default=[], metavar='FILE') | 586 parser.add_argument('-O', '--pnacl-optlevel', |
587 parser.add_option('-O', '--pnacl-optlevel', | 587 help='Set the optimization level to N in PNaCl manifests', |
588 help='Set the optimization level to N in PNaCl manifests', | 588 metavar='N') |
589 metavar='N') | 589 parser.add_argument('--pnacl-debug-optlevel', |
590 parser.add_option('--pnacl-debug-optlevel', | 590 help='Set the optimization level to N for debugging ' |
591 help='Set the optimization level to N for debugging ' | 591 'sections in PNaCl manifests', |
592 'sections in PNaCl manifests', | 592 metavar='N') |
593 metavar='N') | 593 parser.add_argument('-v', '--verbose', |
594 parser.add_option('-v', '--verbose', | 594 help='Verbose output', action='store_true') |
595 help='Verbose output', action='store_true') | 595 parser.add_argument('-d', '--debug-mode', |
596 parser.add_option('-d', '--debug-mode', | 596 help='Debug mode', action='store_true') |
597 help='Debug mode', action='store_true') | 597 parser.add_argument('executables', metavar='EXECUTABLE', nargs='+') |
598 | 598 |
599 # To enable bash completion for this command first install optcomplete | 599 # To enable bash completion for this command first install optcomplete |
600 # and then add this line to your .bashrc: | 600 # and then add this line to your .bashrc: |
601 # complete -F _optcomplete create_nmf.py | 601 # complete -F _optcomplete create_nmf.py |
602 try: | 602 try: |
603 import optcomplete | 603 import optcomplete |
604 optcomplete.autocomplete(parser) | 604 optcomplete.autocomplete(parser) |
605 except ImportError: | 605 except ImportError: |
606 pass | 606 pass |
607 | 607 |
608 options, args = parser.parse_args(argv) | 608 options = parser.parse_args(args) |
609 if options.verbose: | 609 if options.verbose: |
610 Trace.verbose = True | 610 Trace.verbose = True |
611 if options.debug_mode: | 611 if options.debug_mode: |
612 DebugPrint.debug_mode = True | 612 DebugPrint.debug_mode = True |
613 | 613 |
614 if options.toolchain is not None: | 614 if options.toolchain is not None: |
615 sys.stderr.write('warning: option -t/--toolchain is deprecated.\n') | 615 sys.stderr.write('warning: option -t/--toolchain is deprecated.\n') |
616 | 616 |
617 if len(args) < 1: | |
618 parser.error('No nexe files specified. See --help for more info') | |
619 | |
620 canonicalized = ParseExtraFiles(options.extra_files, sys.stderr) | 617 canonicalized = ParseExtraFiles(options.extra_files, sys.stderr) |
621 if canonicalized is None: | 618 if canonicalized is None: |
622 parser.error('Bad --extra-files (-x) argument syntax') | 619 parser.error('Bad --extra-files (-x) argument syntax') |
623 | 620 |
624 remap = {} | 621 remap = {} |
625 for ren in options.name: | 622 for ren in options.name: |
626 parts = ren.split(',') | 623 parts = ren.split(',') |
627 if len(parts) != 2: | 624 if len(parts) != 2: |
628 parser.error('Expecting --name=<orig_arch.so>,<new_name.so>') | 625 parser.error('Expecting --name=<orig_arch.so>,<new_name.so>') |
629 remap[parts[0]] = parts[1] | 626 remap[parts[0]] = parts[1] |
(...skipping 24 matching lines...) Expand all Loading... |
654 if options.pnacl_debug_optlevel is not None: | 651 if options.pnacl_debug_optlevel is not None: |
655 pnacl_debug_optlevel = int(options.pnacl_debug_optlevel) | 652 pnacl_debug_optlevel = int(options.pnacl_debug_optlevel) |
656 else: | 653 else: |
657 pnacl_debug_optlevel = pnacl_optlevel | 654 pnacl_debug_optlevel = pnacl_optlevel |
658 | 655 |
659 nmf_root = None | 656 nmf_root = None |
660 if options.output: | 657 if options.output: |
661 nmf_root = os.path.dirname(options.output) | 658 nmf_root = os.path.dirname(options.output) |
662 | 659 |
663 nmf = NmfUtils(objdump=options.objdump, | 660 nmf = NmfUtils(objdump=options.objdump, |
664 main_files=args, | 661 main_files=options.executables, |
665 lib_path=options.lib_path, | 662 lib_path=options.lib_path, |
666 extra_files=canonicalized, | 663 extra_files=canonicalized, |
667 lib_prefix=options.lib_prefix, | 664 lib_prefix=options.lib_prefix, |
668 nexe_prefix=options.nexe_prefix, | 665 nexe_prefix=options.nexe_prefix, |
669 no_arch_prefix=options.no_arch_prefix, | 666 no_arch_prefix=options.no_arch_prefix, |
670 remap=remap, | 667 remap=remap, |
671 pnacl_optlevel=pnacl_optlevel, | 668 pnacl_optlevel=pnacl_optlevel, |
672 pnacl_debug_optlevel=pnacl_debug_optlevel, | 669 pnacl_debug_optlevel=pnacl_debug_optlevel, |
673 nmf_root=nmf_root) | 670 nmf_root=nmf_root) |
674 | 671 |
(...skipping 13 matching lines...) Expand all Loading... |
688 if __name__ == '__main__': | 685 if __name__ == '__main__': |
689 try: | 686 try: |
690 rtn = main(sys.argv[1:]) | 687 rtn = main(sys.argv[1:]) |
691 except Error, e: | 688 except Error, e: |
692 sys.stderr.write('%s: %s\n' % (os.path.basename(__file__), e)) | 689 sys.stderr.write('%s: %s\n' % (os.path.basename(__file__), e)) |
693 rtn = 1 | 690 rtn = 1 |
694 except KeyboardInterrupt: | 691 except KeyboardInterrupt: |
695 sys.stderr.write('%s: interrupted\n' % os.path.basename(__file__)) | 692 sys.stderr.write('%s: interrupted\n' % os.path.basename(__file__)) |
696 rtn = 1 | 693 rtn = 1 |
697 sys.exit(rtn) | 694 sys.exit(rtn) |
OLD | NEW |