jack2 codebase
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

88 lines
3.2KB

  1. #! /usr/bin/env python
  2. # encoding: utf-8
  3. """
  4. this tool supports the export_symbols_regex to export the symbols in a shared library.
  5. by default, all symbols are exported by gcc, and nothing by msvc.
  6. to use the tool, do something like:
  7. def build(ctx):
  8. ctx(features='c cshlib syms', source='a.c b.c', export_symbols_regex='mylib_.*', target='testlib')
  9. only the symbols starting with 'mylib_' will be exported.
  10. """
  11. import os
  12. import re
  13. from waflib.Context import STDOUT
  14. from waflib.Task import Task
  15. from waflib.Errors import WafError
  16. from waflib.TaskGen import feature, after_method
  17. class gen_sym(Task):
  18. def run(self):
  19. obj = self.inputs[0]
  20. kw = {}
  21. if 'msvc' in (self.env.CC_NAME, self.env.CXX_NAME):
  22. re_nm = re.compile(r'External\s+\|\s+_(' + self.generator.export_symbols_regex + r')\b')
  23. cmd = (self.env.DUMPBIN or ['dumpbin']) + ['/symbols', obj.abspath()]
  24. # Dumpbin requires custom environment sniffed out by msvc.py earlier
  25. if self.env['PATH']:
  26. env = dict(self.env.env or os.environ)
  27. env.update(PATH = os.pathsep.join(self.env['PATH']))
  28. kw['env'] = env
  29. else:
  30. if self.env.DEST_BINFMT == 'pe': #gcc uses nm, and has a preceding _ on windows
  31. re_nm = re.compile(r'T\s+_(' + self.generator.export_symbols_regex + r')\b')
  32. elif self.env.DEST_BINFMT=='mac-o':
  33. re_nm=re.compile(r'T\s+(_?'+self.generator.export_symbols_regex+r')\b')
  34. else:
  35. re_nm = re.compile(r'T\s+(' + self.generator.export_symbols_regex + r')\b')
  36. cmd = [self.env.NM[0] or 'nm', '-g', obj.abspath()]
  37. syms = re_nm.findall(self.generator.bld.cmd_and_log(cmd, quiet=STDOUT, **kw))
  38. self.outputs[0].write('%r' % syms)
  39. class compile_sym(Task):
  40. def run(self):
  41. syms = {}
  42. for x in self.inputs:
  43. slist = eval(x.read())
  44. for s in slist:
  45. syms[s] = 1
  46. lsyms = list(syms.keys())
  47. lsyms.sort()
  48. if self.env.DEST_BINFMT == 'pe':
  49. self.outputs[0].write('EXPORTS\n' + '\n'.join(lsyms))
  50. elif self.env.DEST_BINFMT == 'elf':
  51. self.outputs[0].write('{ global:\n' + ';\n'.join(lsyms) + ";\nlocal: *; };\n")
  52. elif self.env.DEST_BINFMT=='mac-o':
  53. self.outputs[0].write('\n'.join(lsyms) + '\n')
  54. else:
  55. raise WafError('NotImplemented')
  56. @feature('syms')
  57. @after_method('process_source', 'process_use', 'apply_link', 'process_uselib_local')
  58. def do_the_symbol_stuff(self):
  59. ins = [x.outputs[0] for x in self.compiled_tasks]
  60. self.gen_sym_tasks = [self.create_task('gen_sym', x, x.change_ext('.%d.sym' % self.idx)) for x in ins]
  61. tsk = self.create_task('compile_sym',
  62. [x.outputs[0] for x in self.gen_sym_tasks],
  63. self.path.find_or_declare(getattr(self, 'sym_filename', self.target + '.def')))
  64. self.link_task.set_run_after(tsk)
  65. self.link_task.dep_nodes.append(tsk.outputs[0])
  66. if 'msvc' in (self.env.CC_NAME, self.env.CXX_NAME):
  67. self.link_task.env.append_value('LINKFLAGS', ['/def:' + tsk.outputs[0].bldpath()])
  68. elif self.env.DEST_BINFMT == 'pe': #gcc on windows takes *.def as an additional input
  69. self.link_task.inputs.append(tsk.outputs[0])
  70. elif self.env.DEST_BINFMT == 'elf':
  71. self.link_task.env.append_value('LINKFLAGS', ['-Wl,-version-script', '-Wl,' + tsk.outputs[0].bldpath()])
  72. elif self.env.DEST_BINFMT=='mac-o':
  73. self.link_task.env.append_value('LINKFLAGS',['-Wl,-exported_symbols_list,'+tsk.outputs[0].bldpath()])
  74. else:
  75. raise WafError('NotImplemented')