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

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

Issue 11571032: [NaCl SDK] cleanup python unittests (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years 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 | Annotate | Revision Log
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 from __future__ import with_statement 6 from __future__ import with_statement
7 7
8 import errno 8 import errno
9 import optparse 9 import optparse
10 import os 10 import os
11 import re 11 import re
12 import shutil 12 import shutil
13 import struct 13 import struct
14 import subprocess 14 import subprocess
15 import sys 15 import sys
16 import urllib 16 import urllib
17 17
18 import quote
19
18 try: 20 try:
19 import json 21 import json
20 except ImportError: 22 except ImportError:
21 import simplejson as json 23 import simplejson as json
22 24
23 NeededMatcher = re.compile('^ *NEEDED *([^ ]+)\n$') 25 NeededMatcher = re.compile('^ *NEEDED *([^ ]+)\n$')
24 FormatMatcher = re.compile('^(.+):\\s*file format (.+)\n$') 26 FormatMatcher = re.compile('^(.+):\\s*file format (.+)\n$')
25 27
26 OBJDUMP_ARCH_MAP = { 28 OBJDUMP_ARCH_MAP = {
27 # Names returned by Linux's objdump: 29 # Names returned by Linux's objdump:
(...skipping 344 matching lines...) Expand 10 before | Expand all | Expand 10 after
372 Trace("copy: %s -> %s" % (source, destination)) 374 Trace("copy: %s -> %s" % (source, destination))
373 shutil.copy2(source, destination) 375 shutil.copy2(source, destination)
374 376
375 def _GenerateManifest(self): 377 def _GenerateManifest(self):
376 '''Create a JSON formatted dict containing the files 378 '''Create a JSON formatted dict containing the files
377 379
378 NaCl will map url requests based on architecture. The startup NEXE 380 NaCl will map url requests based on architecture. The startup NEXE
379 can always be found under the top key PROGRAM. Additional files are under 381 can always be found under the top key PROGRAM. Additional files are under
380 the FILES key further mapped by file name. In the case of 'runnable' the 382 the FILES key further mapped by file name. In the case of 'runnable' the
381 PROGRAM key is populated with urls pointing the runnable-ld.so which acts 383 PROGRAM key is populated with urls pointing the runnable-ld.so which acts
382 as the startup nexe. The application itself, is then placed under the 384 as the startup nexe. The application itself is then placed under the
383 FILES key mapped as 'main.exe' instead of it's original name so that the 385 FILES key mapped as 'main.exe' instead of the original name so that the
384 loader can find it.''' 386 loader can find it. '''
385 manifest = { FILES_KEY: {}, PROGRAM_KEY: {} } 387 manifest = { FILES_KEY: {}, PROGRAM_KEY: {} }
386 388
387 needed = self.GetNeeded() 389 needed = self.GetNeeded()
388 390
389 runnable = any(n.endswith(RUNNABLE_LD) for n in needed) 391 runnable = any(n.endswith(RUNNABLE_LD) for n in needed)
390 392
391 for need, archinfo in needed.items(): 393 extra_files_kv = [(key, ArchFile(name=key,
394 arch=arch,
395 path=url,
396 url=url))
397 for key, arch, url in self.extra_files]
398
399 for need, archinfo in needed.items() + extra_files_kv:
392 urlinfo = { URL_KEY: archinfo.url } 400 urlinfo = { URL_KEY: archinfo.url }
393 name = archinfo.name 401 name = archinfo.name
394 402
395 # If starting with runnable-ld.so, make that the main executable. 403 # If starting with runnable-ld.so, make that the main executable.
396 if runnable: 404 if runnable:
397 if need.endswith(RUNNABLE_LD): 405 if need.endswith(RUNNABLE_LD):
398 manifest[PROGRAM_KEY][archinfo.arch] = urlinfo 406 manifest[PROGRAM_KEY][archinfo.arch] = urlinfo
399 continue 407 continue
400 408
401 # For the main nexes: 409 # For the main nexes:
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
433 return '\n'.join([line.rstrip() for line in pretty_lines]) + '\n' 441 return '\n'.join([line.rstrip() for line in pretty_lines]) + '\n'
434 442
435 443
436 def Trace(msg): 444 def Trace(msg):
437 if Trace.verbose: 445 if Trace.verbose:
438 sys.stderr.write(str(msg) + '\n') 446 sys.stderr.write(str(msg) + '\n')
439 447
440 Trace.verbose = False 448 Trace.verbose = False
441 449
442 450
451 def ParseExtraFiles(encoded_list, err):
452 """Parse the extra-files list and return a canonicalized list of
453 [key, arch, url] triples. The |encoded_list| should be a list of
454 strings of the form 'key:url' or 'key:arch:url', where an omitted
455 'arch' is taken to mean 'portable'.
456
457 All entries in |encoded_list| are checked for syntax errors before
458 returning. Error messages are written to |err| (typically
459 sys.stderr) so that the user has actionable feedback for fixing all
460 errors, rather than one at a time. If there are any errors, None is
461 returned instead of a list, since an empty list is a valid return
462 value.
463 """
464 seen_error = False
465 canonicalized = []
466 for ix in range(len(encoded_list)):
467 kv = encoded_list[ix]
468 unquoted = quote.unquote(kv, ':')
469 if len(unquoted) == 3:
470 if unquoted[1] != ':':
471 err.write('Syntax error for key:value tuple ' +
472 'for --extra-files argument: ' + kv + '\n')
473 seen_error = True
474 else:
475 canonicalized.append([unquoted[0], 'portable', unquoted[2]])
476 elif len(unquoted) == 5:
477 if unquoted[1] != ':' or unquoted[3] != ':':
478 err.write('Syntax error for key:arch:url tuple ' +
479 'for --extra-files argument: ' +
480 kv + '\n')
481 seen_error = True
482 else:
483 canonicalized.append([unquoted[0], unquoted[2], unquoted[4]])
484 else:
485 err.write('Bad key:arch:url tuple for --extra-files: ' + kv + '\n')
486 if seen_error:
487 return None
488 return canonicalized
489
490
443 def main(argv): 491 def main(argv):
444 parser = optparse.OptionParser( 492 parser = optparse.OptionParser(
445 usage='Usage: %prog [options] nexe [extra_libs...]') 493 usage='Usage: %prog [options] nexe [extra_libs...]')
446 parser.add_option('-o', '--output', dest='output', 494 parser.add_option('-o', '--output', dest='output',
447 help='Write manifest file to FILE (default is stdout)', 495 help='Write manifest file to FILE (default is stdout)',
448 metavar='FILE') 496 metavar='FILE')
449 parser.add_option('-D', '--objdump', dest='objdump', 497 parser.add_option('-D', '--objdump', dest='objdump',
450 help='Use TOOL as the "objdump" tool to run', 498 help='Use TOOL as the "objdump" tool to run',
451 metavar='TOOL') 499 metavar='TOOL')
452 parser.add_option('-L', '--library-path', dest='lib_path', 500 parser.add_option('-L', '--library-path', dest='lib_path',
453 action='append', default=[], 501 action='append', default=[],
454 help='Add DIRECTORY to library search path', 502 help='Add DIRECTORY to library search path',
455 metavar='DIRECTORY') 503 metavar='DIRECTORY')
456 parser.add_option('-P', '--path-prefix', dest='path_prefix', default='', 504 parser.add_option('-P', '--path-prefix', dest='path_prefix', default='',
457 help='A path to prepend to shared libraries in the .nmf', 505 help='A path to prepend to shared libraries in the .nmf',
458 metavar='DIRECTORY') 506 metavar='DIRECTORY')
459 parser.add_option('-s', '--stage-dependencies', dest='stage_dependencies', 507 parser.add_option('-s', '--stage-dependencies', dest='stage_dependencies',
460 help='Destination directory for staging libraries', 508 help='Destination directory for staging libraries',
461 metavar='DIRECTORY') 509 metavar='DIRECTORY')
462 parser.add_option('-r', '--remove', dest='remove', 510 parser.add_option('-r', '--remove', dest='remove',
463 help='Remove the prefix from the files.', 511 help='Remove the prefix from the files.',
464 metavar='PATH') 512 metavar='PATH')
465 parser.add_option('-t', '--toolchain', help='Legacy option, do not use') 513 parser.add_option('-t', '--toolchain', help='Legacy option, do not use')
466 parser.add_option('-n', '--name', dest='name', 514 parser.add_option('-n', '--name', dest='name',
467 help='Rename FOO as BAR', 515 help='Rename FOO as BAR',
468 action='append', default=[], metavar='FOO,BAR') 516 action='append', default=[], metavar='FOO,BAR')
517 parser.add_option('-x', '--extra-files',
518 help=('Add extra key:file tuple to the "files"' +
519 ' section of the .nmf'),
520 action='append', default=[], metavar='FILE')
469 parser.add_option('-v', '--verbose', 521 parser.add_option('-v', '--verbose',
470 help='Verbose output', action='store_true') 522 help='Verbose output', action='store_true')
471 parser.add_option('-d', '--debug-mode', 523 parser.add_option('-d', '--debug-mode',
472 help='Debug mode', action='store_true') 524 help='Debug mode', action='store_true')
473 options, args = parser.parse_args(argv) 525 options, args = parser.parse_args(argv)
474 if options.verbose: 526 if options.verbose:
475 Trace.verbose = True 527 Trace.verbose = True
476 if options.debug_mode: 528 if options.debug_mode:
477 DebugPrint.debug_mode = True 529 DebugPrint.debug_mode = True
478 530
479 if options.toolchain is not None: 531 if options.toolchain is not None:
480 print "warning: option -t/--toolchain is deprecated." 532 print "warning: option -t/--toolchain is deprecated."
481 533
482 if len(args) < 1: 534 if len(args) < 1:
483 raise Error("No nexe files specified. See --help for more info") 535 raise Error("No nexe files specified. See --help for more info")
484 536
537 canonicalized = ParseExtraFiles(options.extra_files, sys.stderr)
538 if canonicalized is None:
539 parser.error("Bad --extra-files (-x) argument syntax")
540
485 remap = {} 541 remap = {}
486 for ren in options.name: 542 for ren in options.name:
487 parts = ren.split(',') 543 parts = ren.split(',')
488 if len(parts) != 2: 544 if len(parts) != 2:
489 raise Error('Expecting --name=<orig_arch.so>,<new_name.so>') 545 raise Error('Expecting --name=<orig_arch.so>,<new_name.so>')
490 remap[parts[0]] = parts[1] 546 remap[parts[0]] = parts[1]
491 547
492 if options.path_prefix: 548 if options.path_prefix:
493 path_prefix = options.path_prefix.split('/') 549 path_prefix = options.path_prefix.split('/')
494 else: 550 else:
495 path_prefix = [] 551 path_prefix = []
496 552
497 nmf = NmfUtils(objdump=options.objdump, 553 nmf = NmfUtils(objdump=options.objdump,
498 main_files=args, 554 main_files=args,
499 lib_path=options.lib_path, 555 lib_path=options.lib_path,
556 extra_files=canonicalized,
500 lib_prefix=path_prefix, 557 lib_prefix=path_prefix,
501 remap=remap) 558 remap=remap)
502 559
503 nmf.GetManifest() 560 nmf.GetManifest()
504 if options.output is None: 561 if options.output is None:
505 sys.stdout.write(nmf.GetJson()) 562 sys.stdout.write(nmf.GetJson())
506 else: 563 else:
507 with open(options.output, 'w') as output: 564 with open(options.output, 'w') as output:
508 output.write(nmf.GetJson()) 565 output.write(nmf.GetJson())
509 566
510 if options.stage_dependencies: 567 if options.stage_dependencies:
511 Trace("Staging dependencies...") 568 Trace("Staging dependencies...")
512 nmf.StageDependencies(options.stage_dependencies) 569 nmf.StageDependencies(options.stage_dependencies)
513 570
514 return 0 571 return 0
515 572
516 573
517 # Invoke this file directly for simple testing. 574 # Invoke this file directly for simple testing.
518 if __name__ == '__main__': 575 if __name__ == '__main__':
519 try: 576 try:
520 rtn = main(sys.argv[1:]) 577 rtn = main(sys.argv[1:])
521 except Error, e: 578 except Error, e:
522 sys.stderr.write("%s: %s\n" % (os.path.basename(__file__), e)) 579 sys.stderr.write("%s: %s\n" % (os.path.basename(__file__), e))
523 rtn = 1 580 rtn = 1
524 sys.exit(rtn) 581 sys.exit(rtn)
OLDNEW
« no previous file with comments | « native_client_sdk/src/build_tools/tests/update_nacl_manifest_test.py ('k') | native_client_sdk/src/tools/quote.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698