summaryrefslogtreecommitdiff
path: root/src/rebar_erlc_compiler.erl
diff options
context:
space:
mode:
authorTristan Sloughter <t@crashfast.com>2014-11-22 09:13:10 -0600
committerTristan Sloughter <t@crashfast.com>2014-11-22 20:24:21 -0600
commitaf35d5f0a2c91319fc86c5bb4a9d018658519c4c (patch)
tree81513a265a2710a36a83b69e0758c3fcd0d5b61a /src/rebar_erlc_compiler.erl
parentf22db1302d710fbf017108852991cd6ac538de17 (diff)
replace rlx_depsolver use with new rebar_digraph
Diffstat (limited to 'src/rebar_erlc_compiler.erl')
-rw-r--r--src/rebar_erlc_compiler.erl71
1 files changed, 69 insertions, 2 deletions
diff --git a/src/rebar_erlc_compiler.erl b/src/rebar_erlc_compiler.erl
index 5e7787c..71ee780 100644
--- a/src/rebar_erlc_compiler.erl
+++ b/src/rebar_erlc_compiler.erl
@@ -38,6 +38,14 @@
-define(ERLCINFO_VSN, 1).
-define(ERLCINFO_FILE, "erlcinfo").
+-type erlc_info_v() :: {digraph:vertex(), term()} | 'false'.
+-type erlc_info_e() :: {digraph:vertex(), digraph:vertex()}.
+-type erlc_info() :: {list(erlc_info_v()), list(erlc_info_e())}.
+-record(erlcinfo,
+ {
+ vsn = ?ERLCINFO_VSN :: pos_integer(),
+ info = {[], []} :: erlc_info()
+ }).
-define(RE_PREFIX, "^[^._]").
@@ -392,11 +400,20 @@ needs_compile(Source, Target, Parents) ->
lists:any(fun(I) -> TargetLastMod < filelib:last_modified(I) end,
[Source] ++ Parents).
+check_erlcinfo(_Config, #erlcinfo{vsn=?ERLCINFO_VSN}) ->
+ ok;
+check_erlcinfo(Config, #erlcinfo{vsn=Vsn}) ->
+ ?ABORT("~s file version is incompatible. expected: ~b got: ~b",
+ [erlcinfo_file(Config), ?ERLCINFO_VSN, Vsn]);
+check_erlcinfo(Config, _) ->
+ ?ABORT("~s file is invalid. Please delete before next run.",
+ [erlcinfo_file(Config)]).
+
erlcinfo_file(_Config) ->
filename:join([rebar_utils:get_cwd(), ?CONFIG_DIR, ?ERLCINFO_FILE]).
init_erlcinfo(Config, Erls) ->
- G = rebar_digraph:restore_graph(erlcinfo_file(Config)),
+ G = restore_erlcinfo(Config),
%% Get a unique list of dirs based on the source files' locations.
%% This is used for finding files in sub dirs of the configured
%% src_dirs. For example, src/sub_dir/foo.erl.
@@ -408,7 +425,7 @@ init_erlcinfo(Config, Erls) ->
Updates = [update_erlcinfo(G, Erl, include_path(Erl, Config) ++ Dirs)
|| Erl <- Erls],
Modified = lists:member(modified, Updates),
- ok = rebar_digraph:store_graph(G, erlcinfo_file(Config), Modified),
+ ok = store_erlcinfo(G, Config, Modified),
G.
update_erlcinfo(G, Source, Dirs) ->
@@ -445,6 +462,56 @@ modify_erlcinfo(G, Source, Dirs) ->
digraph:add_edge(G, Source, Incl)
end, AbsIncls).
+restore_erlcinfo(Config) ->
+ File = erlcinfo_file(Config),
+ G = digraph:new(),
+ case file:read_file(File) of
+ {ok, Data} ->
+ try binary_to_term(Data) of
+ Erlcinfo ->
+ ok = check_erlcinfo(Config, Erlcinfo),
+ #erlcinfo{info=ErlcInfo} = Erlcinfo,
+ {Vs, Es} = ErlcInfo,
+ lists:foreach(
+ fun({V, LastUpdated}) ->
+ digraph:add_vertex(G, V, LastUpdated)
+ end, Vs),
+ lists:foreach(
+ fun({V1, V2}) ->
+ digraph:add_edge(G, V1, V2)
+ end, Es)
+ catch
+ error:badarg ->
+ ?ERROR(
+ "Failed (binary_to_term) to restore rebar info file."
+ " Discard file.", []),
+ ok
+ end;
+ _Err ->
+ ok
+ end,
+ G.
+
+store_erlcinfo(_G, _Config, _Modified = false) ->
+ ok;
+store_erlcinfo(G, Config, _Modified) ->
+ Vs = lists:map(
+ fun(V) ->
+ digraph:vertex(G, V)
+ end, digraph:vertices(G)),
+ Es = lists:flatmap(
+ fun({V, _}) ->
+ lists:map(
+ fun(E) ->
+ {_, V1, V2, _} = digraph:edge(G, E),
+ {V1, V2}
+ end, digraph:out_edges(G, V))
+ end, Vs),
+ File = erlcinfo_file(Config),
+ ok = filelib:ensure_dir(File),
+ Data = term_to_binary(#erlcinfo{info={Vs, Es}}, [{compressed, 9}]),
+ file:write_file(File, Data).
+
%% NOTE: If, for example, one of the entries in Files, refers to
%% gen_server.erl, that entry will be dropped. It is dropped because
%% such an entry usually refers to the beam file, and we don't pass a