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