diff --git a/inttest/erlc_dep_graph/erlc_dep_graph_rt.erl b/inttest/erlc_dep_graph/erlc_dep_graph_rt.erl index d5f92cf..ee3907e 100644 --- a/inttest/erlc_dep_graph/erlc_dep_graph_rt.erl +++ b/inttest/erlc_dep_graph/erlc_dep_graph_rt.erl @@ -32,13 +32,22 @@ files() -> [{copy, "../../rebar", "rebar"}, - {copy, "src", "src"}]. + {copy, "rebar.config", "rebar.config"}, + {copy, "src", "src"}, + {copy, "include", "include"}, + {copy, "extra_include", "extra_include"}]. run(_Dir) -> compile_all(ok, ""), check_beams_ok(), check_beams_untouched(), - modify_and_recompile_ok(), + modify_and_recompile_ok("src/lisp.erl", "ebin/lisp.beam"), + + clean_all_ok(), + compile_all(error, "-C rebar.config.non-existing"), + compile_all(ok, ""), + modify_and_recompile_ok("extra_include/extra.hrl", "ebin/java.beam"), + ok. check_beams_ok() -> @@ -49,9 +58,9 @@ check_beams_untouched() -> Beams = filelib:wildcard("ebin/*.beam"), compile_all_and_assert_mtimes(Beams, fun erlang:'=:='/2). -modify_and_recompile_ok() -> - touch(["src/lisp.erl"]), - compile_all_and_assert_mtimes(["ebin/lisp.beam"], fun erlang:'<'/2). +modify_and_recompile_ok(TouchFile, CheckFile) -> + touch([TouchFile]), + compile_all_and_assert_mtimes([CheckFile], fun erlang:'<'/2). compile_all_and_assert_mtimes(Beams, Cmp) -> BeamsModifiedBefore = mtime_ns(Beams), diff --git a/inttest/erlc_dep_graph/extra_include/extra.hrl b/inttest/erlc_dep_graph/extra_include/extra.hrl new file mode 100644 index 0000000..9d034c9 --- /dev/null +++ b/inttest/erlc_dep_graph/extra_include/extra.hrl @@ -0,0 +1,3 @@ +%% -*- mode: erlang;erlang-indent-level: 4;indent-tabs-mode: nil -*- +%% ex: ts=4 sw=4 ft=erlang et +-define(CONCISE, impossible). diff --git a/inttest/erlc_dep_graph/include/lambda.hrl b/inttest/erlc_dep_graph/include/lambda.hrl new file mode 100644 index 0000000..6b1622c --- /dev/null +++ b/inttest/erlc_dep_graph/include/lambda.hrl @@ -0,0 +1,3 @@ +%% -*- mode: erlang;erlang-indent-level: 4;indent-tabs-mode: nil -*- +%% ex: ts=4 sw=4 ft=erlang et +-define(FUN, fake). diff --git a/inttest/erlc_dep_graph/rebar.config b/inttest/erlc_dep_graph/rebar.config new file mode 100644 index 0000000..5002bcd --- /dev/null +++ b/inttest/erlc_dep_graph/rebar.config @@ -0,0 +1,6 @@ +%% -*- mode: erlang;erlang-indent-level: 4;indent-tabs-mode: nil -*- +%% ex: ts=4 sw=4 ft=erlang et +{erl_opts, + [ + {i, "extra_include"} + ]}. diff --git a/inttest/erlc_dep_graph/src/java.erl b/inttest/erlc_dep_graph/src/java.erl new file mode 100644 index 0000000..2e3f281 --- /dev/null +++ b/inttest/erlc_dep_graph/src/java.erl @@ -0,0 +1,11 @@ +%% -*- mode: erlang;erlang-indent-level: 4;indent-tabs-mode: nil -*- +%% ex: ts=4 sw=4 ft=erlang et +-module(java). + +-export([factory/0]). + +-include("lambda.hrl"). +-include("extra.hrl"). + +factory() -> + ?FUN. diff --git a/src/rebar_erlc_compiler.erl b/src/rebar_erlc_compiler.erl index af7cf64..e8b77a6 100644 --- a/src/rebar_erlc_compiler.erl +++ b/src/rebar_erlc_compiler.erl @@ -40,11 +40,11 @@ -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())}. +-type erlc_info() :: {list(erlc_info_v()), list(erlc_info_e()), list(string())}. -record(erlcinfo, { vsn = ?ERLCINFO_VSN :: pos_integer(), - info = {[], []} :: erlc_info() + info = {[], [], []} :: erlc_info() }). -ifdef(namespaced_types). @@ -387,10 +387,6 @@ u_add_element(Elem, [Elem|_]=Set) -> Set; u_add_element(Elem, [E1|Set]) -> [E1|u_add_element(Elem, Set)]; u_add_element(Elem, []) -> [Elem]. --spec include_path(file:filename(), list()) -> [file:filename(), ...]. -include_path(Source, InclDirs) -> - lists:usort(["include", filename:dirname(Source) |InclDirs]). - -spec needs_compile(file:filename(), file:filename(), [string()]) -> boolean(). needs_compile(Source, Target, Parents) -> @@ -403,26 +399,22 @@ erlcinfo_file() -> init_erlcinfo(InclDirs, Erls) -> G = digraph:new(), - try restore_erlcinfo(G) + try restore_erlcinfo(G, InclDirs) catch - _ -> + _:_ -> ?WARN("Failed to restore ~s file. Discarding it.~n", [erlcinfo_file()]), ok = file:delete(erlcinfo_file()) end, - %% 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. - Dirs = sets:to_list(lists:foldl( - fun(Erl, Acc) -> - Dir = filename:dirname(Erl), - sets:add_element(Dir, Acc) - end, sets:new(), Erls)), - Updates = [update_erlcinfo(G, Erl, include_path(Erl, InclDirs) ++ Dirs) - || Erl <- Erls], + Dirs = source_and_include_dirs(InclDirs, Erls), + Updates = [update_erlcinfo(G, Erl, Dirs) || Erl <- Erls], Modified = lists:member(modified, Updates), - ok = store_erlcinfo(G, Modified), + ok = store_erlcinfo(G, Modified, InclDirs), G. +source_and_include_dirs(InclDirs, Erls) -> + SourceDirs = lists:map(fun filename:dirname/1, Erls), + lists:usort(["include" | InclDirs ++ SourceDirs]). + update_erlcinfo(G, Source, Dirs) -> case digraph:vertex(G, Source) of {_, LastUpdated} -> @@ -457,10 +449,13 @@ modify_erlcinfo(G, Source, Dirs) -> digraph:add_edge(G, Source, Incl) end, AbsIncls). -restore_erlcinfo(G) -> +restore_erlcinfo(G, InclDirs) -> case file:read_file(erlcinfo_file()) of {ok, Data} -> - #erlcinfo{vsn=?ERLCINFO_VSN, info={Vs, Es}} = binary_to_term(Data), + %% Since externally passed InclDirs can influence erlcinfo graph (see + %% modify_erlcinfo), we have to check here that they didn't change. + #erlcinfo{vsn=?ERLCINFO_VSN, info={Vs, Es, InclDirs}} = + binary_to_term(Data), lists:foreach( fun({V, LastUpdated}) -> digraph:add_vertex(G, V, LastUpdated) @@ -473,9 +468,9 @@ restore_erlcinfo(G) -> ok end. -store_erlcinfo(_G, _Modified = false) -> +store_erlcinfo(_G, _Modified = false, _InclDirs) -> ok; -store_erlcinfo(G, _Modified) -> +store_erlcinfo(G, _Modified, InclDirs) -> Vs = lists:map( fun(V) -> digraph:vertex(G, V) @@ -490,7 +485,7 @@ store_erlcinfo(G, _Modified) -> end, Vs), File = erlcinfo_file(), ok = filelib:ensure_dir(File), - Data = term_to_binary(#erlcinfo{info={Vs, Es}}, [{compressed, 9}]), + Data = term_to_binary(#erlcinfo{info={Vs, Es, InclDirs}}, [{compressed, 9}]), file:write_file(File, Data). %% NOTE: If, for example, one of the entries in Files refers to