| 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 |