cabal.py 4.9 KB

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