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.

171 lines
4.2KB

  1. #! /usr/bin/env python
  2. # encoding: UTF-8
  3. # Petar Forai
  4. # Thomas Nagy 2008-2010 (ita)
  5. import re
  6. from waflib import Task, Logs
  7. from waflib.TaskGen import extension
  8. from waflib.Configure import conf
  9. from waflib.Tools import c_preproc
  10. """
  11. tasks have to be added dynamically:
  12. - swig interface files may be created at runtime
  13. - the module name may be unknown in advance
  14. """
  15. SWIG_EXTS = ['.swig', '.i']
  16. re_module = re.compile('%module(?:\s*\(.*\))?\s+(.+)', re.M)
  17. re_1 = re.compile(r'^%module.*?\s+([\w]+)\s*?$', re.M)
  18. re_2 = re.compile('[#%]include [<"](.*)[">]', re.M)
  19. class swig(Task.Task):
  20. color = 'BLUE'
  21. run_str = '${SWIG} ${SWIGFLAGS} ${SWIGPATH_ST:INCPATHS} ${SWIGDEF_ST:DEFINES} ${SRC}'
  22. ext_out = ['.h'] # might produce .h files although it is not mandatory
  23. vars = ['SWIG_VERSION', 'SWIGDEPS']
  24. def runnable_status(self):
  25. for t in self.run_after:
  26. if not t.hasrun:
  27. return Task.ASK_LATER
  28. if not getattr(self, 'init_outputs', None):
  29. self.init_outputs = True
  30. if not getattr(self, 'module', None):
  31. # search the module name
  32. txt = self.inputs[0].read()
  33. m = re_module.search(txt)
  34. if not m:
  35. raise ValueError("could not find the swig module name")
  36. self.module = m.group(1)
  37. swig_c(self)
  38. # add the language-specific output files as nodes
  39. # call funs in the dict swig_langs
  40. for x in self.env['SWIGFLAGS']:
  41. # obtain the language
  42. x = x[1:]
  43. try:
  44. fun = swig_langs[x]
  45. except KeyError:
  46. pass
  47. else:
  48. fun(self)
  49. return super(swig, self).runnable_status()
  50. def scan(self):
  51. "scan for swig dependencies, climb the .i files"
  52. lst_src = []
  53. seen = []
  54. to_see = [self.inputs[0]]
  55. while to_see:
  56. node = to_see.pop(0)
  57. if node in seen:
  58. continue
  59. seen.append(node)
  60. lst_src.append(node)
  61. # read the file
  62. code = node.read()
  63. code = c_preproc.re_nl.sub('', code)
  64. code = c_preproc.re_cpp.sub(c_preproc.repl, code)
  65. # find .i files and project headers
  66. names = re_2.findall(code)
  67. for n in names:
  68. for d in self.generator.includes_nodes + [node.parent]:
  69. u = d.find_resource(n)
  70. if u:
  71. to_see.append(u)
  72. break
  73. else:
  74. Logs.warn('could not find %r' % n)
  75. return (lst_src, [])
  76. # provide additional language processing
  77. swig_langs = {}
  78. def swigf(fun):
  79. swig_langs[fun.__name__.replace('swig_', '')] = fun
  80. swig.swigf = swigf
  81. def swig_c(self):
  82. ext = '.swigwrap_%d.c' % self.generator.idx
  83. flags = self.env['SWIGFLAGS']
  84. if '-c++' in flags:
  85. ext += 'xx'
  86. out_node = self.inputs[0].parent.find_or_declare(self.module + ext)
  87. if '-c++' in flags:
  88. c_tsk = self.generator.cxx_hook(out_node)
  89. else:
  90. c_tsk = self.generator.c_hook(out_node)
  91. c_tsk.set_run_after(self)
  92. ge = self.generator.bld.producer
  93. ge.outstanding.insert(0, c_tsk)
  94. ge.total += 1
  95. try:
  96. ltask = self.generator.link_task
  97. except AttributeError:
  98. pass
  99. else:
  100. ltask.set_run_after(c_tsk)
  101. ltask.inputs.append(c_tsk.outputs[0])
  102. self.outputs.append(out_node)
  103. if not '-o' in self.env['SWIGFLAGS']:
  104. self.env.append_value('SWIGFLAGS', ['-o', self.outputs[0].abspath()])
  105. @swigf
  106. def swig_python(tsk):
  107. tsk.set_outputs(tsk.inputs[0].parent.find_or_declare(tsk.module + '.py'))
  108. @swigf
  109. def swig_ocaml(tsk):
  110. tsk.set_outputs(tsk.inputs[0].parent.find_or_declare(tsk.module + '.ml'))
  111. tsk.set_outputs(tsk.inputs[0].parent.find_or_declare(tsk.module + '.mli'))
  112. @extension(*SWIG_EXTS)
  113. def i_file(self, node):
  114. # the task instance
  115. tsk = self.create_task('swig')
  116. tsk.set_inputs(node)
  117. tsk.module = getattr(self, 'swig_module', None)
  118. flags = self.to_list(getattr(self, 'swig_flags', []))
  119. tsk.env.append_value('SWIGFLAGS', flags)
  120. # looks like this is causing problems
  121. #if not '-outdir' in flags:
  122. # tsk.env.append_value('SWIGFLAGS', ['-outdir', node.parent.abspath()])
  123. @conf
  124. def check_swig_version(self):
  125. """Returns a tuple representing the swig version, like (1,3,28)"""
  126. reg_swig = re.compile(r'SWIG Version\s(.*)', re.M)
  127. swig_out = self.cmd_and_log(self.env.SWIG + ['-version'])
  128. swigver = tuple([int(s) for s in reg_swig.findall(swig_out)[0].split('.')])
  129. self.env['SWIG_VERSION'] = swigver
  130. msg = 'Checking for swig version'
  131. self.msg(msg, '.'.join(map(str, swigver)))
  132. return swigver
  133. def configure(conf):
  134. conf.find_program('swig', var='SWIG')
  135. conf.env.SWIGPATH_ST = '-I%s'
  136. conf.env.SWIGDEF_ST = '-D%s'