erlang.py 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. #!/usr/bin/env python
  2. # encoding: utf-8
  3. # Thomas Nagy, 2010 (ita)
  4. # Przemyslaw Rzepecki, 2016
  5. """
  6. Erlang support
  7. """
  8. import re
  9. from waflib import Task, TaskGen
  10. from waflib.TaskGen import feature, after_method, before_method
  11. # to load the method "to_incnodes" below
  12. from waflib.Tools import ccroot
  13. # Those flags are required by the Erlang VM to execute/evaluate code in
  14. # non-interactive mode. It is used in this tool to create Erlang modules
  15. # documentation and run unit tests. The user can pass additional arguments to the
  16. # 'erl' command with ERL_FLAGS environment variable.
  17. EXEC_NON_INTERACTIVE = ['-noshell', '-noinput', '-eval']
  18. def configure(conf):
  19. conf.find_program('erlc', var='ERLC')
  20. conf.find_program('erl', var='ERL')
  21. conf.add_os_flags('ERLC_FLAGS')
  22. conf.add_os_flags('ERL_FLAGS')
  23. conf.env.ERLC_DEF_PATTERN = '-D%s'
  24. conf.env.ERLC_INC_PATTERN = '-I%s'
  25. @TaskGen.extension('.erl')
  26. def process_erl_node(self, node):
  27. tsk = self.create_task('erl', node, node.change_ext('.beam'))
  28. tsk.erlc_incnodes = [tsk.outputs[0].parent] + self.to_incnodes(self.includes)
  29. tsk.env.append_value('ERLC_INCPATHS', [x.abspath() for x in tsk.erlc_incnodes])
  30. tsk.env.append_value('ERLC_DEFINES', self.to_list(getattr(self, 'defines', [])))
  31. tsk.env.append_value('ERLC_FLAGS', self.to_list(getattr(self, 'flags', [])))
  32. tsk.cwd = tsk.outputs[0].parent
  33. class erl(Task.Task):
  34. color = 'GREEN'
  35. run_str = '${ERLC} ${ERL_FLAGS} ${ERLC_INC_PATTERN:ERLC_INCPATHS} ${ERLC_DEF_PATTERN:ERLC_DEFINES} ${SRC}'
  36. def scan(task):
  37. node = task.inputs[0]
  38. deps = []
  39. scanned = set([])
  40. nodes_to_scan = [node]
  41. for n in nodes_to_scan:
  42. if n.abspath() in scanned:
  43. continue
  44. for i in re.findall('-include\("(.*)"\)\.', n.read()):
  45. for d in task.erlc_incnodes:
  46. r = d.find_node(i)
  47. if r:
  48. deps.append(r)
  49. nodes_to_scan.append(r)
  50. break
  51. scanned.add(n.abspath())
  52. return (deps, [])
  53. @TaskGen.extension('.beam')
  54. def process(self, node):
  55. pass
  56. class erl_test(Task.Task):
  57. color = 'BLUE'
  58. run_str = '${ERL} ${ERL_FLAGS} ${ERL_TEST_FLAGS}'
  59. @feature('eunit')
  60. @after_method('process_source')
  61. def add_erl_test_run(self):
  62. test_modules = [t.outputs[0] for t in self.tasks]
  63. test_task = self.create_task('erl_test')
  64. test_task.set_inputs(self.source + test_modules)
  65. test_task.cwd = test_modules[0].parent
  66. test_task.env.append_value('ERL_FLAGS', self.to_list(getattr(self, 'flags', [])))
  67. test_list = ", ".join([m.change_ext("").path_from(test_task.cwd)+":test()" for m in test_modules])
  68. test_flag = 'halt(case lists:all(fun(Elem) -> Elem == ok end, [%s]) of true -> 0; false -> 1 end).' % test_list
  69. test_task.env.append_value('ERL_TEST_FLAGS', EXEC_NON_INTERACTIVE)
  70. test_task.env.append_value('ERL_TEST_FLAGS', test_flag)
  71. class edoc(Task.Task):
  72. color = 'BLUE'
  73. run_str = "${ERL} ${ERL_FLAGS} ${ERL_DOC_FLAGS}"
  74. def keyword(self):
  75. return 'Generating edoc'
  76. @feature('edoc')
  77. @before_method('process_source')
  78. def add_edoc_task(self):
  79. # do not process source, it would create double erl->beam task
  80. self.meths.remove('process_source')
  81. e = self.path.find_resource(self.source)
  82. t = e.change_ext('.html')
  83. png = t.parent.make_node('erlang.png')
  84. css = t.parent.make_node('stylesheet.css')
  85. tsk = self.create_task('edoc', e, [t, png, css])
  86. tsk.cwd = tsk.outputs[0].parent
  87. tsk.env.append_value('ERL_DOC_FLAGS', EXEC_NON_INTERACTIVE)
  88. tsk.env.append_value('ERL_DOC_FLAGS', 'edoc:files(["%s"]), halt(0).' % tsk.inputs[0].abspath())
  89. # TODO the above can break if a file path contains '"'