summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTristan Sloughter <tristan.sloughter@gmail.com>2015-02-17 10:37:27 -0600
committerTristan Sloughter <tristan.sloughter@gmail.com>2015-02-17 10:37:27 -0600
commitc5a655da140ed66818e5d22f1924dd60ab381d48 (patch)
tree76db4ebd9a55a8859d0ba538f991691bf53f2c26
parent43a18bf4fa55a7ef23a6da837ba4450996fe8725 (diff)
parent7fa628d61558a4051c4e415f33cae3cf0927ca2c (diff)
Merge pull request #157 from talentdeficit/real_needs_recompile
check already compiled modules compile arguments against current compile arguments
-rw-r--r--src/rebar_erlc_compiler.erl35
-rw-r--r--test/rebar_compile_SUITE.erl58
2 files changed, 82 insertions, 11 deletions
diff --git a/src/rebar_erlc_compiler.erl b/src/rebar_erlc_compiler.erl
index cb342a8..14e6349 100644
--- a/src/rebar_erlc_compiler.erl
+++ b/src/rebar_erlc_compiler.erl
@@ -250,11 +250,26 @@ include_path(Source, Config) ->
++ proplists:get_all_values(i, ErlOpts)).
-spec needs_compile(file:filename(), file:filename(),
- [string()]) -> boolean().
-needs_compile(Source, Target, Parents) ->
+ list(), [string()]) -> boolean().
+needs_compile(Source, Target, Opts, Parents) ->
TargetLastMod = filelib:last_modified(Target),
- lists:any(fun(I) -> TargetLastMod < filelib:last_modified(I) end,
- [Source] ++ Parents).
+ F = fun(I) -> source_changed(TargetLastMod, I) end,
+ lists:any(F, [Source] ++ Parents) orelse opts_changed(Opts, Target).
+
+source_changed(TargetLastMod, I) -> TargetLastMod < filelib:last_modified(I).
+
+opts_changed(Opts, Target) ->
+ Basename = filename:basename(Target, ".beam"),
+ Dirname = filename:dirname(Target),
+ ObjectFile = filename:join([Dirname, Basename]),
+ case code:load_abs(ObjectFile) of
+ {module, Mod} ->
+ Compile = Mod:module_info(compile),
+ lists:sort(Opts) =/= lists:sort(proplists:get_value(options,
+ Compile,
+ undefined));
+ {error, nofile} -> true
+ end.
check_erlcinfo(_Config, #erlcinfo{vsn=?ERLCINFO_VSN}) ->
ok;
@@ -423,13 +438,15 @@ internal_erl_compile(Config, Dir, Source, OutDir, ErlOpts, G) ->
Target = filename:join([OutDir | string:tokens(Module, ".")]) ++ ".beam",
ok = filelib:ensure_dir(Target),
+ %% Construct the compile opts
+ Opts = [{outdir, filename:dirname(Target)}] ++
+ ErlOpts ++ [{i, filename:join(Dir, "include")}],
+
%% If the file needs compilation, based on last mod date of includes or
%% the target
- case needs_compile(Source, Target, Parents) of
+ case needs_compile(Source, Target, Opts, Parents) of
true ->
- Opts = [{outdir, filename:dirname(Target)}] ++
- ErlOpts ++ [{i, filename:join(Dir, "include")}, return],
- case compile:file(Source, Opts) of
+ case compile:file(Source, Opts ++ [return]) of
{ok, _Mod} ->
ok;
{ok, _Mod, Ws} ->
@@ -485,7 +502,7 @@ compile_xrl_yrl(Config, Source, Target, Opts, Mod) ->
Dir = rebar_state:dir(Config),
Opts1 = [{includefile, filename:join(Dir, I)} || {includefile, I} <- Opts,
filename:pathtype(I) =:= relative],
- case needs_compile(Source, Target, []) of
+ case needs_compile(Source, Target, Opts1, []) of
true ->
case Mod:file(Source, Opts1 ++ [{return, true}]) of
{ok, _} ->
diff --git a/test/rebar_compile_SUITE.erl b/test/rebar_compile_SUITE.erl
index 627e834..fd1899f 100644
--- a/test/rebar_compile_SUITE.erl
+++ b/test/rebar_compile_SUITE.erl
@@ -8,7 +8,9 @@
build_basic_app/1,
build_release_apps/1,
build_checkout_apps/1,
- build_checkout_deps/1]).
+ build_checkout_deps/1,
+ recompile_when_opts_change/1,
+ dont_recompile_when_opts_dont_change/1]).
-include_lib("common_test/include/ct.hrl").
-include_lib("eunit/include/eunit.hrl").
@@ -28,7 +30,8 @@ init_per_testcase(_, Config) ->
all() ->
[build_basic_app, build_release_apps,
- build_checkout_apps, build_checkout_deps].
+ build_checkout_apps, build_checkout_deps,
+ recompile_when_opts_change, dont_recompile_when_opts_dont_change].
build_basic_app(Config) ->
AppDir = ?config(apps, Config),
@@ -88,3 +91,54 @@ build_checkout_deps(Config) ->
ok = application:load(list_to_atom(Name2)),
Loaded = application:loaded_applications(),
{_, _, Vsn2} = lists:keyfind(list_to_atom(Name2), 1, Loaded).
+
+recompile_when_opts_change(Config) ->
+ AppDir = ?config(apps, Config),
+ EbinDir = filename:join([AppDir, "ebin"]),
+
+ Name = rebar_test_utils:create_random_name("app1_"),
+ Vsn = rebar_test_utils:create_random_vsn(),
+ rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]),
+
+ rebar_test_utils:run_and_check(Config, [], ["compile"], {ok, [{app, Name}]}),
+
+ {ok, Files} = file:list_dir(EbinDir),
+ ModTime = [filelib:last_modified(filename:join([EbinDir, F]))
+ || F <- Files, filename:extension(F) == ".beam"],
+
+ timer:sleep(1000),
+
+ rebar_test_utils:create_config(AppDir, [{erl_opts, [{d, some_define}]}]),
+
+ rebar_test_utils:run_and_check(Config, [], ["compile"], {ok, [{app, Name}]}),
+
+ {ok, NewFiles} = file:list_dir(EbinDir),
+ NewModTime = [filelib:last_modified(filename:join([EbinDir, F]))
+ || F <- NewFiles, filename:extension(F) == ".beam"],
+
+ ?assert(ModTime =/= NewModTime).
+
+
+dont_recompile_when_opts_dont_change(Config) ->
+ AppDir = ?config(apps, Config),
+ EbinDir = filename:join([AppDir, "ebin"]),
+
+ Name = rebar_test_utils:create_random_name("app1_"),
+ Vsn = rebar_test_utils:create_random_vsn(),
+ rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]),
+
+ rebar_test_utils:run_and_check(Config, [], ["compile"], {ok, [{app, Name}]}),
+
+ {ok, Files} = file:list_dir(EbinDir),
+ ModTime = [filelib:last_modified(filename:join([EbinDir, F]))
+ || F <- Files, filename:extension(F) == ".beam"],
+
+ timer:sleep(1000),
+
+ rebar_test_utils:run_and_check(Config, [], ["compile"], {ok, [{app, Name}]}),
+
+ {ok, NewFiles} = file:list_dir(EbinDir),
+ NewModTime = [filelib:last_modified(filename:join([EbinDir, F]))
+ || F <- NewFiles, filename:extension(F) == ".beam"],
+
+ ?assert(ModTime == NewModTime). \ No newline at end of file