1
2
3
4
5 "ocaml support"
6
7 import os, re
8 import TaskGen, Utils, Task, Build
9 from Logs import error
10 from TaskGen import taskgen, feature, before, after, extension
11
12 EXT_MLL = ['.mll']
13 EXT_MLY = ['.mly']
14 EXT_MLI = ['.mli']
15 EXT_MLC = ['.c']
16 EXT_ML = ['.ml']
17
18 open_re = re.compile('open ([a-zA-Z]+);;', re.M)
19 foo = re.compile(r"""(\(\*)|(\*\))|("(\\.|[^"\\])*"|'(\\.|[^'\\])*'|.[^()*"'\\]*)""", re.M)
27 return foo.sub(repl, txt)
28
30 node = self.inputs[0]
31 code = filter_comments(node.read(self.env))
32
33 global open_re
34 names = []
35 import_iterator = open_re.finditer(code)
36 if import_iterator:
37 for import_match in import_iterator:
38 names.append(import_match.group(1))
39 found_lst = []
40 raw_lst = []
41 for name in names:
42 nd = None
43 for x in self.incpaths:
44 nd = x.find_resource(name.lower()+'.ml')
45 if nd:
46 found_lst.append(nd)
47 break
48 else:
49 raw_lst.append(name)
50
51 return (found_lst, raw_lst)
52
53 native_lst=['native', 'all', 'c_object']
54 bytecode_lst=['bytecode', 'all']
57 TaskGen.task_gen.__init__(self, *k, **kw)
58
59
60
61
62 self.type = 'all'
63 self._incpaths_lst = []
64 self._bld_incpaths_lst = []
65 self._mlltasks = []
66 self._mlytasks = []
67
68 self.mlitasks = []
69 self.native_tasks = []
70 self.bytecode_tasks = []
71 self.linktasks = []
72
73 self.bytecode_env = None
74 self.native_env = None
75
76
77 self.compiled_tasks = []
78 self.includes = ''
79 self.uselib = ''
80
81 self.out_nodes = []
82
83 self.are_deps_set = 0
84
85 if not self.type in ['bytecode', 'native', 'all', 'c_object']:
86 print 'type for camlobj is undefined '+self.type
87 self.type='all'
88
89 TaskGen.bind_feature('ocaml', 'apply_core')
94
95 self.islibrary = getattr(self, 'islibrary', False)
96
97 global native_lst, bytecode_lst
98 self.native_env = None
99 if self.type in native_lst:
100 self.native_env = self.env.copy()
101 if self.islibrary: self.native_env['OCALINKFLAGS'] = '-a'
102
103 self.bytecode_env = None
104 if self.type in bytecode_lst:
105 self.bytecode_env = self.env.copy()
106 if self.islibrary: self.bytecode_env['OCALINKFLAGS'] = '-a'
107
108 if self.type == 'c_object':
109 self.native_env['OCALINK'] = self.native_env['OCALINK']+' -output-obj'
110
111 @taskgen
112 @feature('ocaml')
113 @before('apply_vars_ml')
114 @after('init_envs_ml')
115 -def apply_incpaths_ml(self):
116 inc_lst = self.includes.split()
117 lst = self._incpaths_lst
118 tree = Build.bld
119 for dir in inc_lst:
120 node = self.path.find_dir(dir)
121 if not node:
122 error("node not found: " + str(dir))
123 continue
124 Build.bld.rescan(node)
125 if not node in lst: lst.append(node)
126 self._bld_incpaths_lst.append(node)
127
128
129 @taskgen
130 @feature('ocaml')
131 @before('apply_core')
132 -def apply_vars_ml(self):
133 for i in self._incpaths_lst:
134 if self.bytecode_env:
135 self.bytecode_env.append_value('OCAMLPATH', '-I %s' % i.srcpath(self.env))
136 self.bytecode_env.append_value('OCAMLPATH', '-I %s' % i.bldpath(self.env))
137
138 if self.native_env:
139 self.native_env.append_value('OCAMLPATH', '-I %s' % i.bldpath(self.env))
140 self.native_env.append_value('OCAMLPATH', '-I %s' % i.srcpath(self.env))
141
142 varnames = ['INCLUDES', 'OCAMLFLAGS', 'OCALINKFLAGS', 'OCALINKFLAGS_OPT']
143 for name in self.uselib.split():
144 for vname in varnames:
145 cnt = self.env[vname+'_'+name]
146 if cnt:
147 if self.bytecode_env: self.bytecode_env.append_value(vname, cnt)
148 if self.native_env: self.native_env.append_value(vname, cnt)
149
150 @taskgen
151 @feature('ocaml')
152 @after('apply_core')
153 -def apply_link_ml(self):
154
155 if self.bytecode_env:
156 ext = self.islibrary and '.cma' or '.run'
157
158 linktask = self.create_task('ocalink')
159 linktask.bytecode = 1
160 linktask.set_outputs(self.path.find_or_declare(self.target + ext))
161 linktask.obj = self
162 linktask.env = self.bytecode_env
163 self.linktasks.append(linktask)
164
165 if self.native_env:
166 if getattr(self, 'c_objects', ''): ext = '.o'
167 elif self.islibrary: ext = '.cmxa'
168 else: ext = ''
169
170 linktask = self.create_task('ocalinkx')
171 linktask.set_outputs(self.path.find_or_declare(self.target + ext))
172 linktask.obj = self
173 linktask.env = self.native_env
174 self.linktasks.append(linktask)
175
176 self.out_nodes += linktask.outputs
177
178
179 if self.type == 'c_object': self.compiled_tasks.append(linktask)
180
183 mll_task = self.create_task('ocamllex', self.native_env)
184 mll_task.set_inputs(node)
185 mll_task.set_outputs(node.change_ext('.ml'))
186 self.mlltasks.append(mll_task)
187
188 self.allnodes.append(mll_task.outputs[0])
189
201
208
216
219 if self.native_env:
220 task = self.create_task('ocamlx', self.native_env)
221 task.set_inputs(node)
222 task.set_outputs(node.change_ext('.cmx'))
223 task.obj = self
224 task.incpaths = self._bld_incpaths_lst
225 self.native_tasks.append(task)
226
227 if self.bytecode_env:
228 task = self.create_task('ocaml', self.bytecode_env)
229 task.set_inputs(node)
230 task.obj = self
231 task.bytecode = 1
232 task.incpaths = self._bld_incpaths_lst
233 task.set_outputs(node.change_ext('.cmo'))
234 self.bytecode_tasks.append(task)
235
237 if not getattr(self.obj, 'flag_deps', ''):
238 self.obj.flag_deps = 1
239
240
241
242 if getattr(self, 'bytecode', ''): alltasks = self.obj.bytecode_tasks
243 else: alltasks = self.obj.native_tasks
244
245 self.signature()
246 tree = Build.bld
247 env = self.env
248 for node in self.inputs:
249 lst = tree.node_deps[self.unique_id()]
250 for depnode in lst:
251 for t in alltasks:
252 if t == self: continue
253 if depnode in t.inputs:
254 self.set_run_after(t)
255
256
257 delattr(self, 'sign_all')
258 self.signature()
259
260 return Task.Task.runnable_status(self)
261
262 b = Task.simple_task_type
263 cls = b('ocamlx', '${OCAMLOPT} ${OCAMLPATH} ${OCAMLFLAGS} ${INCLUDES} -c -o ${TGT} ${SRC}', color='GREEN')
264 cls.runnable_status = compile_may_start
265 cls.scan = scan
266
267 b = Task.simple_task_type
268 cls = b('ocaml', '${OCAMLC} ${OCAMLPATH} ${OCAMLFLAGS} ${INCLUDES} -c -o ${TGT} ${SRC}', color='GREEN')
269 cls.runnable_status = compile_may_start
270 cls.scan = scan
271
272
273 b('ocamlcmi', '${OCAMLC} ${OCAMLPATH} ${INCLUDES} -o ${TGT} -c ${SRC}', color='BLUE', before="ocaml ocamlcc")
274 b('ocamlcc', 'cd ${TGT[0].bld_dir(env)} && ${OCAMLOPT} ${OCAMLFLAGS} ${OCAMLPATH} ${INCLUDES} -c ${SRC[0].abspath(env)}', color='GREEN')
275
276 b('ocamllex', '${OCAMLLEX} ${SRC} -o ${TGT}', color='BLUE', before="ocamlcmi ocaml ocamlcc")
277 b('ocamlyacc', '${OCAMLYACC} -b ${TGT[0].bld_base(env)} ${SRC}', color='BLUE', before="ocamlcmi ocaml ocamlcc")
281 if not getattr(self, 'order', ''):
282
283
284 if getattr(self, 'bytecode', 0): alltasks = self.obj.bytecode_tasks
285 else: alltasks = self.obj.native_tasks
286
287
288
289 seen = []
290 pendant = []+alltasks
291 while pendant:
292 task = pendant.pop(0)
293 if task in seen: continue
294 for x in task.run_after:
295 if not x in seen:
296 pendant.append(task)
297 break
298 else:
299 seen.append(task)
300 self.inputs = [x.outputs[0] for x in seen]
301 self.order = 1
302 return Task.Task.