summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFred Hebert <mononcqc@ferd.ca>2014-12-30 13:31:23 -0500
committerFred Hebert <mononcqc@ferd.ca>2014-12-30 13:31:23 -0500
commit78774fe9e84c4cfc252f87436e8492ebd39dee09 (patch)
treec54f80ea178fe8b5bcf068dd5a7dbb9fd8d03edf
parentb8e0018782d8bdea138e56cb02fbc6cdf364bbcf (diff)
downloadrebar-revert-413-undo-386-merge.tar.gz
Revert "Revert "Merge pull request #386 ... gpb-recompilation...detection""revert-413-undo-386-merge
-rw-r--r--inttest/proto_gpb/proto_gpb_rt.erl50
-rw-r--r--src/rebar_proto_gpb_compiler.erl83
2 files changed, 106 insertions, 27 deletions
diff --git a/inttest/proto_gpb/proto_gpb_rt.erl b/inttest/proto_gpb/proto_gpb_rt.erl
index aafc677..cfbd1b4 100644
--- a/inttest/proto_gpb/proto_gpb_rt.erl
+++ b/inttest/proto_gpb/proto_gpb_rt.erl
@@ -29,6 +29,8 @@
run/1]).
-include_lib("eunit/include/eunit.hrl").
+-include_lib("kernel/include/file.hrl").
+-include_lib("deps/retest/include/retest.hrl").
-define(MODULES,
[foo,
@@ -42,6 +44,13 @@
test4_gpb,
test5_gpb]).
+-define(SOURCE_PROTO_FILES,
+ ["test.proto",
+ "a/test2.proto",
+ "a/b/test3.proto",
+ "c/test4.proto",
+ "c/d/test5.proto"]).
+
files() ->
[
{copy, "../../rebar", "rebar"},
@@ -60,6 +69,17 @@ run(_Dir) ->
%% generating the test_gpb.hrl file, and also that it generated
%% the .hrl file was generated before foo was compiled.
ok = check_beams_generated(),
+
+ ?DEBUG("Verifying recompilation~n", []),
+ TestErl = hd(generated_erl_files()),
+ TestProto = hd(source_proto_files()),
+ make_proto_newer_than_erl(TestProto, TestErl),
+ TestMTime1 = read_mtime(TestErl),
+ ?assertMatch({ok, _}, retest_sh:run("./rebar compile", [])),
+ TestMTime2 = read_mtime(TestErl),
+ ?assert(TestMTime2 > TestMTime1),
+
+ ?DEBUG("Verify cleanup~n", []),
?assertMatch({ok, _}, retest_sh:run("./rebar clean", [])),
ok = check_files_deleted(),
ok.
@@ -81,6 +101,12 @@ generated_erl_files() ->
generated_hrl_files() ->
add_dir("include", add_ext(?GENERATED_MODULES, ".hrl")).
+generated_beam_files() ->
+ add_dir("ebin", add_ext(?GENERATED_MODULES, ".beam")).
+
+source_proto_files() ->
+ add_dir("src", ?SOURCE_PROTO_FILES).
+
file_does_not_exist(F) ->
not filelib:is_regular(F).
@@ -90,6 +116,30 @@ add_ext(Modules, Ext) ->
add_dir(Dir, Files) ->
[filename:join(Dir, File) || File <- Files].
+read_mtime(File) ->
+ {ok, #file_info{mtime=MTime}} = file:read_file_info(File),
+ MTime.
+
+
+make_proto_newer_than_erl(Proto, Erl) ->
+ %% Do this by back-dating the erl file instead of touching the
+ %% proto file. Do this instead of sleeping for a second to get a
+ %% reliable test. Sleeping would have been needed sin ce the
+ %% #file_info{} (used by eg. filelib:last_modified) does not have
+ %% sub-second resolution (even though most file systems have).
+ {ok, #file_info{mtime=ProtoMTime}} = file:read_file_info(Proto),
+ {ok, ErlInfo} = file:read_file_info(Erl),
+ OlderMTime = update_seconds_to_datetime(ProtoMTime, -2),
+ OlderErlInfo = ErlInfo#file_info{mtime = OlderMTime},
+ ok = file:write_file_info(Erl, OlderErlInfo).
+
+update_seconds_to_datetime(DT, ToAdd) ->
+ calendar:gregorian_seconds_to_datetime(
+ calendar:datetime_to_gregorian_seconds(DT) + ToAdd).
+
+touch_file(File) ->
+ ?assertMatch({ok, _}, retest_sh:run("touch " ++ File, [])).
+
check(Check, Files) ->
lists:foreach(
fun(F) ->
diff --git a/src/rebar_proto_gpb_compiler.erl b/src/rebar_proto_gpb_compiler.erl
index 32a1f6d..d6c2c44 100644
--- a/src/rebar_proto_gpb_compiler.erl
+++ b/src/rebar_proto_gpb_compiler.erl
@@ -42,29 +42,36 @@
key() ->
gpb.
-proto_compile(Config, _AppFile, _ProtoFiles) ->
+proto_compile(Config, _AppFile, ProtoFiles) ->
%% Check for gpb library -- if it's not present, fail
%% since we have.proto files that need building
case gpb_is_present() of
true ->
- rebar_base_compiler:run(Config, [],
- "src", ".proto",
- "src", ".erl",
- fun compile_gpb/3,
- [{check_last_mod, true}]);
+ UserGpbOpts = user_gpb_opts(Config),
+ lists:foreach(
+ fun(ProtoFile) ->
+ GpbOpts = UserGpbOpts ++ default_dest_opts()
+ ++ default_include_opts(ProtoFile),
+
+ case needs_compile(ProtoFile, GpbOpts) of
+ true ->
+ compile_gpb(ProtoFile, GpbOpts);
+ false ->
+ ok
+ end
+ end,
+ ProtoFiles);
false ->
?ERROR("The gpb library is not present in code path!\n", []),
?FAIL
end.
proto_clean(Config, _AppFile, ProtoFiles) ->
- GpbOpts = gpb_opts(Config),
- MPrefix = proplists:get_value(module_name_prefix, GpbOpts, ""),
- MSuffix = proplists:get_value(module_name_suffix, GpbOpts, ""),
+ GpbOpts = user_gpb_opts(Config) ++ default_dest_opts(),
rebar_file_utils:delete_each(
- [beam_relpath(MPrefix, F, MSuffix) || F <- ProtoFiles]
- ++ [erl_relpath(MPrefix, F, MSuffix) || F <- ProtoFiles]
- ++ [hrl_relpath(MPrefix, F, MSuffix) || F <- ProtoFiles]),
+ [beam_file(F, GpbOpts) || F <- ProtoFiles]
+ ++ [erl_file(F, GpbOpts) || F <- ProtoFiles]
+ ++ [hrl_file(F, GpbOpts) || F <- ProtoFiles]),
ok.
%% ===================================================================
@@ -82,17 +89,27 @@ proto_info(help, compile) ->
proto_info(help, clean) ->
?CONSOLE("", []).
-gpb_opts(Config) ->
- rebar_config:get_local(Config, gpb_opts, []).
-
gpb_is_present() ->
code:which(gpb) =/= non_existing.
-compile_gpb(Source, _Target, Config) ->
+user_gpb_opts(Config) ->
+ rebar_config:get_local(Config, gpb_opts, []).
+
+default_dest_opts() ->
+ [{o_erl, "src"}, {o_hrl, "include"}].
+
+default_include_opts(Source) ->
+ SourceFullPath = filename:absname(Source),
+ [{i,filename:dirname(SourceFullPath)}].
+
+needs_compile(ProtoFile, GpbOpts) ->
+ Erl = erl_file(ProtoFile, GpbOpts),
+ Hrl = hrl_file(ProtoFile, GpbOpts),
+ filelib:last_modified(Erl) < filelib:last_modified(ProtoFile) orelse
+ filelib:last_modified(Hrl) < filelib:last_modified(ProtoFile).
+
+compile_gpb(Source, GpbOpts) ->
SourceFullPath = filename:absname(Source),
- DefaultDestOpts = [{o_erl, "src"}, {o_hrl, "include"}],
- SelfIncludeOpt = [{i,filename:dirname(SourceFullPath)}],
- GpbOpts = gpb_opts(Config) ++ DefaultDestOpts ++ SelfIncludeOpt,
ok = filelib:ensure_dir(filename:join("ebin", "dummy")),
ok = filelib:ensure_dir(filename:join("include", "dummy")),
case gpb_compile:file(SourceFullPath, GpbOpts) of
@@ -103,16 +120,28 @@ compile_gpb(Source, _Target, Config) ->
?FAIL
end.
-beam_relpath(Prefix, Proto, Suffix) ->
- proto_filename_to_relpath("ebin", Prefix, Proto, Suffix, ".beam").
+beam_file(ProtoFile, GpbOpts) ->
+ proto_filename_to_path("ebin", ProtoFile, ".beam", GpbOpts).
-erl_relpath(Prefix, Proto, Suffix) ->
- proto_filename_to_relpath("src", Prefix, Proto, Suffix, ".erl").
+erl_file(ProtoFile, GpbOpts) ->
+ ErlOutDir = get_erl_outdir(GpbOpts),
+ proto_filename_to_path(ErlOutDir, ProtoFile, ".erl", GpbOpts).
-hrl_relpath(Prefix, Proto, Suffix) ->
- proto_filename_to_relpath("include", Prefix, Proto, Suffix, ".hrl").
+hrl_file(ProtoFile, GpbOpts) ->
+ HrlOutDir = get_hrl_outdir(GpbOpts),
+ proto_filename_to_path(HrlOutDir, ProtoFile, ".hrl", GpbOpts).
-proto_filename_to_relpath(Dir, Prefix, Proto, Suffix, NewExt) ->
- BaseNoExt = filename:basename(Proto, ".proto"),
+proto_filename_to_path(Dir, ProtoFile, NewExt, GpbOpts) ->
+ BaseNoExt = filename:basename(ProtoFile, ".proto"),
+ Prefix = proplists:get_value(module_name_prefix, GpbOpts, ""),
+ Suffix = proplists:get_value(module_name_suffix, GpbOpts, ""),
filename:join([Dir, Prefix ++ BaseNoExt ++ Suffix ++ NewExt]).
+get_erl_outdir(Opts) ->
+ proplists:get_value(o_erl, Opts, get_outdir(Opts)).
+
+get_hrl_outdir(Opts) ->
+ proplists:get_value(o_hrl, Opts, get_outdir(Opts)).
+
+get_outdir(Opts) ->
+ proplists:get_value(o, Opts, ".").