7 import Task
, Utils
, Logs
8 from TaskGen
import extension
9 from Configure
import conf
13 Welcome in the hell of adding tasks dynamically
15 swig interface files may be created at runtime, the module name may be unknown in advance
17 rev 5859 is much more simple
20 SWIG_EXTS
= ['.swig', '.i']
22 swig_str
= '${SWIG} ${SWIGFLAGS} ${_CCINCFLAGS} ${_CXXINCFLAGS} ${_CCDEFFLAGS} ${_CXXDEFFLAGS} ${SRC}'
23 cls
= Task
.simple_task_type('swig', swig_str
, color
='BLUE', ext_in
='.i .h', ext_out
='.o .c .cxx', shell
=False)
25 def runnable_status(self
):
26 for t
in self
.run_after
:
30 if not getattr(self
, 'init_outputs', None):
31 self
.init_outputs
= True
32 if not getattr(self
, 'module', None):
33 # search the module name
34 txt
= self
.inputs
[0].read(self
.env
)
35 m
= re_module
.search(txt
)
37 raise ValueError("could not find the swig module name")
38 self
.module
= m
.group(1)
42 # add the language-specific output files as nodes
43 # call funs in the dict swig_langs
44 for x
in self
.env
['SWIGFLAGS']:
54 return Task
.Task
.runnable_status(self
)
55 setattr(cls
, 'runnable_status', runnable_status
)
57 re_module
= re
.compile('%module(?:\s*\(.*\))?\s+(.+)', re
.M
)
59 re_1
= re
.compile(r
'^%module.*?\s+([\w]+)\s*?$', re
.M
)
60 re_2
= re
.compile('%include "(.*)"', re
.M
)
61 re_3
= re
.compile('#include "(.*)"', re
.M
)
64 "scan for swig dependencies, climb the .i files"
70 to_see
= [self
.inputs
[0]]
81 code
= preproc
.re_nl
.sub('', code
)
82 code
= preproc
.re_cpp
.sub(preproc
.repl
, code
)
84 # find .i files and project headers
85 names
= re_2
.findall(code
) + re_3
.findall(code
)
87 for d
in self
.generator
.env
.INC_PATHS
+ [node
.parent
]:
88 u
= d
.find_resource(n
)
93 Logs
.warn('could not find %r' % n
)
95 # list of nodes this one depends on, and module name if present
97 Logs
.debug('deps: deps for %s: %s' % (str(self
), str(lst_src
)))
101 # provide additional language processing
104 swig_langs
[fun
.__name
__.replace('swig_', '')] = fun
107 ext
= '.swigwrap_%d.c' % self
.generator
.idx
108 flags
= self
.env
['SWIGFLAGS']
111 out_node
= self
.inputs
[0].parent
.find_or_declare(self
.module
+ ext
)
115 fun
= self
.generator
.cxx_hook
117 fun
= self
.generator
.c_hook
118 except AttributeError:
119 raise Utils
.WafError('No c%s compiler was found to process swig files' % ('-c++' in flags
and '++' or ''))
122 task
.set_run_after(self
)
124 ge
= self
.generator
.bld
.generator
125 ge
.outstanding
.insert(0, task
)
129 ltask
= self
.generator
.link_task
130 except AttributeError:
133 ltask
.inputs
.append(task
.outputs
[0])
135 self
.outputs
.append(out_node
)
137 if not '-o' in self
.env
['SWIGFLAGS']:
138 self
.env
.append_value('SWIGFLAGS', '-o')
139 self
.env
.append_value('SWIGFLAGS', self
.outputs
[0].abspath(self
.env
))
142 def swig_python(tsk
):
143 tsk
.set_outputs(tsk
.inputs
[0].parent
.find_or_declare(tsk
.module
+ '.py'))
147 tsk
.set_outputs(tsk
.inputs
[0].parent
.find_or_declare(tsk
.module
+ '.ml'))
148 tsk
.set_outputs(tsk
.inputs
[0].parent
.find_or_declare(tsk
.module
+ '.mli'))
150 @extension(SWIG_EXTS
)
151 def i_file(self
, node
):
153 tsk
= self
.create_task('swig')
155 tsk
.module
= getattr(self
, 'swig_module', None)
157 flags
= self
.to_list(getattr(self
, 'swig_flags', []))
158 self
.env
.append_value('SWIGFLAGS', flags
)
160 if not '-outdir' in flags
:
161 flags
.append('-outdir')
162 flags
.append(node
.parent
.abspath(self
.env
))
165 def check_swig_version(conf
, minver
=None):
166 """Check for a minimum swig version like conf.check_swig_version('1.3.28')
167 or conf.check_swig_version((1,3,28)) """
168 reg_swig
= re
.compile(r
'SWIG Version\s(.*)', re
.M
)
170 swig_out
= Utils
.cmd_output('%s -version' % conf
.env
['SWIG'])
172 swigver
= [int(s
) for s
in reg_swig
.findall(swig_out
)[0].split('.')]
173 if isinstance(minver
, basestring
):
174 minver
= [int(s
) for s
in minver
.split(".")]
175 if isinstance(minver
, tuple):
176 minver
= [int(s
) for s
in minver
]
177 result
= (minver
is None) or (minver
[:3] <= swigver
[:3])
178 swigver_full
= '.'.join(map(str, swigver
))
180 conf
.env
['SWIG_VERSION'] = swigver_full
181 minver_str
= '.'.join(map(str, minver
))
183 conf
.check_message_custom('swig version', '', swigver_full
)
185 conf
.check_message('swig version', '>= %s' % (minver_str
,), result
, option
=swigver_full
)
189 swig
= conf
.find_program('swig', var
='SWIG', mandatory
=True)