1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
|
#!/usr/bin/env escript
%% -*- erlang -*-
main([IncludeDir, ErlDir, TargetFile]) ->
ErlDirContents = filelib:wildcard("*.erl", ErlDir),
ErlFiles = [filename:join(ErlDir, FileName) || FileName <- ErlDirContents],
Modules = sets:from_list(
[list_to_atom(filename:basename(FileName, ".erl")) ||
FileName <- ErlDirContents]),
IncludeDirContents = filelib:wildcard("*.hrl", IncludeDir),
HrlFiles = [filename:join(IncludeDir, FileName) ||
FileName <- IncludeDirContents],
Headers = sets:from_list(IncludeDirContents),
Deps = lists:foldl(fun (Path, Acc) -> make_deps(Path, Acc) end,
dict:new(), ErlFiles),
Deps1 = lists:foldl(fun (Path, Acc) -> make_deps(Path, Acc) end,
Deps, HrlFiles),
Deps2 = dict:map(
fun (_Path, Dep) ->
lists:filter(
fun ({module, Behaviour}) ->
sets:is_element(Behaviour, Modules);
({include, Include}) ->
sets:is_element(Include, Headers)
end, Dep)
end, Deps1),
{ok, Hdl} = file:open(TargetFile, [write, delayed_write]),
dict:fold(
fun (_Path, [], ok) ->
ok;
(Path, Dep, ok) ->
case lists:suffix(".hrl", Path) of
false ->
Module = filename:basename(Path, ".erl"),
ok = file:write(Hdl, ["$(EBIN_DIR)/", Module, ".beam:"]),
lists:foreach(
fun (E) -> write_deps(Hdl, IncludeDir, E) end, Dep),
file:write(Hdl, [" ", ErlDir, "/", Module, ".erl\n"]);
true ->
ok = file:write(Hdl, [Path, ":"]),
lists:foreach(
fun (E) -> write_deps(Hdl, IncludeDir, E) end, Dep),
file:write(Hdl, "\n")
end
end, ok, Deps2),
ok = file:write(Hdl, [TargetFile, ": ", escript:script_name(), "\n"]),
ok = file:sync(Hdl),
ok = file:close(Hdl).
write_deps(Hdl, _IncludeDir, {module, Behaviour}) ->
ok = file:write(Hdl, [" $(EBIN_DIR)/", atom_to_list(Behaviour), ".beam"]);
write_deps(Hdl, IncludeDir, {include, Include}) ->
ok = file:write(Hdl, [" ", IncludeDir, "/", Include]).
make_deps(Path, Deps) ->
{ok, Forms} = epp:parse_file(Path, [], []),
Behaviours =
lists:foldl(fun (Form, Acc) -> detect_deps(Form, Acc) end,
[], Forms),
dict:store(Path, Behaviours, Deps).
detect_deps({attribute, _LineNumber, behaviour, Behaviour}, Deps) ->
[{module, Behaviour} | Deps];
detect_deps({error, {_LineNumber, epp, {include, file, Include}}}, Deps) ->
[{include, Include} | Deps];
detect_deps(_Form, Deps) ->
Deps.
|