diff options
| -rw-r--r-- | src/rebar_erlc_compiler.erl | 35 | ||||
| -rw-r--r-- | test/rebar_compile_SUITE.erl | 58 | 
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 | 
