58 lines
2.4 KiB
Erlang
58 lines
2.4 KiB
Erlang
#!/usr/bin/env escript
|
|
%% -*- erlang -*-
|
|
-mode(compile).
|
|
|
|
%% We expect the list of Erlang source and header files to arrive on
|
|
%% stdin, with the entries colon-separated.
|
|
main([TargetFile, EbinDir]) ->
|
|
ErlsAndHrls = [ string:strip(S,left) ||
|
|
S <- string:tokens(io:get_line(""), ":\n")],
|
|
ErlFiles = [F || F <- ErlsAndHrls, lists:suffix(".erl", F)],
|
|
Modules = sets:from_list(
|
|
[list_to_atom(filename:basename(FileName, ".erl")) ||
|
|
FileName <- ErlFiles]),
|
|
HrlFiles = [F || F <- ErlsAndHrls, lists:suffix(".hrl", F)],
|
|
IncludeDirs = lists:usort([filename:dirname(Path) || Path <- HrlFiles]),
|
|
Headers = sets:from_list(HrlFiles),
|
|
Deps = lists:foldl(
|
|
fun (Path, Deps1) ->
|
|
dict:store(Path, detect_deps(IncludeDirs, EbinDir,
|
|
Modules, Headers, Path),
|
|
Deps1)
|
|
end, dict:new(), ErlFiles),
|
|
{ok, Hdl} = file:open(TargetFile, [write, delayed_write]),
|
|
dict:fold(
|
|
fun (_Path, [], ok) ->
|
|
ok;
|
|
(Path, Dep, ok) ->
|
|
Module = filename:basename(Path, ".erl"),
|
|
ok = file:write(Hdl, [EbinDir, "/", Module, ".beam: ",
|
|
Path]),
|
|
ok = sets:fold(fun (E, ok) -> file:write(Hdl, [" ", E]) end,
|
|
ok, Dep),
|
|
file:write(Hdl, ["\n"])
|
|
end, ok, Deps),
|
|
ok = file:write(Hdl, [TargetFile, ": ", escript:script_name(), "\n"]),
|
|
ok = file:sync(Hdl),
|
|
ok = file:close(Hdl).
|
|
|
|
detect_deps(IncludeDirs, EbinDir, Modules, Headers, Path) ->
|
|
{ok, Forms} = epp:parse_file(Path, IncludeDirs, [{use_specs, true}]),
|
|
lists:foldl(
|
|
fun ({attribute, _LineNumber, Attribute, Behaviour}, Deps)
|
|
when Attribute =:= behaviour orelse Attribute =:= behavior ->
|
|
case sets:is_element(Behaviour, Modules) of
|
|
true -> sets:add_element(
|
|
[EbinDir, "/", atom_to_list(Behaviour), ".beam"],
|
|
Deps);
|
|
false -> Deps
|
|
end;
|
|
({attribute, _LineNumber, file, {FileName, _LineNumber1}}, Deps) ->
|
|
case sets:is_element(FileName, Headers) of
|
|
true -> sets:add_element(FileName, Deps);
|
|
false -> Deps
|
|
end;
|
|
(_Form, Deps) ->
|
|
Deps
|
|
end, sets:new(), Forms).
|