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
|
#!/usr/bin/env escript
%% -*- erlang -*-
-mode(compile).
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, Deps1) ->
dict:store(Path, detect_deps(Path), Deps1)
end, dict:new(), ErlFiles ++ HrlFiles),
Deps1 = 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, Deps),
{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:"]),
[write_deps(Hdl, IncludeDir, E) || E <- Dep],
file:write(Hdl, [" ", ErlDir, "/", Module, ".erl\n"]);
true ->
ok = file:write(Hdl, [Path, ":"]),
[write_deps(Hdl, IncludeDir, E) || E <- Dep],
file:write(Hdl, "\n")
end
end, ok, Deps1),
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]).
detect_deps(Path) ->
{ok, Forms} = epp:parse_file(Path, [], [{use_specs, true}]),
lists:foldl(
fun ({attribute, _LineNumber, behaviour, Behaviour}, Deps) ->
[{module, Behaviour} | Deps];
({error, {_LineNumber, epp, {include, file, Include}}}, Deps) ->
[{include, Include} | Deps];
(_Form, Deps) ->
Deps
end, [], Forms).
|