5 %% We expect the list of Erlang source and header files to arrive on
6 %% stdin, with the entries colon-separated.
7 main([TargetFile, EbinDir]) ->
8 ErlsAndHrls = [ string:strip(S,left) ||
9 S <- string:tokens(io:get_line(""), ":\n")],
10 ErlFiles = [F || F <- ErlsAndHrls, lists:suffix(".erl", F)],
11 Modules = sets:from_list(
12 [list_to_atom(filename:basename(FileName, ".erl")) ||
13 FileName <- ErlFiles]),
14 HrlFiles = [F || F <- ErlsAndHrls, lists:suffix(".hrl", F)],
15 IncludeDirs = lists:usort([filename:dirname(Path) || Path <- HrlFiles]),
16 Headers = sets:from_list(HrlFiles),
19 dict:store(Path, detect_deps(IncludeDirs, EbinDir,
20 Modules, Headers, Path),
22 end, dict:new(), ErlFiles),
23 {ok, Hdl} = file:open(TargetFile, [write, delayed_write]),
25 fun (_Path, [], ok) ->
28 Module = filename:basename(Path, ".erl"),
29 ok = file:write(Hdl, [EbinDir, "/", Module, ".beam: ",
31 ok = sets:fold(fun (E, ok) -> file:write(Hdl, [" ", E]) end,
33 file:write(Hdl, ["\n"])
35 ok = file:write(Hdl, [TargetFile, ": ", escript:script_name(), "\n"]),
39 detect_deps(IncludeDirs, EbinDir, Modules, Headers, Path) ->
40 {ok, Forms} = epp:parse_file(Path, IncludeDirs, [{use_specs, true}]),
42 fun ({attribute, _LineNumber, Attribute, Behaviour}, Deps)
43 when Attribute =:= behaviour orelse Attribute =:= behavior ->
44 case sets:is_element(Behaviour, Modules) of
45 true -> sets:add_element(
46 [EbinDir, "/", atom_to_list(Behaviour), ".beam"],
50 ({attribute, _LineNumber, file, {FileName, _LineNumber1}}, Deps) ->
51 case sets:is_element(FileName, Headers) of
52 true -> sets:add_element(FileName, Deps);
57 end, sets:new(), Forms).