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 import errno | 6 import errno |
7 import json | 7 import json |
8 import optparse | 8 import optparse |
9 import os | 9 import os |
10 import re | 10 import re |
(...skipping 29 matching lines...) Expand all Loading... |
40 'arm': 'lib', | 40 'arm': 'lib', |
41 } | 41 } |
42 | 42 |
43 | 43 |
44 # These constants are used within nmf files. | 44 # These constants are used within nmf files. |
45 RUNNABLE_LD = 'runnable-ld.so' # Name of the dynamic loader | 45 RUNNABLE_LD = 'runnable-ld.so' # Name of the dynamic loader |
46 MAIN_NEXE = 'main.nexe' # Name of entry point for execution | 46 MAIN_NEXE = 'main.nexe' # Name of entry point for execution |
47 PROGRAM_KEY = 'program' # Key of the program section in an nmf file | 47 PROGRAM_KEY = 'program' # Key of the program section in an nmf file |
48 URL_KEY = 'url' # Key of the url field for a particular file in an nmf file | 48 URL_KEY = 'url' # Key of the url field for a particular file in an nmf file |
49 FILES_KEY = 'files' # Key of the files section in an nmf file | 49 FILES_KEY = 'files' # Key of the files section in an nmf file |
| 50 PORTABLE_KEY = 'portable' # key for portable section of manifest |
| 51 TRANSLATE_KEY = 'pnacl-translate' # key for translatable objects |
| 52 |
50 | 53 |
51 # The proper name of the dynamic linker, as kept in the IRT. This is | 54 # The proper name of the dynamic linker, as kept in the IRT. This is |
52 # excluded from the nmf file by convention. | 55 # excluded from the nmf file by convention. |
53 LD_NACL_MAP = { | 56 LD_NACL_MAP = { |
54 'x86-32': 'ld-nacl-x86-32.so.1', | 57 'x86-32': 'ld-nacl-x86-32.so.1', |
55 'x86-64': 'ld-nacl-x86-64.so.1', | 58 'x86-64': 'ld-nacl-x86-64.so.1', |
56 'arm': None, | 59 'arm': None, |
57 } | 60 } |
58 | 61 |
59 | 62 |
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
221 remap: Remaps the library name in the manifest. | 224 remap: Remaps the library name in the manifest. |
222 ''' | 225 ''' |
223 self.objdump = objdump | 226 self.objdump = objdump |
224 self.main_files = main_files or [] | 227 self.main_files = main_files or [] |
225 self.extra_files = extra_files or [] | 228 self.extra_files = extra_files or [] |
226 self.lib_path = lib_path or [] | 229 self.lib_path = lib_path or [] |
227 self.manifest = None | 230 self.manifest = None |
228 self.needed = {} | 231 self.needed = {} |
229 self.lib_prefix = lib_prefix or [] | 232 self.lib_prefix = lib_prefix or [] |
230 self.remap = remap or {} | 233 self.remap = remap or {} |
| 234 self.pnacl = len(main_files) > 0 and main_files[0].endswith('pexe') |
231 | 235 |
232 def GleanFromObjdump(self, files): | 236 def GleanFromObjdump(self, files): |
233 '''Get architecture and dependency information for given files | 237 '''Get architecture and dependency information for given files |
234 | 238 |
235 Args: | 239 Args: |
236 files: A dict with key=filename and value=list or set of archs. E.g.: | 240 files: A dict with key=filename and value=list or set of archs. E.g.: |
237 { '/path/to/my.nexe': ['x86-32'] | 241 { '/path/to/my.nexe': ['x86-32'] |
238 '/path/to/lib64/libmy.so': ['x86-64'], | 242 '/path/to/lib64/libmy.so': ['x86-64'], |
239 '/path/to/mydata.so': ['x86-32', 'x86-64'], | 243 '/path/to/mydata.so': ['x86-32', 'x86-64'], |
240 '/path/to/my.data': None } # Indicates all architectures | 244 '/path/to/my.data': None } # Indicates all architectures |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
298 return files | 302 return files |
299 | 303 |
300 def GetNeeded(self): | 304 def GetNeeded(self): |
301 '''Collect the list of dependencies for the main_files | 305 '''Collect the list of dependencies for the main_files |
302 | 306 |
303 Returns: | 307 Returns: |
304 A dict with key=filename and value=ArchFile of input files. | 308 A dict with key=filename and value=ArchFile of input files. |
305 Includes the input files as well, with arch filled in if absent. | 309 Includes the input files as well, with arch filled in if absent. |
306 Example: { '/path/to/my.nexe': ArchFile(my.nexe), | 310 Example: { '/path/to/my.nexe': ArchFile(my.nexe), |
307 '/path/to/libfoo.so': ArchFile(libfoo.so) }''' | 311 '/path/to/libfoo.so': ArchFile(libfoo.so) }''' |
| 312 |
308 if self.needed: | 313 if self.needed: |
309 return self.needed | 314 return self.needed |
310 | 315 |
311 DebugPrint('GetNeeded(%s)' % self.main_files) | 316 DebugPrint('GetNeeded(%s)' % self.main_files) |
312 | 317 |
313 dynamic = any(ParseElfHeader(f)[1] for f in self.main_files) | 318 dynamic = any(ParseElfHeader(f)[1] for f in self.main_files) |
314 | 319 |
315 if dynamic: | 320 if dynamic: |
316 examined = set() | 321 examined = set() |
317 all_files, unexamined = self.GleanFromObjdump( | 322 all_files, unexamined = self.GleanFromObjdump( |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
365 destination = os.path.join(destination_dir, urldest) | 370 destination = os.path.join(destination_dir, urldest) |
366 | 371 |
367 if (os.path.normcase(os.path.abspath(source)) != | 372 if (os.path.normcase(os.path.abspath(source)) != |
368 os.path.normcase(os.path.abspath(destination))): | 373 os.path.normcase(os.path.abspath(destination))): |
369 # make sure target dir exists | 374 # make sure target dir exists |
370 MakeDir(os.path.dirname(destination)) | 375 MakeDir(os.path.dirname(destination)) |
371 | 376 |
372 Trace("copy: %s -> %s" % (source, destination)) | 377 Trace("copy: %s -> %s" % (source, destination)) |
373 shutil.copy2(source, destination) | 378 shutil.copy2(source, destination) |
374 | 379 |
| 380 def _GeneratePNaClManifest(self): |
| 381 manifest = {} |
| 382 manifest[PROGRAM_KEY] = {} |
| 383 manifest[PROGRAM_KEY][PORTABLE_KEY] = {} |
| 384 manifest[PROGRAM_KEY][PORTABLE_KEY][TRANSLATE_KEY] = { |
| 385 "url": os.path.basename(self.main_files[0]) |
| 386 } |
| 387 self.manifest = manifest |
| 388 |
375 def _GenerateManifest(self): | 389 def _GenerateManifest(self): |
376 '''Create a JSON formatted dict containing the files | 390 '''Create a JSON formatted dict containing the files |
377 | 391 |
378 NaCl will map url requests based on architecture. The startup NEXE | 392 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 | 393 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 | 394 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 | 395 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 | 396 as the startup nexe. The application itself is then placed under the |
383 FILES key mapped as 'main.exe' instead of the original name so that the | 397 FILES key mapped as 'main.exe' instead of the original name so that the |
384 loader can find it. ''' | 398 loader can find it. ''' |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
419 | 433 |
420 name = self.remap.get(name, name) | 434 name = self.remap.get(name, name) |
421 fileinfo = manifest[FILES_KEY].get(name, {}) | 435 fileinfo = manifest[FILES_KEY].get(name, {}) |
422 fileinfo[archinfo.arch] = urlinfo | 436 fileinfo[archinfo.arch] = urlinfo |
423 manifest[FILES_KEY][name] = fileinfo | 437 manifest[FILES_KEY][name] = fileinfo |
424 self.manifest = manifest | 438 self.manifest = manifest |
425 | 439 |
426 def GetManifest(self): | 440 def GetManifest(self): |
427 '''Returns a JSON-formatted dict containing the NaCl dependencies''' | 441 '''Returns a JSON-formatted dict containing the NaCl dependencies''' |
428 if not self.manifest: | 442 if not self.manifest: |
429 self._GenerateManifest() | 443 if self.pnacl: |
430 | 444 self._GeneratePNaClManifest() |
| 445 else: |
| 446 self._GenerateManifest() |
431 return self.manifest | 447 return self.manifest |
432 | 448 |
433 def GetJson(self): | 449 def GetJson(self): |
434 '''Returns the Manifest as a JSON-formatted string''' | 450 '''Returns the Manifest as a JSON-formatted string''' |
435 pretty_string = json.dumps(self.GetManifest(), indent=2) | 451 pretty_string = json.dumps(self.GetManifest(), indent=2) |
436 # json.dumps sometimes returns trailing whitespace and does not put | 452 # json.dumps sometimes returns trailing whitespace and does not put |
437 # a newline at the end. This code fixes these problems. | 453 # a newline at the end. This code fixes these problems. |
438 pretty_lines = pretty_string.split('\n') | 454 pretty_lines = pretty_string.split('\n') |
439 return '\n'.join([line.rstrip() for line in pretty_lines]) + '\n' | 455 return '\n'.join([line.rstrip() for line in pretty_lines]) + '\n' |
440 | 456 |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
555 lib_prefix=path_prefix, | 571 lib_prefix=path_prefix, |
556 remap=remap) | 572 remap=remap) |
557 | 573 |
558 nmf.GetManifest() | 574 nmf.GetManifest() |
559 if options.output is None: | 575 if options.output is None: |
560 sys.stdout.write(nmf.GetJson()) | 576 sys.stdout.write(nmf.GetJson()) |
561 else: | 577 else: |
562 with open(options.output, 'w') as output: | 578 with open(options.output, 'w') as output: |
563 output.write(nmf.GetJson()) | 579 output.write(nmf.GetJson()) |
564 | 580 |
565 if options.stage_dependencies: | 581 if options.stage_dependencies and not nmf.pnacl: |
566 Trace("Staging dependencies...") | 582 Trace("Staging dependencies...") |
567 nmf.StageDependencies(options.stage_dependencies) | 583 nmf.StageDependencies(options.stage_dependencies) |
568 | 584 |
569 return 0 | 585 return 0 |
570 | 586 |
571 | 587 |
572 # Invoke this file directly for simple testing. | 588 # Invoke this file directly for simple testing. |
573 if __name__ == '__main__': | 589 if __name__ == '__main__': |
574 try: | 590 try: |
575 rtn = main(sys.argv[1:]) | 591 rtn = main(sys.argv[1:]) |
576 except Error, e: | 592 except Error, e: |
577 sys.stderr.write("%s: %s\n" % (os.path.basename(__file__), e)) | 593 sys.stderr.write("%s: %s\n" % (os.path.basename(__file__), e)) |
578 rtn = 1 | 594 rtn = 1 |
579 sys.exit(rtn) | 595 sys.exit(rtn) |
OLD | NEW |