7
import Action, Scan, Params
8
from Params import fatal, set_globals
10
swig_str = '${SWIG} ${SWIGFLAGS} -o ${TGT[0].bldpath(env)} ${SRC}'
12
set_globals('EXT_SWIG_C','.swigwrap.c')
13
set_globals('EXT_SWIG_CC','.swigwrap.cc')
14
set_globals('EXT_SWIG_OUT','.swigwrap.os')
16
re_1 = re.compile(r'^%module.*?\s+([\w]+)\s*?$', re.M)
17
re_2 = re.compile('%include "(.*)"', re.M)
18
re_3 = re.compile('#include "(.*)"', re.M)
20
class swig_class_scanner(Scan.scanner):
22
Scan.scanner.__init__(self)
23
def scan(self, node, env):
24
variant = node.variant(env)
31
fi = open(node.abspath(env), 'r')
35
# module name, only for the .swig file
36
names = re_1.findall(content)
37
if names: lst_names.append(names[0])
39
# find .i files (and perhaps .h files)
40
names = re_2.findall(content)
42
u = node.m_parent.find_source(n)
43
if u: lst_src.append(u)
45
# find project headers
46
names = re_3.findall(content)
48
u = node.m_parent.find_source(n)
49
if u: lst_src.append(u)
51
# list of nodes this one depends on, and module name if present
52
#print "result of ", node, lst_src, lst_names
53
return (lst_src, lst_names)
55
swig_scanner = swig_class_scanner()
57
def i_file(self, node):
58
if self.__class__.__name__ == 'ccobj':
59
ext = self.env['EXT_SWIG_C']
60
elif self.__class__.__name__ == 'cppobj':
61
ext = self.env['EXT_SWIG_CC']
63
ext = self.env['EXT_SWIG_C']
64
# the extension does not matter so much, does it ? (ita)
66
variant = node.variant(self.env)
68
# check if rescanning is needed
69
# the swig include system makes a small tree
70
def check_rec(nn, env, variant, tree):
71
if tree.needs_rescan(nn, env):
72
swig_scanner.do_scan(nn, env, hashparams={})
73
nodes = tree.m_depends_on[variant][nn]
75
if kk.m_name[-2:] != '.i': return # avoid others than .i files
76
check_rec(kk, env, variant, tree)
77
check_rec(node, self.env, variant, Params.g_build)
79
# get the name of the swig module to process
80
try: modname = Params.g_build.m_raw_deps[variant][node][0]
83
# set the output files
84
outs = [node.change_ext(ext)]
85
# swig generates a python file in python mode TODO: other modes ?
86
if '-python' in self.env['SWIGFLAGS']:
87
outs.append(node.m_parent.find_build(modname+'.py'))
88
elif '-ocaml' in self.env['SWIGFLAGS']:
89
outs.append(node.m_parent.find_build(modname+'.ml'))
90
outs.append(node.m_parent.find_build(modname+'.mli'))
92
# create the swig task
93
ltask = self.create_task('swig', nice=40)
94
ltask.set_inputs(node)
95
ltask.set_outputs(outs)
97
# create the build task (c or cpp)
98
task = self.create_task(self.m_type_initials)
99
task.set_inputs(ltask.m_outputs[0])
100
task.set_outputs(node.change_ext(self.env['EXT_SWIG_OUT']))
103
Action.simple_action('swig', swig_str, color='BLUE')
105
# register the hook for use with cppobj and ccobj
106
try: env.hook('cpp', 'SWIG_EXT', i_file)
108
try: env.hook('cc', 'SWIG_EXT', i_file)
111
def check_swig_version(conf, minver=None):
112
"""Check for a minimum swig version like conf.check_swig_version("1.3.28")
113
or conf.check_swig_version((1,3,28)) """
114
from pproc import Popen, PIPE
115
reg_swig = re.compile(r'SWIG Version\s(.*)', re.M)
116
proc = Popen([conf.env['SWIG'], "-version"], stdout=PIPE)
117
swig_out = proc.communicate()[0]
118
swigver = [int(s) for s in reg_swig.findall(swig_out)[0].split(".")]
119
if isinstance(minver, basestring):
120
minver = [int(s) for s in minver.split(".")]
121
if isinstance(minver, tuple):
122
minver = [int(s) for s in minver]
123
result = (minver is None) or (minver[:3] <= swigver[:3])
124
swigver_full = '.'.join(map(str, swigver))
126
conf.env['SWIG_VERSION'] = swigver_full
127
minver_str = '.'.join(map(str, minver))
129
conf.check_message_custom('swig version', '', swigver_full)
131
conf.check_message('swig version', ">= %s" % (minver_str,), result, option=swigver_full)
135
swig = conf.find_program('swig', var='SWIG')
136
if not swig: return 0
139
env['SWIGFLAGS'] = ''
140
env['SWIG_EXT'] = ['.swig']
141
conf.hook(check_swig_version)