|
matthias@2648
|
1 |
#!/usr/bin/env escript
|
|
matthias@2648
|
2 |
%% -*- erlang -*-
|
|
matthias@2648
|
3 |
-mode(compile).
|
|
matthias@2648
|
4 |
|
|
jerryk@5411
|
5 |
%% We expect the list of Erlang source and header files to arrive on
|
|
jerryk@5411
|
6 |
%% stdin, with the entries colon-separated.
|
|
jerryk@5394
|
7 |
main([TargetFile, EbinDir]) ->
|
|
jerryk@5411
|
8 |
ErlsAndHrls = [ string:strip(S,left) ||
|
|
jerryk@5411
|
9 |
S <- string:tokens(io:get_line(""), ":\n")],
|
|
jerryk@5394
|
10 |
ErlFiles = [F || F <- ErlsAndHrls, lists:suffix(".erl", F)],
|
|
matthias@2648
|
11 |
Modules = sets:from_list(
|
|
matthias@2648
|
12 |
[list_to_atom(filename:basename(FileName, ".erl")) ||
|
|
jerryk@5374
|
13 |
FileName <- ErlFiles]),
|
|
jerryk@5394
|
14 |
HrlFiles = [F || F <- ErlsAndHrls, lists:suffix(".hrl", F)],
|
|
jerryk@5374
|
15 |
IncludeDirs = lists:usort([filename:dirname(Path) || Path <- HrlFiles]),
|
|
jerryk@5374
|
16 |
Headers = sets:from_list(HrlFiles),
|
|
matthias@2648
|
17 |
Deps = lists:foldl(
|
|
matthias@2648
|
18 |
fun (Path, Deps1) ->
|
|
jerryk@5374
|
19 |
dict:store(Path, detect_deps(IncludeDirs, EbinDir,
|
|
matthias@2648
|
20 |
Modules, Headers, Path),
|
|
matthias@2648
|
21 |
Deps1)
|
|
matthias@2648
|
22 |
end, dict:new(), ErlFiles),
|
|
matthias@2648
|
23 |
{ok, Hdl} = file:open(TargetFile, [write, delayed_write]),
|
|
matthias@2648
|
24 |
dict:fold(
|
|
matthias@2648
|
25 |
fun (_Path, [], ok) ->
|
|
matthias@2648
|
26 |
ok;
|
|
matthias@2648
|
27 |
(Path, Dep, ok) ->
|
|
matthias@2648
|
28 |
Module = filename:basename(Path, ".erl"),
|
|
matthew@2916
|
29 |
ok = file:write(Hdl, [EbinDir, "/", Module, ".beam: ",
|
|
matthew@2916
|
30 |
Path]),
|
|
matthias@2648
|
31 |
ok = sets:fold(fun (E, ok) -> file:write(Hdl, [" ", E]) end,
|
|
matthias@2648
|
32 |
ok, Dep),
|
|
matthew@2916
|
33 |
file:write(Hdl, ["\n"])
|
|
matthias@2648
|
34 |
end, ok, Deps),
|
|
matthias@2648
|
35 |
ok = file:write(Hdl, [TargetFile, ": ", escript:script_name(), "\n"]),
|
|
matthias@2648
|
36 |
ok = file:sync(Hdl),
|
|
matthias@2648
|
37 |
ok = file:close(Hdl).
|
|
matthias@2648
|
38 |
|
|
jerryk@5374
|
39 |
detect_deps(IncludeDirs, EbinDir, Modules, Headers, Path) ->
|
|
jerryk@5374
|
40 |
{ok, Forms} = epp:parse_file(Path, IncludeDirs, [{use_specs, true}]),
|
|
matthias@2648
|
41 |
lists:foldl(
|
|
matthew@2805
|
42 |
fun ({attribute, _LineNumber, Attribute, Behaviour}, Deps)
|
|
matthew@2805
|
43 |
when Attribute =:= behaviour orelse Attribute =:= behavior ->
|
|
matthias@2648
|
44 |
case sets:is_element(Behaviour, Modules) of
|
|
matthias@2648
|
45 |
true -> sets:add_element(
|
|
matthias@2648
|
46 |
[EbinDir, "/", atom_to_list(Behaviour), ".beam"],
|
|
matthias@2648
|
47 |
Deps);
|
|
matthias@2648
|
48 |
false -> Deps
|
|
matthias@2648
|
49 |
end;
|
|
matthias@2648
|
50 |
({attribute, _LineNumber, file, {FileName, _LineNumber1}}, Deps) ->
|
|
matthias@2648
|
51 |
case sets:is_element(FileName, Headers) of
|
|
matthias@2648
|
52 |
true -> sets:add_element(FileName, Deps);
|
|
matthias@2648
|
53 |
false -> Deps
|
|
matthias@2648
|
54 |
end;
|
|
matthias@2648
|
55 |
(_Form, Deps) ->
|
|
matthias@2648
|
56 |
Deps
|
|
matthias@2648
|
57 |
end, sets:new(), Forms).
|