1#!/usr/bin/env python 2# encoding: utf-8 3# Anton Feldmann, 2012 4# "Base for cabal" 5 6from waflib import Task, Utils 7from waflib.TaskGen import extension 8from waflib.Utils import threading 9from shutil import rmtree 10 11lock = threading.Lock() 12registering = False 13 14def configure(self): 15 self.find_program('cabal', var='CABAL') 16 self.find_program('ghc-pkg', var='GHCPKG') 17 pkgconfd = self.bldnode.abspath() + '/package.conf.d' 18 self.env.PREFIX = self.bldnode.abspath() + '/dist' 19 self.env.PKGCONFD = pkgconfd 20 if self.root.find_node(pkgconfd + '/package.cache'): 21 self.msg('Using existing package database', pkgconfd, color='CYAN') 22 else: 23 pkgdir = self.root.find_dir(pkgconfd) 24 if pkgdir: 25 self.msg('Deleting corrupt package database', pkgdir.abspath(), color ='RED') 26 rmtree(pkgdir.abspath()) 27 pkgdir = None 28 29 self.cmd_and_log(self.env.GHCPKG + ['init', pkgconfd]) 30 self.msg('Created package database', pkgconfd, color = 'YELLOW' if pkgdir else 'GREEN') 31 32@extension('.cabal') 33def process_cabal(self, node): 34 out_dir_node = self.bld.root.find_dir(self.bld.out_dir) 35 package_node = node.change_ext('.package') 36 package_node = out_dir_node.find_or_declare(package_node.name) 37 build_node = node.parent.get_bld() 38 build_path = build_node.abspath() 39 config_node = build_node.find_or_declare('setup-config') 40 inplace_node = build_node.find_or_declare('package.conf.inplace') 41 42 config_task = self.create_task('cabal_configure', node) 43 config_task.cwd = node.parent.abspath() 44 config_task.depends_on = getattr(self, 'depends_on', '') 45 config_task.build_path = build_path 46 config_task.set_outputs(config_node) 47 48 build_task = self.create_task('cabal_build', config_node) 49 build_task.cwd = node.parent.abspath() 50 build_task.build_path = build_path 51 build_task.set_outputs(inplace_node) 52 53 copy_task = self.create_task('cabal_copy', inplace_node) 54 copy_task.cwd = node.parent.abspath() 55 copy_task.depends_on = getattr(self, 'depends_on', '') 56 copy_task.build_path = build_path 57 58 last_task = copy_task 59 task_list = [config_task, build_task, copy_task] 60 61 if (getattr(self, 'register', False)): 62 register_task = self.create_task('cabal_register', inplace_node) 63 register_task.cwd = node.parent.abspath() 64 register_task.set_run_after(copy_task) 65 register_task.build_path = build_path 66 67 pkgreg_task = self.create_task('ghcpkg_register', inplace_node) 68 pkgreg_task.cwd = node.parent.abspath() 69 pkgreg_task.set_run_after(register_task) 70 pkgreg_task.build_path = build_path 71 72 last_task = pkgreg_task 73 task_list += [register_task, pkgreg_task] 74 75 touch_task = self.create_task('cabal_touch', inplace_node) 76 touch_task.set_run_after(last_task) 77 touch_task.set_outputs(package_node) 78 touch_task.build_path = build_path 79 80 task_list += [touch_task] 81 82 return task_list 83 84def get_all_src_deps(node): 85 hs_deps = node.ant_glob('**/*.hs') 86 hsc_deps = node.ant_glob('**/*.hsc') 87 lhs_deps = node.ant_glob('**/*.lhs') 88 c_deps = node.ant_glob('**/*.c') 89 cpp_deps = node.ant_glob('**/*.cpp') 90 proto_deps = node.ant_glob('**/*.proto') 91 return sum([hs_deps, hsc_deps, lhs_deps, c_deps, cpp_deps, proto_deps], []) 92 93class Cabal(Task.Task): 94 def scan(self): 95 return (get_all_src_deps(self.generator.path), ()) 96 97class cabal_configure(Cabal): 98 run_str = '${CABAL} configure -v0 --prefix=${PREFIX} --global --user --package-db=${PKGCONFD} --builddir=${tsk.build_path}' 99 shell = True 100 101 def scan(self): 102 out_node = self.generator.bld.root.find_dir(self.generator.bld.out_dir) 103 deps = [out_node.find_or_declare(dep).change_ext('.package') for dep in Utils.to_list(self.depends_on)] 104 return (deps, ()) 105 106class cabal_build(Cabal): 107 run_str = '${CABAL} build -v1 --builddir=${tsk.build_path}/' 108 shell = True 109 110class cabal_copy(Cabal): 111 run_str = '${CABAL} copy -v0 --builddir=${tsk.build_path}' 112 shell = True 113 114class cabal_register(Cabal): 115 run_str = '${CABAL} register -v0 --gen-pkg-config=${tsk.build_path}/pkg.config --builddir=${tsk.build_path}' 116 shell = True 117 118class ghcpkg_register(Cabal): 119 run_str = '${GHCPKG} update -v0 --global --user --package-conf=${PKGCONFD} ${tsk.build_path}/pkg.config' 120 shell = True 121 122 def runnable_status(self): 123 global lock, registering 124 125 val = False 126 lock.acquire() 127 val = registering 128 lock.release() 129 130 if val: 131 return Task.ASK_LATER 132 133 ret = Task.Task.runnable_status(self) 134 if ret == Task.RUN_ME: 135 lock.acquire() 136 registering = True 137 lock.release() 138 139 return ret 140 141 def post_run(self): 142 global lock, registering 143 144 lock.acquire() 145 registering = False 146 lock.release() 147 148 return Task.Task.post_run(self) 149 150class cabal_touch(Cabal): 151 run_str = 'touch ${TGT}' 152 153