Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(35)

Side by Side Diff: native_client_sdk/src/tools/create_nmf.py

Issue 720233003: [NaCl SDK] Convert python scripts from optparse to argparse. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 errno 12 import errno
13 import json 13 import json
14 import optparse 14 import argparse
binji 2014/11/13 23:57:03 sort
Sam Clegg 2014/11/30 17:55:12 Done.
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, 6, 0): 22 if sys.version_info < (2, 6, 0):
23 sys.stderr.write("python 2.6 or later is required run this script\n") 23 sys.stderr.write("python 2.6 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
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
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 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
458 seen_error = True 458 seen_error = True
459 else: 459 else:
460 canonicalized.append([unquoted[0], unquoted[2], unquoted[4]]) 460 canonicalized.append([unquoted[0], unquoted[2], unquoted[4]])
461 else: 461 else:
462 err.write('Bad key:arch:url tuple for --extra-files: ' + kv + '\n') 462 err.write('Bad key:arch:url tuple for --extra-files: ' + kv + '\n')
463 if seen_error: 463 if seen_error:
464 return None 464 return None
465 return canonicalized 465 return canonicalized
466 466
467 467
468 def IsValidSDKRoot(directory):
469 if not os.path.exists(os.path.join(directory, 'toolchain')):
binji 2014/11/13 23:57:03 just return os.path.exists(...) ?
Sam Clegg 2014/11/30 17:55:12 Split into seperate CL
470 return False
471
472 return True
473
474
468 def GetSDKRoot(): 475 def GetSDKRoot():
469 """Determine current NACL_SDK_ROOT, either via the environment variable 476 """Determine current NACL_SDK_ROOT, either via the environment variable
470 itself, or by attempting to derive it from the location of this script. 477 itself, or by attempting to derive it from the location of this script.
471 """ 478 """
472 sdk_root = os.environ.get('NACL_SDK_ROOT') 479 sdk_root = os.environ.get('NACL_SDK_ROOT')
473 if not sdk_root: 480 if sdk_root:
binji 2014/11/13 23:57:03 Is this change necessary?
Sam Clegg 2014/11/30 17:55:12 Separate CL
474 sdk_root = os.path.dirname(SCRIPT_DIR) 481 if not IsValidSDKRoot(sdk_root):
475 if not os.path.exists(os.path.join(sdk_root, 'toolchain')): 482 raise Error('Invalid NACL_SDK_ROOT: %s' % sdk_root)
476 return None 483 return sdk_root
477 484
478 return sdk_root 485 # If no $NACL_SDK_ROOT set then use the current script location to
486 # attempt to drive the root.
binji 2014/11/13 23:57:03 sp: derive
Sam Clegg 2014/11/30 17:55:12 Separate CL
487 sdk_root = os.path.dirname(SCRIPT_DIR)
488 if IsValidSDKRoot(sdk_root):
489 return sdk_root
490
491 return None
479 492
480 493
481 def FindObjdumpExecutable(): 494 def FindObjdumpExecutable():
482 """Derive path to objdump executable to use for determining shared 495 """Derive path to objdump executable to use for determining shared
483 object dependencies. 496 object dependencies.
484 """ 497 """
485 sdk_root = GetSDKRoot() 498 sdk_root = GetSDKRoot()
486 if not sdk_root: 499 if sdk_root is None:
487 return None 500 return None
488 501
489 osname = getos.GetPlatform() 502 osname = getos.GetPlatform()
490 toolchain = os.path.join(sdk_root, 'toolchain', '%s_x86_glibc' % osname) 503 toolchain = os.path.join(sdk_root, 'toolchain', '%s_x86_glibc' % osname)
491 objdump = os.path.join(toolchain, 'bin', 'x86_64-nacl-objdump') 504 objdump = os.path.join(toolchain, 'bin', 'x86_64-nacl-objdump')
492 if osname == 'win': 505 if osname == 'win':
493 objdump += '.exe' 506 objdump += '.exe'
494 507
495 if not os.path.exists(objdump): 508 if not os.path.exists(objdump):
496 sys.stderr.write('WARNING: failed to find objdump in default ' 509 sys.stderr.write('WARNING: failed to find objdump in default '
497 'location: %s' % objdump) 510 'location: %s' % objdump)
498 return None 511 return None
499 512
500 return objdump 513 return objdump
501 514
502 515
503 def GetDefaultLibPath(config): 516 def GetDefaultLibPath(config):
504 """Derive default library path to use when searching for shared 517 """Derive default library path to use when searching for shared
505 objects. This currently include the toolchain library folders 518 objects. This currently include the toolchain library folders
506 as well as the top level SDK lib folder and the naclports lib 519 as well as the top level SDK lib folder and the naclports lib
507 folder. We include both 32-bit and 64-bit library paths. 520 folder. We include both 32-bit and 64-bit library paths.
508 """ 521 """
509 assert(config in ('Debug', 'Release')) 522 assert(config in ('Debug', 'Release'))
510 sdk_root = GetSDKRoot() 523 sdk_root = GetSDKRoot()
511 if not sdk_root: 524 if sdk_root is None:
512 # TOOD(sbc): output a warning here? We would also need to suppress 525 # TOOD(sbc): output a warning here? We would also need to suppress
513 # the warning when run from the chromium build. 526 # the warning when run from the chromium build.
514 return [] 527 return []
515 528
516 osname = getos.GetPlatform() 529 osname = getos.GetPlatform()
517 libpath = [ 530 libpath = [
518 # Core toolchain libraries 531 # Core toolchain libraries
519 'toolchain/%s_x86_glibc/x86_64-nacl/lib' % osname, 532 'toolchain/%s_x86_glibc/x86_64-nacl/lib' % osname,
520 'toolchain/%s_x86_glibc/x86_64-nacl/lib32' % osname, 533 'toolchain/%s_x86_glibc/x86_64-nacl/lib32' % osname,
521 # naclports installed libraries 534 # naclports installed libraries
(...skipping 13 matching lines...) Expand all
535 '%s/arm-nacl/lib' % bionic_dir, 548 '%s/arm-nacl/lib' % bionic_dir,
536 '%s/arm-nacl/usr/lib' % bionic_dir, 549 '%s/arm-nacl/usr/lib' % bionic_dir,
537 'lib/bionic_arm/%s' % config, 550 'lib/bionic_arm/%s' % config,
538 ] 551 ]
539 libpath = [os.path.normpath(p) for p in libpath] 552 libpath = [os.path.normpath(p) for p in libpath]
540 libpath = [os.path.join(sdk_root, p) for p in libpath] 553 libpath = [os.path.join(sdk_root, p) for p in libpath]
541 return libpath 554 return libpath
542 555
543 556
544 def main(argv): 557 def main(argv):
545 parser = optparse.OptionParser( 558 parser = argparse.ArgumentParser(description=__doc__)
546 usage='Usage: %prog [options] nexe [extra_libs...]', description=__doc__) 559 parser.add_argument('-o', '--output', dest='output',
547 parser.add_option('-o', '--output', dest='output', 560 help='Write manifest file to FILE (default is stdout)',
548 help='Write manifest file to FILE (default is stdout)', 561 metavar='FILE')
549 metavar='FILE') 562 parser.add_argument('-D', '--objdump', dest='objdump',
550 parser.add_option('-D', '--objdump', dest='objdump', 563 help='Override the default "objdump" tool used to find '
551 help='Override the default "objdump" tool used to find ' 564 'shared object dependencies',
552 'shared object dependencies', 565 metavar='TOOL')
553 metavar='TOOL') 566 parser.add_argument('--no-default-libpath', action='store_true',
554 parser.add_option('--no-default-libpath', action='store_true', 567 help="Don't include the SDK default library paths")
555 help="Don't include the SDK default library paths") 568 parser.add_argument('--debug-libs', action='store_true',
556 parser.add_option('--debug-libs', action='store_true', 569 help='Use debug library paths when constructing default '
557 help='Use debug library paths when constructing default ' 570 'library path.')
558 'library path.') 571 parser.add_argument('-L', '--library-path', dest='lib_path',
559 parser.add_option('-L', '--library-path', dest='lib_path', 572 action='append', default=[],
560 action='append', default=[], 573 help='Add DIRECTORY to library search path',
561 help='Add DIRECTORY to library search path', 574 metavar='DIRECTORY')
562 metavar='DIRECTORY') 575 parser.add_argument('-P', '--path-prefix', dest='path_prefix', default='',
563 parser.add_option('-P', '--path-prefix', dest='path_prefix', default='', 576 help='Deprecated. An alias for --lib-prefix.',
564 help='Deprecated. An alias for --lib-prefix.', 577 metavar='DIRECTORY')
565 metavar='DIRECTORY') 578 parser.add_argument('-p', '--lib-prefix', dest='lib_prefix', default='',
566 parser.add_option('-p', '--lib-prefix', dest='lib_prefix', default='', 579 help='A path to prepend to shared libraries in the .nmf',
567 help='A path to prepend to shared libraries in the .nmf', 580 metavar='DIRECTORY')
568 metavar='DIRECTORY') 581 parser.add_argument('-N', '--nexe-prefix', dest='nexe_prefix', default='',
569 parser.add_option('-N', '--nexe-prefix', dest='nexe_prefix', default='', 582 help='A path to prepend to nexes in the .nmf',
570 help='A path to prepend to nexes in the .nmf', 583 metavar='DIRECTORY')
571 metavar='DIRECTORY') 584 parser.add_argument('-s', '--stage-dependencies', dest='stage_dependencies',
572 parser.add_option('-s', '--stage-dependencies', dest='stage_dependencies', 585 help='Destination directory for staging libraries',
573 help='Destination directory for staging libraries', 586 metavar='DIRECTORY')
574 metavar='DIRECTORY') 587 parser.add_argument('--no-arch-prefix', action='store_true',
575 parser.add_option('--no-arch-prefix', action='store_true', 588 help='Don\'t put shared libraries in the lib32/lib64 '
576 help='Don\'t put shared libraries in the lib32/lib64 ' 589 'directories. Instead, they will be put in the same '
577 'directories. Instead, they will be put in the same ' 590 'directory as the .nexe that matches its architecture.')
578 'directory as the .nexe that matches its architecture.') 591 parser.add_argument('-t', '--toolchain', help='Legacy option, do not use')
579 parser.add_option('-t', '--toolchain', help='Legacy option, do not use') 592 parser.add_argument('-n', '--name', dest='name',
580 parser.add_option('-n', '--name', dest='name', 593 help='Rename FOO as BAR',
581 help='Rename FOO as BAR', 594 action='append', default=[], metavar='FOO,BAR')
582 action='append', default=[], metavar='FOO,BAR') 595 parser.add_argument('-x', '--extra-files',
583 parser.add_option('-x', '--extra-files', 596 help=('Add extra key:file tuple to the "files"' +
584 help=('Add extra key:file tuple to the "files"' + 597 ' section of the .nmf'),
585 ' section of the .nmf'), 598 action='append', default=[], metavar='FILE')
586 action='append', default=[], metavar='FILE') 599 parser.add_argument('-O', '--pnacl-optlevel',
587 parser.add_option('-O', '--pnacl-optlevel', 600 help='Set the optimization level to N in PNaCl manifests',
588 help='Set the optimization level to N in PNaCl manifests', 601 metavar='N')
589 metavar='N') 602 parser.add_argument('--pnacl-debug-optlevel',
590 parser.add_option('--pnacl-debug-optlevel', 603 help='Set the optimization level to N for debugging '
591 help='Set the optimization level to N for debugging ' 604 'sections in PNaCl manifests',
592 'sections in PNaCl manifests', 605 metavar='N')
593 metavar='N') 606 parser.add_argument('-v', '--verbose',
594 parser.add_option('-v', '--verbose', 607 help='Verbose output', action='store_true')
595 help='Verbose output', action='store_true') 608 parser.add_argument('-d', '--debug-mode',
596 parser.add_option('-d', '--debug-mode', 609 help='Debug mode', action='store_true')
597 help='Debug mode', action='store_true') 610 parser.add_argument('executables', nargs='+')
598 611
599 # To enable bash completion for this command first install optcomplete 612 # To enable bash completion for this command first install optcomplete
600 # and then add this line to your .bashrc: 613 # and then add this line to your .bashrc:
601 # complete -F _optcomplete create_nmf.py 614 # complete -F _optcomplete create_nmf.py
602 try: 615 try:
603 import optcomplete 616 import optcomplete
604 optcomplete.autocomplete(parser) 617 optcomplete.autocomplete(parser)
605 except ImportError: 618 except ImportError:
606 pass 619 pass
607 620
608 options, args = parser.parse_args(argv) 621 options = parser.parse_args(argv)
609 if options.verbose: 622 if options.verbose:
610 Trace.verbose = True 623 Trace.verbose = True
611 if options.debug_mode: 624 if options.debug_mode:
612 DebugPrint.debug_mode = True 625 DebugPrint.debug_mode = True
613 626
614 if options.toolchain is not None: 627 if options.toolchain is not None:
615 sys.stderr.write('warning: option -t/--toolchain is deprecated.\n') 628 sys.stderr.write('warning: option -t/--toolchain is deprecated.\n')
616 629
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) 630 canonicalized = ParseExtraFiles(options.extra_files, sys.stderr)
621 if canonicalized is None: 631 if canonicalized is None:
622 parser.error('Bad --extra-files (-x) argument syntax') 632 parser.error('Bad --extra-files (-x) argument syntax')
623 633
624 remap = {} 634 remap = {}
625 for ren in options.name: 635 for ren in options.name:
626 parts = ren.split(',') 636 parts = ren.split(',')
627 if len(parts) != 2: 637 if len(parts) != 2:
628 parser.error('Expecting --name=<orig_arch.so>,<new_name.so>') 638 parser.error('Expecting --name=<orig_arch.so>,<new_name.so>')
629 remap[parts[0]] = parts[1] 639 remap[parts[0]] = parts[1]
(...skipping 24 matching lines...) Expand all
654 if options.pnacl_debug_optlevel is not None: 664 if options.pnacl_debug_optlevel is not None:
655 pnacl_debug_optlevel = int(options.pnacl_debug_optlevel) 665 pnacl_debug_optlevel = int(options.pnacl_debug_optlevel)
656 else: 666 else:
657 pnacl_debug_optlevel = pnacl_optlevel 667 pnacl_debug_optlevel = pnacl_optlevel
658 668
659 nmf_root = None 669 nmf_root = None
660 if options.output: 670 if options.output:
661 nmf_root = os.path.dirname(options.output) 671 nmf_root = os.path.dirname(options.output)
662 672
663 nmf = NmfUtils(objdump=options.objdump, 673 nmf = NmfUtils(objdump=options.objdump,
664 main_files=args, 674 main_files=options.executables,
665 lib_path=options.lib_path, 675 lib_path=options.lib_path,
666 extra_files=canonicalized, 676 extra_files=canonicalized,
667 lib_prefix=options.lib_prefix, 677 lib_prefix=options.lib_prefix,
668 nexe_prefix=options.nexe_prefix, 678 nexe_prefix=options.nexe_prefix,
669 no_arch_prefix=options.no_arch_prefix, 679 no_arch_prefix=options.no_arch_prefix,
670 remap=remap, 680 remap=remap,
671 pnacl_optlevel=pnacl_optlevel, 681 pnacl_optlevel=pnacl_optlevel,
672 pnacl_debug_optlevel=pnacl_debug_optlevel, 682 pnacl_debug_optlevel=pnacl_debug_optlevel,
673 nmf_root=nmf_root) 683 nmf_root=nmf_root)
674 684
675 if not options.output: 685 if options.output is None:
676 sys.stdout.write(nmf.GetJson()) 686 sys.stdout.write(nmf.GetJson())
677 else: 687 else:
678 with open(options.output, 'w') as output: 688 with open(options.output, 'w') as output:
679 output.write(nmf.GetJson()) 689 output.write(nmf.GetJson())
680 690
681 if options.stage_dependencies and not nmf.pnacl: 691 if options.stage_dependencies and not nmf.pnacl:
682 Trace('Staging dependencies...') 692 Trace('Staging dependencies...')
683 nmf.StageDependencies(options.stage_dependencies) 693 nmf.StageDependencies(options.stage_dependencies)
684 694
685 return 0 695 return 0
686 696
687 697
688 if __name__ == '__main__': 698 if __name__ == '__main__':
689 try: 699 try:
690 rtn = main(sys.argv[1:]) 700 rtn = main(sys.argv[1:])
691 except Error, e: 701 except Error, e:
692 sys.stderr.write('%s: %s\n' % (os.path.basename(__file__), e)) 702 sys.stderr.write('%s: %s\n' % (os.path.basename(__file__), e))
693 rtn = 1 703 rtn = 1
694 except KeyboardInterrupt: 704 except KeyboardInterrupt:
695 sys.stderr.write('%s: interrupted\n' % os.path.basename(__file__)) 705 sys.stderr.write('%s: interrupted\n' % os.path.basename(__file__))
696 rtn = 1 706 rtn = 1
697 sys.exit(rtn) 707 sys.exit(rtn)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698