swig.py
import re
import os
import _import_wrapper as iw
import _common as common
_SWIG_LIB_PATH = 'contrib/libs/swig/swig-2.0.9/Lib'
_PREDEFINED_INCLUDES = [
os.path.join(_SWIG_LIB_PATH, 'python', 'python.swg'),
os.path.join(_SWIG_LIB_PATH, 'swig.swg'),
]
class Swig(iw.CustomCommand):
def __init__(self, path, unit):
self._path = path
self._flags = ['-cpperraswarn']
self._bindir = common.tobuilddir(unit.path())
self._input_name = common.stripext(os.path.basename(self._path))
relpath = os.path.relpath(os.path.dirname(self._path), unit.path())
self._main_out = os.path.join(self._bindir, '' if relpath == '.' else relpath.replace('..', '__'), self._input_name + '_wrap.c')
if not path.endswith('.c.swg'):
self._flags += ['-c++']
self._main_out += 'pp'
self._swig_lang = unit.get('SWIG_LANG')
lang_specific_incl_dir = 'perl5' if self._swig_lang == 'perl' else self._swig_lang
incl_dirs = ['bindings/swiglib', os.path.join(_SWIG_LIB_PATH, lang_specific_incl_dir), _SWIG_LIB_PATH, os.path.join(_SWIG_LIB_PATH, 'python')]
self._incl_dirs = ['$S', '$B'] + ['$S/{}'.format(d) for d in incl_dirs]
modname = unit.get('REALPRJNAME')
self._flags.extend(['-module', modname])
unit.onaddincl(incl_dirs)
unit.onpython_addincl([])
if self._swig_lang == 'python':
self._out_name = modname + '.py'
self._flags.extend(['-interface', unit.get('MODULE_PREFIX') + modname])
if self._swig_lang == 'perl':
self._out_name = modname + '.pm'
self._flags.append('-shadow')
unit.onpeerdir(['contrib/libs/platform/perl'])
if self._swig_lang == 'java':
self._out_name = os.path.splitext(os.path.basename(self._path))[0] + '.jsrc'
self._package = 'ru.yandex.' + os.path.dirname(self._path).replace('$S/', '').replace('$B/', '').replace('/', '.').replace('-', '_')
unit.onpeerdir(['contrib/libs/jdk'])
self._flags.append('-' + self._swig_lang)
def descr(self):
return 'SW', self._path, 'yellow'
def flags(self):
return self._flags
def tools(self):
return ['contrib/tools/swig']
def input(self):
return [
(self._path, [])
]
def output(self):
return [
(self._main_out, []),
(common.join_intl_paths(self._bindir, self._out_name), (['noauto', 'add_to_outs'] if self._swig_lang != 'java' else [])),
]
def run(self, binary):
return self.do_run(binary, self._path) if self._swig_lang != 'java' else self.do_run_java(binary, self._path)
def do_run(self, binary, path):
self._incl_dirs = ['-I' + self.resolve_path(x) for x in self._incl_dirs]
self.call([binary] + self._flags + ['-o', self.resolve_path(common.get(self.output, 0)), '-outdir', self.resolve_path(self._bindir)]
+ self._incl_dirs + [self.resolve_path(path)])
def do_run_java(self, binary, path):
cmd = common.get_interpreter_path() + ['$S/build/scripts/run_swig_java.py', '--tool', binary, '--src', self.resolve_path(path)]
for inc in self._incl_dirs:
if inc:
cmd += ['--flag', 'I' + self.resolve_path(inc)]
cmd += ['--cpp-out', self._main_out, '--jsrc-out', '/'.join([self.resolve_path(self._bindir), self._out_name]), '--package', self._package]
self.call(cmd)
class SwigParser(object):
def __init__(self, path, unit):
self._path = path
retargeted = os.path.join(unit.path(), os.path.basename(path))
with open(path, 'rb') as f:
includes, induced = SwigParser.parse_includes(f.readlines())
self._includes = unit.resolve_include([retargeted] + _PREDEFINED_INCLUDES + includes)
self._induced = unit.resolve_include([retargeted] + induced) if induced else []
@staticmethod
def parse_includes(content):
includes = []
induced = []
in_block = False
include_pattern = re.compile('\%(include|import|insert *\([^\)]*\)) *("|<)([^">]*)')
induced_pattern = re.compile('include *("|<)([^">]*)')
for line in content:
line = line.lstrip()
if not in_block and line.startswith('%include') or line.startswith('%import') or line.startswith('%insert'):
m = include_pattern.match(line)
if m and m.group(3):
includes.append(m.group(3))
elif line.startswith('%{'):
in_block = True
elif line.startswith('%begin') or line.startswith('%header'):
if line.find('%{'):
in_block = True
elif line.startswith('%}'):
in_block = False
elif in_block and line.startswith('#'):
m = induced_pattern.search(line)
if m and m.group(2):
induced.append(m.group(2))
return (includes, induced)
def includes(self):
return self._includes
def induced_deps(self):
return {
'h+cpp': self._induced
}
def init():
iw.addrule('swg', Swig)
iw.addparser('swg', SwigParser)