Reply with correct trans2 message on a setpathinfo with a bad EA name.
[Samba.git] / buildtools / wafadmin / 3rdparty / swig.py
blobc0a4108700e72b6e082f166d7dbdf4442b3576db
1 #! /usr/bin/env python
2 # encoding: UTF-8
3 # Petar Forai
4 # Thomas Nagy 2008
6 import re
7 import Task, Utils, Logs
8 from TaskGen import extension
9 from Configure import conf
10 import preproc
12 """
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
18 """
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:
27 if not t.hasrun:
28 return ASK_LATER
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)
36 if not m:
37 raise ValueError("could not find the swig module name")
38 self.module = m.group(1)
40 swig_c(self)
42 # add the language-specific output files as nodes
43 # call funs in the dict swig_langs
44 for x in self.env['SWIGFLAGS']:
45 # obtain the language
46 x = x[1:]
47 try:
48 fun = swig_langs[x]
49 except KeyError:
50 pass
51 else:
52 fun(self)
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)
63 def scan(self):
64 "scan for swig dependencies, climb the .i files"
65 env = self.env
67 lst_src = []
69 seen = []
70 to_see = [self.inputs[0]]
72 while to_see:
73 node = to_see.pop(0)
74 if node.id in seen:
75 continue
76 seen.append(node.id)
77 lst_src.append(node)
79 # read the file
80 code = node.read(env)
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)
86 for n in names:
87 for d in self.generator.env.INC_PATHS + [node.parent]:
88 u = d.find_resource(n)
89 if u:
90 to_see.append(u)
91 break
92 else:
93 Logs.warn('could not find %r' % n)
95 # list of nodes this one depends on, and module name if present
96 if Logs.verbose:
97 Logs.debug('deps: deps for %s: %s' % (str(self), str(lst_src)))
98 return (lst_src, [])
99 cls.scan = scan
101 # provide additional language processing
102 swig_langs = {}
103 def swig(fun):
104 swig_langs[fun.__name__.replace('swig_', '')] = fun
106 def swig_c(self):
107 ext = '.swigwrap_%d.c' % self.generator.idx
108 flags = self.env['SWIGFLAGS']
109 if '-c++' in flags:
110 ext += 'xx'
111 out_node = self.inputs[0].parent.find_or_declare(self.module + ext)
113 try:
114 if '-c++' in flags:
115 fun = self.generator.cxx_hook
116 else:
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 ''))
121 task = fun(out_node)
122 task.set_run_after(self)
124 ge = self.generator.bld.generator
125 ge.outstanding.insert(0, task)
126 ge.total += 1
128 try:
129 ltask = self.generator.link_task
130 except AttributeError:
131 pass
132 else:
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))
141 @swig
142 def swig_python(tsk):
143 tsk.set_outputs(tsk.inputs[0].parent.find_or_declare(tsk.module + '.py'))
145 @swig
146 def swig_ocaml(tsk):
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):
152 # the task instance
153 tsk = self.create_task('swig')
154 tsk.set_inputs(node)
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))
164 @conf
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))
179 if result:
180 conf.env['SWIG_VERSION'] = swigver_full
181 minver_str = '.'.join(map(str, minver))
182 if minver is None:
183 conf.check_message_custom('swig version', '', swigver_full)
184 else:
185 conf.check_message('swig version', '>= %s' % (minver_str,), result, option=swigver_full)
186 return result
188 def detect(conf):
189 swig = conf.find_program('swig', var='SWIG', mandatory=True)