summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/rebar_erlc_compiler.erl33
-rw-r--r--src/rebar_prv_install_deps.erl35
-rw-r--r--test/mock_pkg_resource.erl2
-rw-r--r--test/rebar_compile_SUITE.erl27
-rw-r--r--test/rebar_test_utils.erl4
5 files changed, 77 insertions, 24 deletions
diff --git a/src/rebar_erlc_compiler.erl b/src/rebar_erlc_compiler.erl
index 862d21e..8fe03b7 100644
--- a/src/rebar_erlc_compiler.erl
+++ b/src/rebar_erlc_compiler.erl
@@ -161,7 +161,7 @@ doterl_compile(Config, Dir, OutDir, MoreSources, ErlOpts) ->
filename:extension(File) =:= ".erl"],
NeededErlFiles = needed_files(G, ErlOpts, Dir, OutDir1, AllErlFiles),
- ErlFirstFiles = erl_first_files(Config, Dir, NeededErlFiles),
+ {ErlFirstFiles, ErlOptsFirst} = erl_first_files(Config, ErlOpts, Dir, NeededErlFiles),
{DepErls, OtherErls} = lists:partition(
fun(Source) -> digraph:in_degree(G, Source) > 0 end,
[File || File <- NeededErlFiles, not lists:member(File, ErlFirstFiles)]),
@@ -171,15 +171,36 @@ doterl_compile(Config, Dir, OutDir, MoreSources, ErlOpts) ->
rebar_base_compiler:run(
Config, FirstErls, OtherErls,
fun(S, C) ->
- internal_erl_compile(C, Dir, S, OutDir1, ErlOpts)
+ ErlOpts1 = case lists:member(S, ErlFirstFiles) of
+ true -> ErlOptsFirst;
+ false -> ErlOpts
+ end,
+ internal_erl_compile(C, Dir, S, OutDir1, ErlOpts1)
end),
ok.
-erl_first_files(Config, Dir, NeededErlFiles) ->
+%% Get files which need to be compiled first, i.e. those specified in erl_first_files
+%% and parse_transform options. Also produce specific erl_opts for these first
+%% files, so that yet to be compiled parse transformations are excluded from it.
+erl_first_files(Config, ErlOpts, Dir, NeededErlFiles) ->
ErlFirstFilesConf = rebar_state:get(Config, erl_first_files, []),
- %% NOTE: order of files in ErlFirstFiles is important!
- [filename:join(Dir, File) || File <- ErlFirstFilesConf,
- lists:member(filename:join(Dir, File), NeededErlFiles)].
+ NeededSrcDirs = lists:usort(lists:map(fun filename:dirname/1, NeededErlFiles)),
+ %% NOTE: order of files here is important!
+ ErlFirstFiles =
+ [filename:join(Dir, File) || File <- ErlFirstFilesConf,
+ lists:member(filename:join(Dir, File), NeededErlFiles)],
+ {ParseTransforms, ParseTransformsErls} =
+ lists:unzip(lists:flatmap(
+ fun(PT) ->
+ PTerls = [filename:join(D, module_to_erl(PT)) || D <- NeededSrcDirs],
+ [{PT, PTerl} || PTerl <- PTerls, lists:member(PTerl, NeededErlFiles)]
+ end, proplists:get_all_values(parse_transform, ErlOpts))),
+ ErlOptsFirst = lists:filter(fun({parse_transform, PT}) ->
+ not lists:member(PT, ParseTransforms);
+ (_) ->
+ true
+ end, ErlOpts),
+ {ErlFirstFiles ++ ParseTransformsErls, ErlOptsFirst}.
%% Get subset of SourceFiles which need to be recompiled, respecting
%% dependencies induced by given graph G.
diff --git a/src/rebar_prv_install_deps.erl b/src/rebar_prv_install_deps.erl
index e25e2c5..17346f4 100644
--- a/src/rebar_prv_install_deps.erl
+++ b/src/rebar_prv_install_deps.erl
@@ -128,30 +128,39 @@ handle_deps(Profile, State, Deps, Locks) when is_list(Locks) ->
handle_deps(_Profile, State, [], _, _) ->
{ok, [], State};
handle_deps(Profile, State0, Deps, Upgrade, Locks) ->
- %% Read in package index and dep graph
- {Packages, Graph} = rebar_state:packages(State0),
- Registry = rebar_packages:registry(State0),
- State = rebar_state:packages(rebar_state:registry(State0, Registry), {Packages, Graph}),
%% Split source deps from pkg deps, needed to keep backwards compatibility
- DepsDir = profile_dep_dir(State, Profile),
- {SrcDeps, PkgDeps} = parse_deps(DepsDir, Deps, State, Locks, 0),
+ DepsDir = profile_dep_dir(State0, Profile),
+
+ {SrcDeps, PkgDeps} = parse_deps(DepsDir, Deps, State0, Locks, 0),
%% Fetch transitive src deps
- {State1, SrcApps, PkgDeps1, Seen} =
- update_src_deps(Profile, 0, SrcDeps, PkgDeps, [], State, Upgrade, sets:new(), Locks),
+ {State1, SrcApps, PkgDeps1, Seen} = update_src_deps(Profile, 0, SrcDeps, PkgDeps, []
+ ,State0, Upgrade, sets:new(), Locks),
- {Solved, State2} =
- update_pkg_deps(Profile, Packages, PkgDeps1, Graph, Upgrade, Seen, State1),
+ {Solved, State4} =
+ case PkgDeps1 of
+ [] ->
+ {[], State1};
+ _ ->
+ %% Read in package index and dep graph
+ {Packages, Graph} = rebar_state:packages(State1),
+ Registry = rebar_packages:registry(State1),
+ State2 = rebar_state:packages(rebar_state:registry(State1, Registry)
+ ,{Packages, Graph}),
+
+ update_pkg_deps(Profile, Packages, PkgDeps1
+ ,Graph, Upgrade, Seen, State2)
+ end,
AllDeps = lists:ukeymerge(2
,lists:ukeysort(2, SrcApps)
,lists:ukeysort(2, Solved)),
- State3 = rebar_state:update_all_deps(State2, AllDeps),
+ State5 = rebar_state:update_all_deps(State4, AllDeps),
CodePaths = [rebar_app_info:ebin_dir(A) || A <- AllDeps],
- State4 = rebar_state:update_code_paths(State3, all_deps, CodePaths),
+ State6 = rebar_state:update_code_paths(State5, all_deps, CodePaths),
- {ok, AllDeps, State4}.
+ {ok, AllDeps, State6}.
%% ===================================================================
%% Internal functions
diff --git a/test/mock_pkg_resource.erl b/test/mock_pkg_resource.erl
index 615e8a5..560caef 100644
--- a/test/mock_pkg_resource.erl
+++ b/test/mock_pkg_resource.erl
@@ -152,7 +152,7 @@ find_parts([{AppName, Deps}|Rest], Skip, Acc) ->
end.
to_graph_parts(Dict) ->
- LastUpdated = now(),
+ LastUpdated = os:timestamp(),
dict:fold(fun(K,V,{Ks,Vs}) ->
{_,Deps} = lists:keyfind(<<"deps">>, 1, V),
{[{K,LastUpdated}|Ks],
diff --git a/test/rebar_compile_SUITE.erl b/test/rebar_compile_SUITE.erl
index ee262a1..bdab075 100644
--- a/test/rebar_compile_SUITE.erl
+++ b/test/rebar_compile_SUITE.erl
@@ -19,7 +19,8 @@
delete_beam_if_source_deleted/1,
checkout_priority/1,
compile_plugins/1,
- highest_version_of_pkg_dep/1]).
+ highest_version_of_pkg_dep/1,
+ parse_transform_test/1]).
-include_lib("common_test/include/ct.hrl").
-include_lib("eunit/include/eunit.hrl").
@@ -46,7 +47,8 @@ all() ->
build_all_srcdirs, recompile_when_hrl_changes,
recompile_when_opts_change, dont_recompile_when_opts_dont_change,
dont_recompile_yrl_or_xrl, delete_beam_if_source_deleted,
- deps_in_path, checkout_priority, compile_plugins, highest_version_of_pkg_dep].
+ deps_in_path, checkout_priority, compile_plugins, highest_version_of_pkg_dep,
+ parse_transform_test].
build_basic_app(Config) ->
AppDir = ?config(apps, Config),
@@ -449,3 +451,24 @@ highest_version_of_pkg_dep(Config) ->
Config, RConf, ["compile"],
{ok, [{app, Name}, {dep, PkgName, <<"0.1.3">>}]}
).
+
+parse_transform_test(Config) ->
+ AppDir = ?config(apps, Config),
+
+ RebarConfig = [{erl_opts, [{parse_transform, pascal}]}],
+
+ 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]),
+
+ ExtraSrc = <<"-module(pascal). "
+ "-export([parse_transform/2]). "
+ "parse_transform(Forms, _Options) -> "
+ "Forms.">>,
+
+ ok = file:write_file(filename:join([AppDir, "src", "pascal.erl"]), ExtraSrc),
+
+ rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], {ok, [{app, Name}]}),
+
+ EbinDir = filename:join([AppDir, "_build", "default", "lib", Name, "ebin"]),
+ true = filelib:is_file(filename:join([EbinDir, "pascal.beam"])).
diff --git a/test/rebar_test_utils.erl b/test/rebar_test_utils.erl
index f764146..2cdc58b 100644
--- a/test/rebar_test_utils.erl
+++ b/test/rebar_test_utils.erl
@@ -104,12 +104,12 @@ create_config(AppDir, Contents) ->
%% @doc Util to create a random variation of a given name.
create_random_name(Name) ->
- random:seed(erlang:now()),
+ random:seed(os:timestamp()),
Name ++ erlang:integer_to_list(random:uniform(1000000)).
%% @doc Util to create a random variation of a given version.
create_random_vsn() ->
- random:seed(erlang:now()),
+ random:seed(os:timestamp()),
lists:flatten([erlang:integer_to_list(random:uniform(100)),
".", erlang:integer_to_list(random:uniform(100)),
".", erlang:integer_to_list(random:uniform(100))]).