summaryrefslogtreecommitdiff
path: root/generate_deps
blob: 9be6fc094f3121b7475ace29bc2920debc461317 (plain)
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).