Package wafadmin :: Package Tools :: Module ocaml
[hide private]
[frames] | no frames]

Source Code for Module wafadmin.Tools.ocaml

  1  #!/usr/bin/env python 
  2  # encoding: utf-8 
  3  # Thomas Nagy, 2006 (ita) 
  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) 
20 -def filter_comments(txt):
21 meh = [0] 22 def repl(m): 23 if m.group(1): meh[0] += 1 24 elif m.group(2): meh[0] -= 1 25 elif not meh[0]: return m.group(0) 26 return ''
27 return foo.sub(repl, txt) 28
29 -def scan(self):
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']
55 -class ocaml_taskgen(TaskGen.task_gen):
56 - def __init__(self, *k, **kw):
57 TaskGen.task_gen.__init__(self, *k, **kw) 58 59 #self.type = kw.get('type', 'native') 60 #self.islibrary = kw.get('library', 0) 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')
90 91 @taskgen 92 @feature('ocaml') 93 -def init_envs_ml(self):
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 # now the nodes are added to self._incpaths_lst
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 180
181 @extension(EXT_MLL) 182 -def mll_hook(self, node):
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
190 @extension(EXT_MLY) 191 -def mly_hook(self, node):
192 mly_task = self.create_task('ocamlyacc', self.native_env) 193 mly_task.set_inputs(node) 194 mly_task.set_outputs([node.change_ext('.ml'), node.change_ext('.mli')]) 195 self._mlytasks.append(mly_task) 196 self.allnodes.append(mly_task.outputs[0]) 197 198 task = self.create_task('ocamlcmi', self.native_env) 199 task.set_inputs(mly_task.outputs[1]) 200 task.set_outputs(mly_task.outputs[1].change_ext('.cmi'))
201
202 @extension(EXT_MLI) 203 -def mli_hook(self, node):
204 task = self.create_task('ocamlcmi', self.native_env) 205 task.set_inputs(node) 206 task.set_outputs(node.change_ext('.cmi')) 207 self.mlitasks.append(task)
208
209 @extension(EXT_MLC) 210 -def mlc_hook(self, node):
211 task = self.create_task('ocamlcc', self.native_env) 212 task.set_inputs(node) 213 task.set_outputs(node.change_ext('.o')) 214 215 self.out_nodes += task.outputs
216
217 @extension(EXT_ML) 218 -def ml_hook(self, node):
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
236 -def compile_may_start(self):
237 if not getattr(self.obj, 'flag_deps', ''): 238 self.obj.flag_deps = 1 239 240 # the evil part is that we can only compute the dependencies after the 241 # source files can be read (this means actually producing the source files) 242 if getattr(self, 'bytecode', ''): alltasks = self.obj.bytecode_tasks 243 else: alltasks = self.obj.native_tasks 244 245 self.signature() # ensure that files are scanned - unfortunately 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 # TODO necessary to get the signature right - for now 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")