summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoralisdair sullivan <alisdairsullivan@yahoo.ca>2015-10-15 23:32:43 -0700
committeralisdair sullivan <alisdairsullivan@yahoo.ca>2015-10-26 21:57:32 -0700
commitd1409d0b3b2f7fe5c491f866ef983dd7df7d0f42 (patch)
treed9267423c504dd0b61fd189396fa0cebf816ec67
parent621d8a94856df629a94fac7a77b68fd841267510 (diff)
refactor `rebar_erlc_compiler`
* modify compiler interface to work on either application objects or directories containing source files * compile all sources in `src_dirs` to the application `ebin` dir and all sources in `extra_src_dirs` to a directory mirroring it's position in the app's `_build` directory. for example, `apps/foo/more` would compile to `_build/default/lib/foo/more` for `extra_src_dirs` in the root of a project with multiple applications (so orphan directories that don't "belong" to an application) compile to `_build/default/extras/more` * copy directories specified in `extra_src_dirs` into the `_build` directory so tools like `ct` and `xref` that expect source to be in a particular location still work * clean compiled artifacts from all `extra_src_dirs` * alter `eunit`, `ct` and `cover` to work with the new directory structure * billions of new tests
-rw-r--r--rebar.config1
-rw-r--r--src/rebar_erlc_compiler.erl258
-rw-r--r--src/rebar_prv_clean.erl7
-rw-r--r--src/rebar_prv_common_test.erl44
-rw-r--r--src/rebar_prv_compile.erl119
-rw-r--r--src/rebar_prv_cover.erl32
-rw-r--r--src/rebar_prv_eunit.erl167
-rw-r--r--src/rebar_utils.erl9
-rw-r--r--test/rebar_compile_SUITE.erl633
-rw-r--r--test/rebar_cover_SUITE.erl87
-rw-r--r--test/rebar_ct_SUITE.erl1
-rw-r--r--test/rebar_eunit_SUITE.erl18
-rw-r--r--test/rebar_file_utils_SUITE.erl6
-rw-r--r--test/rebar_src_dirs_SUITE.erl21
-rw-r--r--test/rebar_test_utils.erl7
15 files changed, 1107 insertions, 303 deletions
diff --git a/rebar.config b/rebar.config
index deff2cc..6eed68f 100644
--- a/rebar.config
+++ b/rebar.config
@@ -18,6 +18,7 @@
{"rebar/priv/templates/*", "_build/default/lib/"}]}.
{erl_opts, [{platform_define, "^[0-9]+", namespaced_types},
+ {platform_define, "^R1[4|5]", no_list_dir_all},
no_debug_info,
warnings_as_errors]}.
diff --git a/src/rebar_erlc_compiler.erl b/src/rebar_erlc_compiler.erl
index 06d09bd..5075f0f 100644
--- a/src/rebar_erlc_compiler.erl
+++ b/src/rebar_erlc_compiler.erl
@@ -26,8 +26,9 @@
%% -------------------------------------------------------------------
-module(rebar_erlc_compiler).
--export([compile/1,
- compile/3,
+-export([compile/1, compile/2, compile/3,
+ compile_dir/3, compile_dir/4,
+ compile_dirs/5,
clean/1]).
-include("rebar.hrl").
@@ -38,14 +39,22 @@
-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()), list(string())}.
--record(erlcinfo,
- {
- vsn = ?ERLCINFO_VSN :: pos_integer(),
- info = {[], [], []} :: erlc_info()
- }).
+-record(erlcinfo, {
+ vsn = ?ERLCINFO_VSN :: pos_integer(),
+ info = {[], [], []} :: erlc_info()
+}).
+-type compile_opts() :: [compile_opt()].
+-type compile_opt() :: {recursive, boolean()}.
+
+-record(compile_opts, {
+ recursive = true
+}).
+
+-define(DEFAULT_OUTDIR, "ebin").
-define(RE_PREFIX, "^[^._]").
+
%% ===================================================================
%% Public API
%% ===================================================================
@@ -80,106 +89,189 @@
%% 'old_inets'}]}.
%%
--spec compile(rebar_app_info:t()) -> 'ok'.
-compile(AppInfo) ->
+%% @equiv compile(AppInfo, []).
+
+-spec compile(rebar_app_info:t()) -> ok.
+compile(AppInfo) when is_tuple(AppInfo), element(1, AppInfo) == app_info_t ->
+ compile(AppInfo, []).
+
+%% @doc compile an individual application.
+
+-spec compile(rebar_app_info:t(), compile_opts()) -> ok.
+compile(AppInfo, CompileOpts) when is_tuple(AppInfo), element(1, AppInfo) == app_info_t ->
Dir = ec_cnv:to_list(rebar_app_info:out_dir(AppInfo)),
- compile(rebar_app_info:opts(AppInfo), Dir, filename:join([Dir, "ebin"])).
+ RebarOpts = rebar_app_info:opts(AppInfo),
--spec compile(rebar_dict(), file:name(), file:name()) -> 'ok'.
-compile(Opts, Dir, OutDir) ->
- rebar_base_compiler:run(Opts,
+ rebar_base_compiler:run(RebarOpts,
check_files([filename:join(Dir, File)
- || File <- rebar_opts:get(Opts, xrl_first_files, [])]),
+ || File <- rebar_opts:get(RebarOpts, xrl_first_files, [])]),
filename:join(Dir, "src"), ".xrl", filename:join(Dir, "src"), ".erl",
fun compile_xrl/3),
- rebar_base_compiler:run(Opts,
+ rebar_base_compiler:run(RebarOpts,
check_files([filename:join(Dir, File)
- || File <- rebar_opts:get(Opts, yrl_first_files, [])]),
+ || File <- rebar_opts:get(RebarOpts, yrl_first_files, [])]),
filename:join(Dir, "src"), ".yrl", filename:join(Dir, "src"), ".erl",
fun compile_yrl/3),
- rebar_base_compiler:run(Opts,
+ rebar_base_compiler:run(RebarOpts,
check_files([filename:join(Dir, File)
- || File <- rebar_opts:get(Opts, mib_first_files, [])]),
+ || File <- rebar_opts:get(RebarOpts, mib_first_files, [])]),
filename:join(Dir, "mibs"), ".mib", filename:join([Dir, "priv", "mibs"]), ".bin",
fun compile_mib/3),
- doterl_compile(Opts, Dir, OutDir).
--spec clean(file:filename()) -> 'ok'.
-clean(AppDir) ->
- MibFiles = rebar_utils:find_files(filename:join(AppDir, "mibs"), ?RE_PREFIX".*\\.mib\$"),
+ SrcDirs = lists:map(fun(SrcDir) -> filename:join(Dir, SrcDir) end,
+ rebar_dir:src_dirs(RebarOpts, ["src"])),
+ OutDir = filename:join(Dir, outdir(RebarOpts)),
+ compile_dirs(RebarOpts, Dir, SrcDirs, OutDir, CompileOpts),
+
+ ExtraDirs = rebar_dir:extra_src_dirs(RebarOpts),
+ F = fun(D) ->
+ case ec_file:is_dir(filename:join([Dir, D])) of
+ true -> compile_dirs(RebarOpts, Dir, [D], D, CompileOpts);
+ false -> ok
+ end
+ end,
+ lists:foreach(F, lists:map(fun(SrcDir) -> filename:join(Dir, SrcDir) end, ExtraDirs)).
+
+%% @hidden
+%% these are kept for backwards compatibility but they're bad functions with
+%% bad interfaces you probably shouldn't use
+%% State/RebarOpts have to have src_dirs set and BaseDir must be the parent
+%% directory of those src_dirs
+
+-spec compile(rebar_dict() | rebar_state:t(), file:name(), file:name()) -> ok.
+compile(State, BaseDir, OutDir) when is_tuple(State), element(1, State) == state_t ->
+ compile(rebar_state:opts(State), BaseDir, OutDir, [{recursive, false}]);
+compile(RebarOpts, BaseDir, OutDir) ->
+ compile(RebarOpts, BaseDir, OutDir, [{recursive, false}]).
+
+%% @hidden
+
+-spec compile(rebar_dict() | rebar_state:t(), file:name(), file:name(), compile_opts()) -> ok.
+compile(State, BaseDir, OutDir, CompileOpts) when is_tuple(State), element(1, State) == state_t ->
+ compile(rebar_state:opts(State), BaseDir, OutDir, CompileOpts);
+compile(RebarOpts, BaseDir, OutDir, CompileOpts) ->
+ SrcDirs = lists:map(fun(SrcDir) -> filename:join(BaseDir, SrcDir) end,
+ rebar_dir:src_dirs(RebarOpts, ["src"])),
+ compile_dirs(RebarOpts, BaseDir, SrcDirs, OutDir, CompileOpts),
+
+ ExtraDirs = rebar_dir:extra_src_dirs(RebarOpts),
+ F = fun(D) ->
+ case ec_file:is_dir(filename:join([BaseDir, D])) of
+ true -> compile_dirs(RebarOpts, BaseDir, [D], D, CompileOpts);
+ false -> ok
+ end
+ end,
+ lists:foreach(F, lists:map(fun(SrcDir) -> filename:join(BaseDir, SrcDir) end, ExtraDirs)).
+
+%% @equiv compile_dirs(Context, BaseDir, [Dir], Dir, [{recursive, false}]).
+
+-spec compile_dir(rebar_dict() | rebar_state:t(), file:name(), file:name()) -> ok.
+compile_dir(State, BaseDir, Dir) when is_tuple(State), element(1, State) == state_t ->
+ compile_dir(rebar_state:opts(State), BaseDir, Dir, [{recursive, false}]);
+compile_dir(RebarOpts, BaseDir, Dir) ->
+ compile_dir(RebarOpts, BaseDir, Dir, [{recursive, false}]).
+
+%% @equiv compile_dirs(Context, BaseDir, [Dir], Dir, Opts).
+
+-spec compile_dir(rebar_dict() | rebar_state:t(), file:name(), file:name(), compile_opts()) -> ok.
+compile_dir(State, BaseDir, Dir, Opts) when is_tuple(State), element(1, State) == state_t ->
+ compile_dirs(rebar_state:opts(State), BaseDir, [Dir], Dir, Opts);
+compile_dir(RebarOpts, BaseDir, Dir, Opts) ->
+ compile_dirs(RebarOpts, BaseDir, [Dir], Dir, Opts).
+
+%% @doc compile a list of directories with the given opts.
+
+-spec compile_dirs(rebar_dict() | rebar_state:t(),
+ file:filename(),
+ [file:filename()],
+ file:filename(),
+ compile_opts()) -> ok.
+compile_dirs(State, BaseDir, Dirs, OutDir, CompileOpts) when is_tuple(State), element(1, State) == state_t ->
+ compile_dirs(rebar_state:opts(State), BaseDir, Dirs, OutDir, CompileOpts);
+compile_dirs(RebarOpts, BaseDir, SrcDirs, OutDir, Opts) ->
+ CompileOpts = parse_opts(Opts),
+
+ ErlOpts = rebar_opts:erl_opts(RebarOpts),
+ Recursive = CompileOpts#compile_opts.recursive,
+ AllErlFiles = gather_src(SrcDirs, Recursive),
+
+ %% Make sure that outdir is on the path
+ ok = filelib:ensure_dir(filename:join(OutDir, "dummy.beam")),
+ true = code:add_patha(filename:absname(OutDir)),
+
+ G = init_erlcinfo(proplists:get_all_values(i, ErlOpts), AllErlFiles, BaseDir, OutDir),
+
+ NeededErlFiles = needed_files(G, ErlOpts, BaseDir, OutDir, AllErlFiles),
+ {ErlFirstFiles, ErlOptsFirst} = erl_first_files(RebarOpts, ErlOpts, BaseDir, NeededErlFiles),
+ {DepErls, OtherErls} = lists:partition(
+ fun(Source) -> digraph:in_degree(G, Source) > 0 end,
+ [File || File <- NeededErlFiles, not lists:member(File, ErlFirstFiles)]),
+ SubGraph = digraph_utils:subgraph(G, DepErls),
+ DepErlsOrdered = digraph_utils:topsort(SubGraph),
+ FirstErls = ErlFirstFiles ++ lists:reverse(DepErlsOrdered),
+ try
+ rebar_base_compiler:run(
+ RebarOpts, FirstErls, OtherErls,
+ fun(S, C) ->
+ ErlOpts1 = case lists:member(S, ErlFirstFiles) of
+ true -> ErlOptsFirst;
+ false -> ErlOpts
+ end,
+ internal_erl_compile(C, BaseDir, S, OutDir, ErlOpts1)
+ end)
+ after
+ true = digraph:delete(SubGraph),
+ true = digraph:delete(G)
+ end,
+ ok.
+
+%% @doc remove compiled artifacts from an AppDir.
+
+-spec clean(rebar_app_info:t()) -> 'ok'.
+clean(AppInfo) ->
+ AppDir = rebar_app_info:out_dir(AppInfo),
+
+ MibFiles = rebar_utils:find_files(filename:join([AppDir, "mibs"]), ?RE_PREFIX".*\\.mib\$"),
MIBs = [filename:rootname(filename:basename(MIB)) || MIB <- MibFiles],
rebar_file_utils:delete_each(
[filename:join([AppDir, "include",MIB++".hrl"]) || MIB <- MIBs]),
- lists:foreach(fun(F) -> ok = rebar_file_utils:rm_rf(F) end,
- [filename:join(AppDir, "ebin/*.beam"), filename:join(AppDir, "priv/mibs/*.bin")]),
+ ok = rebar_file_utils:rm_rf(filename:join([AppDir, "priv/mibs/*.bin"])),
- YrlFiles = rebar_utils:find_files(filename:join(AppDir, "src"), ?RE_PREFIX".*\\.[x|y]rl\$"),
+ YrlFiles = rebar_utils:find_files(filename:join([AppDir, "src"]), ?RE_PREFIX".*\\.[x|y]rl\$"),
rebar_file_utils:delete_each(
[ binary_to_list(iolist_to_binary(re:replace(F, "\\.[x|y]rl$", ".erl")))
|| F <- YrlFiles ]),
+ BinDirs = ["ebin"|rebar_dir:extra_src_dirs(rebar_app_info:opts(AppInfo))],
+ ok = clean_dirs(AppDir, BinDirs),
+
%% Delete the build graph, if any
- rebar_file_utils:rm_rf(erlcinfo_file(AppDir)),
+ rebar_file_utils:rm_rf(erlcinfo_file(AppDir)).
+clean_dirs(_AppDir, []) -> ok;
+clean_dirs(AppDir, [Dir|Rest]) ->
+ ok = rebar_file_utils:rm_rf(filename:join([AppDir, Dir, "*.beam"])),
%% Erlang compilation is recursive, so it's possible that we have a nested
%% directory structure in ebin with .beam files within. As such, we want
- %% to scan whatever is left in the ebin/ directory for sub-dirs which
+ %% to scan whatever is left in the app's out_dir directory for sub-dirs which
%% satisfy our criteria.
- BeamFiles = rebar_utils:find_files(filename:join(AppDir, "ebin"), ?RE_PREFIX".*\\.beam\$"),
+ BeamFiles = rebar_utils:find_files(filename:join([AppDir, Dir]), ?RE_PREFIX".*\\.beam\$"),
rebar_file_utils:delete_each(BeamFiles),
- lists:foreach(fun(Dir) -> delete_dir(Dir, dirs(Dir)) end, dirs(filename:join(AppDir, "ebin"))),
- ok.
+ lists:foreach(fun(D) -> delete_dir(D, dirs(D)) end, dirs(filename:join([AppDir, Dir]))),
+ clean_dirs(AppDir, Rest).
+
%% ===================================================================
%% Internal functions
%% ===================================================================
--spec doterl_compile(rebar_dict(), file:filename(), file:filename()) -> ok.
-doterl_compile(Opts, Dir, ODir) ->
- ErlOpts = rebar_opts:erl_opts(Opts),
- doterl_compile(Opts, Dir, ODir, [], ErlOpts).
-
-doterl_compile(Opts, Dir, OutDir, MoreSources, ErlOpts) ->
- ?DEBUG("erl_opts ~p", [ErlOpts]),
- %% Support the src_dirs option allowing multiple directories to
- %% contain erlang source. This might be used, for example, should
- %% eunit tests be separated from the core application source.
- SrcDirs = [filename:join(Dir, X) || X <- rebar_dir:all_src_dirs(Opts, ["src"], [])],
- AllErlFiles = gather_src(SrcDirs, []) ++ MoreSources,
-
- %% Make sure that ebin/ exists and is on the path
- ok = filelib:ensure_dir(filename:join(OutDir, "dummy.beam")),
- true = code:add_patha(filename:absname(OutDir)),
-
- OutDir1 = proplists:get_value(outdir, ErlOpts, OutDir),
-
- G = init_erlcinfo(proplists:get_all_values(i, ErlOpts), AllErlFiles, Dir, OutDir),
-
- NeededErlFiles = needed_files(G, ErlOpts, Dir, OutDir1, AllErlFiles),
- {ErlFirstFiles, ErlOptsFirst} = erl_first_files(Opts, ErlOpts, Dir, NeededErlFiles),
- {DepErls, OtherErls} = lists:partition(
- fun(Source) -> digraph:in_degree(G, Source) > 0 end,
- [File || File <- NeededErlFiles, not lists:member(File, ErlFirstFiles)]),
- SubGraph = digraph_utils:subgraph(G, DepErls),
- DepErlsOrdered = digraph_utils:topsort(SubGraph),
- FirstErls = ErlFirstFiles ++ lists:reverse(DepErlsOrdered),
- ?DEBUG("Files to compile first: ~p", [FirstErls]),
- try
- rebar_base_compiler:run(
- Opts, FirstErls, OtherErls,
- fun(S, C) ->
- ErlOpts1 = case lists:member(S, ErlFirstFiles) of
- true -> ErlOptsFirst;
- false -> ErlOpts
- end,
- internal_erl_compile(C, Dir, S, OutDir1, ErlOpts1)
- end)
- after
- true = digraph:delete(SubGraph),
- true = digraph:delete(G)
- end,
- ok.
+gather_src(Dirs, Recursive) ->
+ gather_src(Dirs, [], Recursive).
+gather_src([], Srcs, _Recursive) -> Srcs;
+gather_src([Dir|Rest], Srcs, Recursive) ->
+ gather_src(Rest, Srcs ++ rebar_utils:find_files(Dir, ?RE_PREFIX".*\\.erl\$", Recursive), Recursive).
+
%% 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.
@@ -487,11 +579,7 @@ compile_xrl_yrl(_Opts, Source, Target, AllOpts, Mod) ->
needs_compile(Source, Target) ->
filelib:last_modified(Source) > filelib:last_modified(Target).
-gather_src([], Srcs) ->
- Srcs;
-gather_src([Dir|Rest], Srcs) ->
- gather_src(
- Rest, Srcs ++ rebar_utils:find_files(Dir, ?RE_PREFIX".*\\.erl\$")).
+
-spec dirs(file:filename()) -> [file:filename()].
dirs(Dir) ->
@@ -620,3 +708,13 @@ check_file(File) ->
false -> ?ABORT("File ~p is missing, aborting\n", [File]);
true -> File
end.
+
+outdir(RebarOpts) ->
+ ErlOpts = rebar_opts:erl_opts(RebarOpts),
+ proplists:get_value(outdir, ErlOpts, ?DEFAULT_OUTDIR).
+
+parse_opts(Opts) -> parse_opts(Opts, #compile_opts{}).
+
+parse_opts([], CompileOpts) -> CompileOpts;
+parse_opts([{recursive, Recursive}|Rest], CompileOpts) when Recursive == true; Recursive == false ->
+ parse_opts(Rest, CompileOpts#compile_opts{recursive = Recursive}).
diff --git a/src/rebar_prv_clean.erl b/src/rebar_prv_clean.erl
index a2b537a..6694dc0 100644
--- a/src/rebar_prv_clean.erl
+++ b/src/rebar_prv_clean.erl
@@ -49,6 +49,7 @@ do(State) ->
Cwd = rebar_dir:get_cwd(),
rebar_hooks:run_all_hooks(Cwd, pre, ?PROVIDER, Providers, State),
clean_apps(State, Providers, ProjectApps),
+ clean_extras(State),
rebar_hooks:run_all_hooks(Cwd, post, ?PROVIDER, Providers, State),
{ok, State}.
@@ -66,10 +67,14 @@ clean_apps(State, Providers, Apps) ->
?INFO("Cleaning out ~s...", [rebar_app_info:name(AppInfo)]),
AppDir = rebar_app_info:dir(AppInfo),
AppInfo1 = rebar_hooks:run_all_hooks(AppDir, pre, ?PROVIDER, Providers, AppInfo, State),
- rebar_erlc_compiler:clean(rebar_app_info:out_dir(AppInfo1)),
+ rebar_erlc_compiler:clean(AppInfo1),
rebar_hooks:run_all_hooks(AppDir, post, ?PROVIDER, Providers, AppInfo1, State)
end || AppInfo <- Apps].
+clean_extras(State) ->
+ BaseDir = rebar_dir:base_dir(State),
+ rebar_file_utils:rm_rf(filename:join([BaseDir, "extras"])).
+
handle_args(State) ->
{Args, _} = rebar_state:command_parsed_args(State),
All = proplists:get_value(all, Args, false),
diff --git a/src/rebar_prv_common_test.erl b/src/rebar_prv_common_test.erl
index 9155d3b..1f4c02d 100644
--- a/src/rebar_prv_common_test.erl
+++ b/src/rebar_prv_common_test.erl
@@ -285,26 +285,7 @@ find_suite_dirs(Suites) ->
copy(State, Dir) ->
From = reduce_path(Dir),
- case From == rebar_state:dir(State) of
- true -> throw({error, suite_at_project_root});
- false -> ok
- end,
- case retarget_path(State, From) of
- %% directory lies outside of our project's file structure so
- %% don't copy it
- From -> From;
- Target ->
- %% recursively delete any symlinks in the target directory
- %% if it exists so we don't smash files in the linked dirs
- case ec_file:is_dir(Target) of
- true -> remove_links(Target);
- false -> ok
- end,
- case rebar_file_utils:symlink_or_copy(From, Target) of
- exists -> Target;
- ok -> Target
- end
- end.
+ retarget_path(State, From).
compile_dir(State, Dir) ->
NewState = replace_src_dirs(State, [filename:absname(Dir)]),
@@ -350,29 +331,6 @@ reduce_path([_|Acc], [".."|Rest]) -> reduce_path(Acc, Rest);
reduce_path([], [".."|Rest]) -> reduce_path([], Rest);
reduce_path(Acc, [Component|Rest]) -> reduce_path([Component|Acc], Rest).
-
-remove_links(Path) ->
- IsDir = ec_file:is_dir(Path),
- case ec_file:is_symlink(Path) of
- true when IsDir ->
- delete_dir_link(Path);
- false when IsDir ->
- lists:foreach(fun(ChildPath) ->
- remove_links(ChildPath)
- end, dir_entries(Path));
- _ -> file:delete(Path)
- end.
-
-delete_dir_link(Path) ->
- case os:type() of
- {unix, _} -> file:delete(Path);
- {win32, _} -> file:del_dir(Path)
- end.
-
-dir_entries(Path) ->
- {ok, SubDirs} = file:list_dir(Path),
- [filename:join(Path, SubDir) || SubDir <- SubDirs].
-
replace_src_dirs(State, Dirs) ->
%% replace any `src_dirs` with the test dirs
ErlOpts = rebar_state:get(State, erl_opts, []),
diff --git a/src/rebar_prv_compile.erl b/src/rebar_prv_compile.erl
index 9811de9..2996aee 100644
--- a/src/rebar_prv_compile.erl
+++ b/src/rebar_prv_compile.erl
@@ -52,8 +52,10 @@ do(State) ->
ProjectApps2 = build_apps(State, Providers, ProjectApps1),
State2 = rebar_state:project_apps(State, ProjectApps2),
- ProjAppsPaths = [filename:join(rebar_app_info:out_dir(X), "ebin") || X <- ProjectApps2],
- State3 = rebar_state:code_paths(State2, all_deps, DepsPaths ++ ProjAppsPaths),
+ %% projects with structures like /apps/foo,/apps/bar,/test
+ build_extra_dirs(State, ProjectApps2),
+
+ State3 = update_code_paths(State2, ProjectApps2, DepsPaths),
rebar_hooks:run_all_hooks(Cwd, post, ?PROVIDER, Providers, State2),
case rebar_state:has_all_artifacts(State3) of
@@ -82,6 +84,30 @@ build_app(State, Providers, AppInfo) ->
copy_app_dirs(AppInfo, AppDir, OutDir),
compile(State, Providers, AppInfo).
+build_extra_dirs(State, Apps) ->
+ BaseDir = rebar_state:dir(State),
+ F = fun(App) -> rebar_app_info:dir(App) == BaseDir end,
+ %% check that this app hasn't already been dealt with
+ case lists:any(F, Apps) of
+ false ->
+ ProjOpts = rebar_state:opts(State),
+ Extras = rebar_dir:extra_src_dirs(ProjOpts, []),
+ [build_extra_dir(State, Dir) || Dir <- Extras];
+ true -> ok
+ end.
+
+build_extra_dir(_State, []) -> ok;
+build_extra_dir(State, Dir) ->
+ case ec_file:is_dir(filename:join([rebar_state:dir(State), Dir])) of
+ true ->
+ BaseDir = filename:join([rebar_dir:base_dir(State), "extras"]),
+ OutDir = filename:join([BaseDir, Dir]),
+ filelib:ensure_dir(filename:join([OutDir, "dummy.beam"])),
+ copy(rebar_state:dir(State), BaseDir, Dir),
+ rebar_erlc_compiler:compile_dir(State, BaseDir, OutDir);
+ false -> ok
+ end.
+
compile(State, AppInfo) ->
compile(State, rebar_state:providers(State), AppInfo).
@@ -104,6 +130,33 @@ compile(State, Providers, AppInfo) ->
%% Internal functions
%% ===================================================================
+update_code_paths(State, ProjectApps, DepsPaths) ->
+ ProjAppsPaths = paths_for_apps(ProjectApps),
+ ExtrasPaths = paths_for_extras(State, ProjectApps),
+ rebar_state:code_paths(State, all_deps, DepsPaths ++ ProjAppsPaths ++ ExtrasPaths).
+
+paths_for_apps(Apps) -> paths_for_apps(Apps, []).
+
+paths_for_apps([], Acc) -> Acc;
+paths_for_apps([App|Rest], Acc) ->
+ {_SrcDirs, ExtraDirs} = resolve_src_dirs(rebar_app_info:opts(App)),
+ Paths = [filename:join([rebar_app_info:out_dir(App), Dir]) || Dir <- ["ebin"|ExtraDirs]],
+ FilteredPaths = lists:filter(fun ec_file:is_dir/1, Paths),
+ paths_for_apps(Rest, Acc ++ FilteredPaths).
+
+paths_for_extras(State, Apps) ->
+ F = fun(App) -> rebar_app_info:dir(App) == rebar_state:dir(State) end,
+ %% check that this app hasn't already been dealt with
+ case lists:any(F, Apps) of
+ false -> paths_for_extras(State);
+ true -> []
+ end.
+
+paths_for_extras(State) ->
+ {_SrcDirs, ExtraDirs} = resolve_src_dirs(rebar_state:opts(State)),
+ Paths = [filename:join([rebar_dir:base_dir(State), "extras", Dir]) || Dir <- ExtraDirs],
+ lists:filter(fun ec_file:is_dir/1, Paths).
+
has_all_artifacts(AppInfo1) ->
case rebar_app_info:has_all_artifacts(AppInfo1) of
{false, File} ->
@@ -120,17 +173,17 @@ copy_app_dirs(AppInfo, OldAppDir, AppDir) ->
%% copy all files from ebin if it exists
case filelib:is_dir(EbinDir) of
true ->
- OutEbin = filename:join(AppDir, "ebin"),
- filelib:ensure_dir(filename:join(OutEbin, "dummy.beam")),
- rebar_file_utils:cp_r(filelib:wildcard(filename:join(EbinDir, "*")), OutEbin);
+ OutEbin = filename:join([AppDir, "ebin"]),
+ filelib:ensure_dir(filename:join([OutEbin, "dummy.beam"])),
+ rebar_file_utils:cp_r(filelib:wildcard(filename:join([EbinDir, "*"])), OutEbin);
false ->
ok
end,
- filelib:ensure_dir(filename:join(AppDir, "dummy")),
+ filelib:ensure_dir(filename:join([AppDir, "dummy"])),
%% link or copy mibs if it exists
- case filelib:is_dir(filename:join(OldAppDir, "mibs")) of
+ case filelib:is_dir(filename:join([OldAppDir, "mibs"])) of
true ->
%% If mibs exist it means we must ensure priv exists.
%% mibs files are compiled to priv/mibs/
@@ -139,15 +192,57 @@ copy_app_dirs(AppInfo, OldAppDir, AppDir) ->
false ->
ok
end,
-
+ {SrcDirs, ExtraDirs} = resolve_src_dirs(rebar_app_info:opts(AppInfo)),
%% link to src_dirs to be adjacent to ebin is needed for R15 use of cover/xref
- SrcDirs = rebar_dir:all_src_dirs(rebar_app_info:opts(AppInfo), ["src"], []),
- [symlink_or_copy(OldAppDir, AppDir, Dir) || Dir <- ["priv", "include"] ++ SrcDirs];
+ [symlink_or_copy(OldAppDir, AppDir, Dir) || Dir <- ["priv", "include"] ++ SrcDirs],
+ %% copy all extra_src_dirs as they build into themselves and linking means they
+ %% are shared across profiles
+ [copy(OldAppDir, AppDir, Dir) || Dir <- ExtraDirs];
false ->
ok
end.
symlink_or_copy(OldAppDir, AppDir, Dir) ->
- Source = filename:join(OldAppDir, Dir),
- Target = filename:join(AppDir, Dir),
+ Source = filename:join([OldAppDir, Dir]),
+ Target = filename:join([AppDir, Dir]),
rebar_file_utils:symlink_or_copy(Source, Target).
+
+copy(OldAppDir, AppDir, Dir) ->
+ Source = filename:join([OldAppDir, Dir]),
+ Target = filename:join([AppDir, Dir]),
+ case ec_file:is_dir(Source) of
+ true -> copy(Source, Target);
+ false -> ok
+ end.
+
+%% TODO: use ec_file:copy/2 to do this, it preserves timestamps and
+%% may prevent recompilation of files in extra dirs
+copy(Source, Target) ->
+ %% important to do this so no files are copied onto themselves
+ %% which truncates them to zero length on some platforms
+ ok = delete_if_symlink(Target),
+ ok = filelib:ensure_dir(filename:join([Target, "dummy.beam"])),
+ {ok, Files} = rebar_utils:list_dir(Source),
+ case [filename:join([Source, F]) || F <- Files] of
+ [] -> ok;
+ Paths -> rebar_file_utils:cp_r(Paths, Target)
+ end.
+
+delete_if_symlink(Path) ->
+ case ec_file:is_symlink(Path) of
+ true -> file:delete(Path);
+ false -> ok
+ end.
+
+resolve_src_dirs(Opts) ->
+ SrcDirs = rebar_dir:src_dirs(Opts, ["src"]),
+ ExtraDirs = rebar_dir:extra_src_dirs(Opts, []),
+ normalize_src_dirs(SrcDirs, ExtraDirs).
+
+%% remove duplicates and make sure no directories that exist
+%% in src_dirs also exist in extra_src_dirs
+normalize_src_dirs(SrcDirs, ExtraDirs) ->
+ S = lists:usort(SrcDirs),
+ E = lists:usort(ExtraDirs),
+ {S, lists:subtract(E, S)}.
+
diff --git a/src/rebar_prv_cover.erl b/src/rebar_prv_cover.erl
index fc7457e..0b9b9bb 100644
--- a/src/rebar_prv_cover.erl
+++ b/src/rebar_prv_cover.erl
@@ -103,7 +103,7 @@ analyze(State) ->
get_all_coverdata(CoverDir) ->
ok = filelib:ensure_dir(filename:join([CoverDir, "dummy.log"])),
- {ok, Files} = file:list_dir(CoverDir),
+ {ok, Files} = rebar_utils:list_dir(CoverDir),
rebar_utils:filtermap(fun(FileName) ->
case filename:extension(FileName) == ".coverdata" of
true -> {true, filename:join([CoverDir, FileName])};
@@ -277,8 +277,9 @@ strip_coverdir(File) ->
cover_compile(State, apps) ->
Apps = filter_checkouts(rebar_state:project_apps(State)),
- AppDirs = app_ebin_dirs(Apps, []),
- cover_compile(State, AppDirs);
+ AppDirs = app_dirs(Apps),
+ ExtraDirs = extra_src_dirs(State, Apps),
+ cover_compile(State, AppDirs ++ ExtraDirs);
cover_compile(State, Dirs) ->
%% start the cover server if necessary
{ok, CoverPid} = start_cover(),
@@ -290,9 +291,30 @@ cover_compile(State, Dirs) ->
compile([], Acc) -> lists:reverse(Acc);
compile([Dir|Rest], Acc) ->
+ ?INFO("covering ~p", [Dir]),
Result = cover:compile_beam_directory(Dir),
compile(Rest, [Result|Acc]).
+app_dirs(Apps) ->
+ lists:foldl(fun app_ebin_dirs/2, [], Apps).
+
+app_ebin_dirs(App, Acc) ->
+ AppDir = rebar_app_info:ebin_dir(App),
+ ExtraDirs = rebar_dir:extra_src_dirs(rebar_app_info:opts(App), []),
+ OutDir = rebar_app_info:out_dir(App),
+ [filename:join([OutDir, D]) || D <- [AppDir|ExtraDirs]] ++ Acc.
+
+extra_src_dirs(State, Apps) ->
+ BaseDir = rebar_state:dir(State),
+ F = fun(App) -> rebar_app_info:dir(App) == BaseDir end,
+ %% check that this app hasn't already been dealt with
+ Extras = case lists:any(F, Apps) of
+ false -> rebar_dir:extra_src_dirs(rebar_state:opts(State), []);
+ true -> []
+ end,
+ OutDir = rebar_dir:base_dir(State),
+ [filename:join([OutDir, "extras", D]) || D <- Extras].
+
filter_checkouts(Apps) -> filter_checkouts(Apps, []).
filter_checkouts([], Acc) -> lists:reverse(Acc);
@@ -302,10 +324,6 @@ filter_checkouts([App|Rest], Acc) ->
false -> filter_checkouts(Rest, [App|Acc])
end.
-app_ebin_dirs([], Acc) -> Acc;
-app_ebin_dirs([App|Rest], Acc) ->
- app_ebin_dirs(Rest, [rebar_app_info:ebin_dir(App)|Acc]).
-
start_cover() ->
case cover:start() of
{ok, Pid} -> {ok, Pid};
diff --git a/src/rebar_prv_eunit.erl b/src/rebar_prv_eunit.erl
index 959be3f..71a1063 100644
--- a/src/rebar_prv_eunit.erl
+++ b/src/rebar_prv_eunit.erl
@@ -9,7 +9,7 @@
do/1,
format_error/1]).
%% exported solely for tests
--export([compile/1, prepare_tests/1, eunit_opts/1]).
+-export([compile/2, prepare_tests/1, eunit_opts/1]).
-include("rebar.hrl").
-include_lib("providers/include/providers.hrl").
@@ -39,14 +39,15 @@ init(State) ->
-spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}.
do(State) ->
- case compile(State) of
+ Tests = prepare_tests(State),
+ case compile(State, Tests) of
%% successfully compiled apps
- {ok, S} -> do_tests(S);
+ {ok, S} -> do(S, Tests);
%% this should look like a compiler error, not an eunit error
Error -> Error
end.
-do_tests(State) ->
+do(State, Tests) ->
?INFO("Performing EUnit tests...", []),
rebar_utils:update_code(rebar_state:code_paths(State, all_deps)),
@@ -56,9 +57,9 @@ do_tests(State) ->
Cwd = rebar_dir:get_cwd(),
rebar_hooks:run_all_hooks(Cwd, pre, ?PROVIDER, Providers, State),
- case prepare_tests(State) of
- {ok, Tests} ->
- case do_tests(State, Tests) of
+ case Tests of
+ {ok, T} ->
+ case run_tests(State, T) of
{ok, State1} ->
%% Run eunit provider posthooks
rebar_hooks:run_all_hooks(Cwd, post, ?PROVIDER, Providers, State1),
@@ -73,11 +74,12 @@ do_tests(State) ->
Error
end.
-do_tests(State, Tests) ->
+run_tests(State, Tests) ->
+ T = translate_paths(State, Tests),
EUnitOpts = resolve_eunit_opts(State),
- ?DEBUG("eunit_tests ~p", [Tests]),
- ?DEBUG("eunit_opts ~p", [EUnitOpts]),
- Result = eunit:test(Tests, EUnitOpts),
+ ?INFO("eunit_tests ~p", [T]),
+ ?INFO("eunit_opts ~p", [EUnitOpts]),
+ Result = eunit:test(T, EUnitOpts),
ok = maybe_write_coverdata(State),
case handle_results(Result) of
{error, Reason} ->
@@ -114,38 +116,80 @@ safe_define_test_macro(Opts) ->
false -> [{d, 'TEST'}] ++ Opts
end.
-compile(State) ->
- %% inject `eunit_first_files` and `eunit_compile_opts` into the applications to be compiled
- NewState = inject_eunit_state(State),
+compile(State, {ok, Tests}) ->
+ %% inject `eunit_first_files`, `eunit_compile_opts` and any
+ %% directories required by tests into the applications
+ NewState = inject_eunit_state(State, Tests),
case rebar_prv_compile:do(NewState) of
%% successfully compiled apps
{ok, S} ->
ok = maybe_cover_compile(S),
- ok = maybe_compile_bare_testdir(S),
{ok, S};
%% this should look like a compiler error, not an eunit error
Error -> Error
- end.
+ end;
+%% maybe compile even in the face of errors?
+compile(_State, Error) -> Error.
-inject_eunit_state(State) ->
+inject_eunit_state(State, Tests) ->
Apps = project_apps(State),
- ModdedApps = lists:map(fun(App) -> inject(State, App) end, Apps),
- rebar_state:project_apps(State, ModdedApps).
-
-inject(State, App) ->
+ ModdedApps = lists:map(fun(App) ->
+ NewOpts = inject(rebar_app_info:opts(App), State),
+ rebar_app_info:opts(App, NewOpts)
+ end, Apps),
+ NewOpts = inject(rebar_state:opts(State), State),
+ NewState = rebar_state:opts(State, NewOpts),
+ test_dirs(NewState, ModdedApps, Tests).
+
+inject(Opts, State) ->
%% append `eunit_compile_opts` to app defined `erl_opts`
- ErlOpts = rebar_app_info:get(App, erl_opts, []),
+ ErlOpts = rebar_opts:get(Opts, erl_opts, []),
EUnitOpts = rebar_state:get(State, eunit_compile_opts, []),
- NewOpts = EUnitOpts ++ ErlOpts,
+ NewErlOpts = EUnitOpts ++ ErlOpts,
%% append `eunit_first_files` to app defined `erl_first_files`
- FirstFiles = rebar_app_info:get(App, erl_first_files, []),
+ FirstFiles = rebar_opts:get(Opts, erl_first_files, []),
EUnitFirstFiles = rebar_state:get(State, eunit_first_files, []),
NewFirstFiles = EUnitFirstFiles ++ FirstFiles,
- %% insert the new keys into the app
- lists:foldl(fun({K, V}, NewApp) -> rebar_app_info:set(NewApp, K, V) end,
- App,
- [{erl_opts, NewOpts}, {erl_first_files, NewFirstFiles}]).
+ %% insert the new keys into the opts
+ lists:foldl(fun({K, V}, NewOpts) -> rebar_opts:set(NewOpts, K, V) end,
+ Opts,
+ [{erl_opts, NewErlOpts}, {erl_first_files, NewFirstFiles}]).
+
+test_dirs(State, Apps, []) -> rebar_state:project_apps(State, Apps);
+test_dirs(State, Apps, [{dir, Dir}|Rest]) ->
+ %% insert `Dir` into an app if relative, or the base state if not
+ %% app relative but relative to the root or not at all if outside
+ %% project scope
+ {NewState, NewApps} = maybe_inject_test_dir(State, [], Apps, Dir),
+ test_dirs(NewState, NewApps, Rest);
+test_dirs(State, Apps, [{file, File}|Rest]) ->
+ Dir = filename:dirname(File),
+ {NewState, NewApps} = maybe_inject_test_dir(State, [], Apps, Dir),
+ test_dirs(NewState, NewApps, Rest);
+test_dirs(State, Apps, [_|Rest]) -> test_dirs(State, Apps, Rest).
+
+maybe_inject_test_dir(State, AppAcc, [App|Rest], Dir) ->
+ case rebar_file_utils:path_from_ancestor(Dir, rebar_app_info:dir(App)) of
+ {ok, Path} ->
+ Opts = inject_test_dir(rebar_app_info:opts(App), Path),
+ {State, AppAcc ++ [rebar_app_info:opts(App, Opts)] ++ Rest};
+ {error, badparent} ->
+ maybe_inject_test_dir(State, AppAcc ++ [App], Rest, Dir)
+ end;
+maybe_inject_test_dir(State, AppAcc, [], Dir) ->
+ case rebar_file_utils:path_from_ancestor(Dir, rebar_state:dir(State)) of
+ {ok, Path} ->
+ Opts = inject_test_dir(rebar_state:opts(State), Path),
+ {rebar_state:opts(State, Opts), AppAcc};
+ {error, badparent} ->
+ {State, AppAcc}
+ end.
+
+inject_test_dir(Opts, Dir) ->
+ %% append specified test targets to app defined `extra_src_dirs`
+ ExtraSrcDirs = rebar_opts:get(Opts, extra_src_dirs, []),
+ rebar_opts:set(Opts, extra_src_dirs, ExtraSrcDirs ++ [Dir]).
test_defined([{d, 'TEST'}|_]) -> true;
test_defined([{d, 'TEST', true}|_]) -> true;
@@ -212,7 +256,7 @@ default_tests(State, Apps) ->
%% included or `test` does not exist
false -> lists:reverse(Tests);
%% need to add `test` dir at root to dirs to be included
- true -> lists:reverse([{dir, filename:join([rebar_dir:base_dir(State), "test"])}|Tests])
+ true -> lists:reverse([{dir, BareTest}|Tests])
end.
set_apps([], Acc) -> Acc;
@@ -268,14 +312,14 @@ validate_app(State, [App|Rest], AppName) ->
false -> validate_app(State, Rest, AppName)
end.
-validate_dir(_State, Dir) ->
- case ec_file:is_dir(Dir) of
+validate_dir(State, Dir) ->
+ case ec_file:is_dir(filename:join([rebar_state:dir(State), Dir])) of
true -> ok;
false -> {error, lists:concat(["Directory `", Dir, "' not found."])}
end.
-validate_file(_State, File) ->
- case ec_file:exists(File) of
+validate_file(State, File) ->
+ case ec_file:exists(filename:join([rebar_state:dir(State), File])) of
true -> ok;
false -> {error, lists:concat(["File `", File, "' not found."])}
end.
@@ -302,6 +346,31 @@ set_verbose(Opts) ->
false -> [verbose] ++ Opts
end.
+translate_paths(State, Tests) -> translate_paths(State, Tests, []).
+
+translate_paths(_State, [], Acc) -> lists:reverse(Acc);
+translate_paths(State, [{dir, Dir}|Rest], Acc) ->
+ Apps = project_apps(State),
+ translate_paths(State, Rest, [translate(State, Apps, Dir)|Acc]);
+translate_paths(State, [{file, File}|Rest], Acc) ->
+ Dir = filename:dirname(File),
+ Apps = project_apps(State),
+ translate_paths(State, Rest, [translate(State, Apps, Dir)|Acc]);
+translate_paths(State, [Test|Rest], Acc) ->
+ translate_paths(State, Rest, [Test|Acc]).
+
+translate(State, [App|Rest], Dir) ->
+ case rebar_file_utils:path_from_ancestor(Dir, rebar_app_info:dir(App)) of
+ {ok, Path} -> {dir, filename:join([rebar_app_info:out_dir(App), Path])};
+ {error, badparent} -> translate(State, Rest, Dir)
+ end;
+translate(State, [], Dir) ->
+ case rebar_file_utils:path_from_ancestor(Dir, rebar_state:dir(State)) of
+ {ok, Path} -> {dir, filename:join([rebar_dir:base_dir(State), "extras", Path])};
+ %% not relative, leave as is
+ {error, badparent} -> {dir, Dir}
+ end.
+
maybe_cover_compile(State) ->
{RawOpts, _} = rebar_state:command_parsed_args(State),
State1 = case proplists:get_value(cover, RawOpts, false) of
@@ -310,14 +379,6 @@ maybe_cover_compile(State) ->
end,
rebar_prv_cover:maybe_cover_compile(State1).
-maybe_cover_compile(State, Dir) ->
- {RawOpts, _} = rebar_state:command_parsed_args(State),
- State1 = case proplists:get_value(cover, RawOpts, false) of
- true -> rebar_state:set(State, cover_enabled, true);
- false -> State
- end,
- rebar_prv_cover:maybe_cover_compile(State1, [Dir]).
-
maybe_write_coverdata(State) ->
{RawOpts, _} = rebar_state:command_parsed_args(State),
State1 = case proplists:get_value(cover, RawOpts, false) of
@@ -326,30 +387,6 @@ maybe_write_coverdata(State) ->
end,
rebar_prv_cover:maybe_write_coverdata(State1, ?PROVIDER).
-maybe_compile_bare_testdir(State) ->
- Apps = project_apps(State),
- BareTest = filename:join([rebar_state:dir(State), "test"]),
- F = fun(App) -> rebar_app_info:dir(App) == rebar_state:dir(State) end,
- case ec_file:is_dir(BareTest) andalso not lists:any(F, Apps) of
- true ->
- ErlOpts = rebar_state:get(State, erl_opts, []),
- EUnitOpts = rebar_state:get(State, eunit_compile_opts, []),
- NewErlOpts = safe_define_test_macro(EUnitOpts ++ ErlOpts),
- %% append `eunit_first_files` to app defined `erl_first_files`
- FirstFiles = rebar_state:get(State, erl_first_files, []),
- EUnitFirstFiles = rebar_state:get(State, eunit_first_files, []),
- NewFirstFiles = EUnitFirstFiles ++ FirstFiles,
- Opts = rebar_state:opts(State),
- NewOpts = lists:foldl(fun({K, V}, Dict) -> rebar_opts:set(Dict, K, V) end,
- Opts,
- [{erl_opts, NewErlOpts}, {erl_first_files, NewFirstFiles}, {src_dirs, ["test"]}]),
- OutDir = filename:join([rebar_dir:base_dir(State), "test"]),
- filelib:ensure_dir(filename:join([OutDir, "dummy.beam"])),
- rebar_erlc_compiler:compile(NewOpts, rebar_state:dir(State), OutDir),
- maybe_cover_compile(State, [OutDir]);
- false -> ok
- end.
-
handle_results(ok) -> ok;
handle_results(error) ->
{error, unknown_error};
diff --git a/src/rebar_utils.erl b/src/rebar_utils.erl
index ccdf960..4fd4bd1 100644
--- a/src/rebar_utils.erl
+++ b/src/rebar_utils.erl
@@ -65,7 +65,8 @@
escape_double_quotes_weak/1,
check_min_otp_version/1,
check_blacklisted_otp_versions/1,
- info_useless/2]).
+ info_useless/2,
+ list_dir/1]).
%% for internal use only
-export([otp_release/0]).
@@ -774,3 +775,9 @@ info_useless(Old, New) ->
|| Name <- Old,
not lists:member(Name, New)],
ok.
+
+-ifdef(no_list_dir_all).
+list_dir(Dir) -> file:list_dir(Dir).
+-else.
+list_dir(Dir) -> file:list_dir_all(Dir).
+-endif.
diff --git a/test/rebar_compile_SUITE.erl b/test/rebar_compile_SUITE.erl
index cc37441..1c2c527 100644
--- a/test/rebar_compile_SUITE.erl
+++ b/test/rebar_compile_SUITE.erl
@@ -5,12 +5,23 @@
end_per_suite/1,
init_per_testcase/2,
end_per_testcase/2,
+ init_per_group/2,
+ end_per_group/2,
all/0,
- build_basic_app/1,
- build_release_apps/1,
- build_checkout_apps/1,
- build_checkout_deps/1,
- build_all_srcdirs/1,
+ groups/0,
+ build_basic_app/1, paths_basic_app/1, clean_basic_app/1,
+ build_release_apps/1, paths_release_apps/1, clean_release_apps/1,
+ build_checkout_apps/1, paths_checkout_apps/1,
+ build_checkout_deps/1, paths_checkout_deps/1,
+ build_basic_srcdirs/1, paths_basic_srcdirs/1,
+ build_release_srcdirs/1, paths_release_srcdirs/1,
+ build_unbalanced_srcdirs/1, paths_unbalanced_srcdirs/1,
+ build_basic_extra_dirs/1, paths_basic_extra_dirs/1, clean_basic_extra_dirs/1,
+ build_release_extra_dirs/1, paths_release_extra_dirs/1, clean_release_extra_dirs/1,
+ build_unbalanced_extra_dirs/1, paths_unbalanced_extra_dirs/1,
+ build_extra_dirs_in_project_root/1,
+ paths_extra_dirs_in_project_root/1,
+ clean_extra_dirs_in_project_root/1,
recompile_when_hrl_changes/1,
recompile_when_opts_change/1,
dont_recompile_when_opts_dont_change/1,
@@ -35,116 +46,590 @@
suite() ->
[].
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_testcase(_, Config) ->
- rebar_test_utils:init_rebar_state(Config).
-
-end_per_testcase(_, _Config) ->
- catch meck:unload().
-
all() ->
- [build_basic_app, build_release_apps,
- build_checkout_apps, build_checkout_deps,
- 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,
+ [{group, basic_app}, {group, release_apps},
+ {group, checkout_apps}, {group, checkout_deps},
+ {group, basic_srcdirs}, {group, release_srcdirs}, {group, unbalanced_srcdirs},
+ {group, basic_extras}, {group, release_extras}, {group, unbalanced_extras},
+ {group, root_extras},
+ 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, highest_version_of_pkg_dep,
parse_transform_test, erl_first_files_test, mib_test,
umbrella_mib_first_test, only_default_transitive_deps,
- clean_all, override_deps, profile_override_deps, build_more_sources].
-
-build_basic_app(Config) ->
- AppDir = ?config(apps, Config),
-
- Name = rebar_test_utils:create_random_name("app1_"),
+ clean_all, override_deps, profile_override_deps].
+
+groups() ->
+ [{basic_app, [], [build_basic_app, paths_basic_app, clean_basic_app]},
+ {release_apps, [], [build_release_apps, paths_release_apps, clean_release_apps]},
+ {checkout_apps, [], [build_checkout_apps, paths_checkout_apps]},
+ {checkout_deps, [], [build_checkout_deps, paths_checkout_deps]},
+ {basic_srcdirs, [], [build_basic_srcdirs, paths_basic_srcdirs]},
+ {release_srcdirs, [], [build_release_srcdirs,
+ paths_release_srcdirs]},
+ {unbalanced_srcdirs, [], [build_unbalanced_srcdirs,
+ paths_unbalanced_srcdirs]},
+ {basic_extras, [], [build_basic_extra_dirs,
+ paths_basic_extra_dirs,
+ clean_basic_extra_dirs]},
+ {release_extras, [], [build_release_extra_dirs,
+ paths_release_extra_dirs,
+ clean_release_extra_dirs]},
+ {unbalanced_extras, [], [build_unbalanced_extra_dirs,
+ paths_unbalanced_extra_dirs]},
+ {root_extras, [], [build_extra_dirs_in_project_root,
+ paths_extra_dirs_in_project_root,
+ clean_extra_dirs_in_project_root]}].
+
+init_per_group(basic_app, Config) ->
+ NewConfig = rebar_test_utils:init_rebar_state(Config, "basic_app_"),
+ AppDir = ?config(apps, NewConfig),
+
+ 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]),
+
+ [{app_names, [Name]}, {vsns, [Vsn]}|NewConfig];
- rebar_test_utils:run_and_check(Config, [], ["compile"], {ok, [{app, Name}]}).
-
-build_release_apps(Config) ->
- AppDir = ?config(apps, Config),
+init_per_group(release_apps, Config) ->
+ NewConfig = rebar_test_utils:init_rebar_state(Config, "release_apps_"),
+ AppDir = ?config(apps, NewConfig),
Name1 = rebar_test_utils:create_random_name("relapp1_"),
Vsn1 = rebar_test_utils:create_random_vsn(),
rebar_test_utils:create_app(filename:join([AppDir,"apps",Name1]), Name1, Vsn1, [kernel, stdlib]),
+
Name2 = rebar_test_utils:create_random_name("relapp2_"),
Vsn2 = rebar_test_utils:create_random_vsn(),
rebar_test_utils:create_app(filename:join([AppDir,"apps",Name2]), Name2, Vsn2, [kernel, stdlib]),
+
+ [{app_names, [Name1, Name2]}, {vsns, [Vsn1, Vsn2]}|NewConfig];
- rebar_test_utils:run_and_check(
- Config, [], ["compile"],
- {ok, [{app, Name1}, {app, Name2}]}
- ).
+init_per_group(checkout_apps, Config) ->
+ NewConfig = rebar_test_utils:init_rebar_state(Config, "checkout_apps_"),
+ AppDir = ?config(apps, NewConfig),
+ CheckoutsDir = ?config(checkouts, NewConfig),
-build_checkout_apps(Config) ->
- AppDir = ?config(apps, Config),
- CheckoutsDir = ?config(checkouts, Config),
Name1 = rebar_test_utils:create_random_name("checkapp1_"),
Vsn1 = rebar_test_utils:create_random_vsn(),
rebar_test_utils:create_app(AppDir, Name1, Vsn1, [kernel, stdlib]),
+
Name2 = rebar_test_utils:create_random_name("checkapp2_"),
Vsn2 = rebar_test_utils:create_random_vsn(),
rebar_test_utils:create_app(filename:join([CheckoutsDir,Name2]), Name2, Vsn2, [kernel, stdlib]),
- rebar_test_utils:run_and_check(
- Config, [], ["compile"],
- {ok, [{app, Name1}, {checkout, Name2}]}
- ).
+ [{app_names, [Name1, Name2]}, {vsns, [Vsn1, Vsn2]}|NewConfig];
-build_checkout_deps(Config) ->
- AppDir = ?config(apps, Config),
- CheckoutsDir = ?config(checkouts, Config),
+init_per_group(checkout_deps, Config) ->
+ NewConfig = rebar_test_utils:init_rebar_state(Config, "checkout_deps_"),
+ AppDir = ?config(apps, NewConfig),
+ CheckoutsDir = ?config(checkouts, NewConfig),
DepsDir = filename:join([AppDir, "_build", "default", "lib"]),
+
Name1 = rebar_test_utils:create_random_name("checkapp1_"),
Vsn1 = rebar_test_utils:create_random_vsn(),
rebar_test_utils:create_app(AppDir, Name1, Vsn1, [kernel, stdlib]),
+
Name2 = rebar_test_utils:create_random_name("checkapp2_"),
Vsn2 = rebar_test_utils:create_random_vsn(),
rebar_test_utils:create_app(filename:join([CheckoutsDir,Name2]), Name2, Vsn2, [kernel, stdlib]),
+
rebar_test_utils:create_app(filename:join([DepsDir,Name2]), Name2, Vsn1, [kernel, stdlib]),
+ [{app_names, [Name1, Name2]}, {vsns, [Vsn1, Vsn2]}|NewConfig];
+
+init_per_group(Group, Config) when Group == basic_srcdirs; Group == basic_extras ->
+ NewConfig = rebar_test_utils:init_rebar_state(Config, "basic_srcdirs_"),
+ AppDir = ?config(apps, NewConfig),
+
+ 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 = io_lib:format("-module(~ts_extra).\n-export([ok/0]).\nok() -> ok.\n", [Name]),
+
+ ok = filelib:ensure_dir(filename:join([AppDir, "extra", "dummy"])),
+ ok = file:write_file(filename:join([AppDir, "extra", io_lib:format("~ts_extra.erl", [Name])]),
+ ExtraSrc),
+
+ [{app_names, [Name]}, {vsns, [Vsn]}|NewConfig];
+
+init_per_group(Group, Config) when Group == release_srcdirs; Group == release_extras ->
+ NewConfig = rebar_test_utils:init_rebar_state(Config, "release_srcdirs_"),
+ AppDir = ?config(apps, NewConfig),
+
+ Name1 = rebar_test_utils:create_random_name("relapp1_"),
+ Vsn1 = rebar_test_utils:create_random_vsn(),
+ rebar_test_utils:create_app(filename:join([AppDir, "apps", Name1]), Name1, Vsn1, [kernel, stdlib]),
+
+ Name2 = rebar_test_utils:create_random_name("relapp2_"),
+ Vsn2 = rebar_test_utils:create_random_vsn(),
+ rebar_test_utils:create_app(filename:join([AppDir, "apps", Name2]), Name2, Vsn2, [kernel, stdlib]),
+
+ ExtraOne = io_lib:format("-module(~ts_extra).\n-export([ok/0]).\nok() -> ok.\n", [Name1]),
+
+ ok = filelib:ensure_dir(filename:join([AppDir, "apps", Name1, "extra", "dummy"])),
+ ok = file:write_file(filename:join([AppDir, "apps", Name1, "extra",
+ io_lib:format("~ts_extra.erl", [Name1])]),
+ ExtraOne),
+
+ ExtraTwo = io_lib:format("-module(~ts_extra).\n-export([ok/0]).\nok() -> ok.\n", [Name2]),
+
+ ok = filelib:ensure_dir(filename:join([AppDir, "apps", Name2, "extra", "dummy"])),
+ ok = file:write_file(filename:join([AppDir, "apps", Name2, "extra",
+ io_lib:format("~ts_extra.erl", [Name2])]),
+ ExtraTwo),
+
+ [{app_names, [Name1, Name2]}, {vsns, [Vsn1, Vsn2]}|NewConfig];
+
+init_per_group(Group, Config) when Group == unbalanced_srcdirs; Group == unbalanced_extras ->
+ NewConfig = rebar_test_utils:init_rebar_state(Config, "unbalanced_srcdirs_"),
+ AppDir = ?config(apps, NewConfig),
+
+ Name1 = rebar_test_utils:create_random_name("relapp1_"),
+ Vsn1 = rebar_test_utils:create_random_vsn(),
+ rebar_test_utils:create_app(filename:join([AppDir, "apps", Name1]), Name1, Vsn1, [kernel, stdlib]),
+
+ Name2 = rebar_test_utils:create_random_name("relapp2_"),
+ Vsn2 = rebar_test_utils:create_random_vsn(),
+ rebar_test_utils:create_app(filename:join([AppDir, "apps", Name2]), Name2, Vsn2, [kernel, stdlib]),
+
+ ExtraOne = io_lib:format("-module(~ts_extra).\n-export([ok/0]).\nok() -> ok.\n", [Name1]),
+
+ ok = filelib:ensure_dir(filename:join([AppDir, "apps", Name1, "extra", "dummy"])),
+ ok = file:write_file(filename:join([AppDir, "apps", Name1, "extra",
+ io_lib:format("~ts_extra.erl", [Name1])]),
+ ExtraOne),
+
+ [{app_names, [Name1, Name2]}, {vsns, [Vsn1, Vsn2]}|NewConfig];
+
+init_per_group(root_extras, Config) ->
+ NewConfig = rebar_test_utils:init_rebar_state(Config, "root_extras_"),
+ AppDir = ?config(apps, NewConfig),
+
+ Name1 = rebar_test_utils:create_random_name("relapp1_"),
+ Vsn1 = rebar_test_utils:create_random_vsn(),
+ rebar_test_utils:create_app(filename:join([AppDir, "apps", Name1]), Name1, Vsn1, [kernel, stdlib]),
+
+ Name2 = rebar_test_utils:create_random_name("relapp2_"),
+ Vsn2 = rebar_test_utils:create_random_vsn(),
+ rebar_test_utils:create_app(filename:join([AppDir, "apps", Name2]), Name2, Vsn2, [kernel, stdlib]),
+
+ Extra = <<"-module(extra).\n-export([ok/0]).\nok() -> ok.\n">>,
+
+ ok = filelib:ensure_dir(filename:join([AppDir, "extra", "dummy"])),
+ ok = file:write_file(filename:join([AppDir, "extra", "extra.erl"]), Extra),
+
+ [{app_names, [Name1, Name2]}, {vsns, [Vsn1, Vsn2]}|NewConfig].
+
+end_per_group(_Group, _Config) ->
+ ok.
+
+init_per_suite(Config) ->
+ Config.
+
+end_per_suite(_Config) ->
+ ok.
+
+init_per_testcase(_, Config) ->
+ case ?config(apps, Config) of
+ undefined -> rebar_test_utils:init_rebar_state(Config);
+ _ -> Config
+ end.
+
+end_per_testcase(_, _Config) ->
+ catch meck:unload().
+
+
+
+%% test cases
+
+build_basic_app(Config) ->
+ [Name] = ?config(app_names, Config),
+ rebar_test_utils:run_and_check(Config, [], ["compile"], {ok, [{app, Name}]}).
+
+build_release_apps(Config) ->
+ [Name1, Name2] = ?config(app_names, Config),
+ rebar_test_utils:run_and_check(
+ Config, [], ["compile"],
+ {ok, [{app, Name1}, {app, Name2}]}
+ ).
+
+build_checkout_apps(Config) ->
+ [Name1, Name2] = ?config(app_names, Config),
+ rebar_test_utils:run_and_check(
+ Config, [], ["compile"],
+ {ok, [{app, Name1}, {checkout, Name2}]}
+ ).
+
+build_checkout_deps(Config) ->
+ AppDir = ?config(apps, Config),
+ [Name1, Name2] = ?config(app_names, Config),
+ [_, Vsn2] = ?config(vsns, Config),
+
Deps = [{list_to_atom(Name2), Vsn2, {git, "", ""}}],
{ok, RebarConfig} = file:consult(rebar_test_utils:create_config(AppDir, [{deps, Deps}])),
- {ok, State} = rebar_test_utils:run_and_check(
+ rebar_test_utils:run_and_check(
Config, RebarConfig, ["compile"],
{ok, [{app, Name1}, {checkout, Name2}]}
+ ).
+
+build_basic_srcdirs(Config) ->
+ AppDir = ?config(apps, Config),
+ [Name] = ?config(app_names, Config),
+
+ RebarConfig = [{erl_opts, [{src_dirs, ["src", "extra"]}]}],
+
+ %% check a beam corresponding to the src in the extra src_dir exists
+ ExtraBeam = filename:join([AppDir, "_build", "default", "lib", Name, "ebin",
+ io_lib:format("~ts_extra.beam", [Name])]),
+ %% check the extra src_dir was copied/linked into the _build dir
+ ExtraDir = filename:join([AppDir, "_build", "default", "lib", Name, "extra"]),
+
+ rebar_test_utils:run_and_check(
+ Config, RebarConfig, ["compile"],
+ {ok, [{app, Name}, {file, ExtraBeam}, {dir, ExtraDir}]}
+ ).
+
+build_release_srcdirs(Config) ->
+ AppDir = ?config(apps, Config),
+ [Name1, Name2] = ?config(app_names, Config),
+
+ RebarConfig = [{erl_opts, [{src_dirs, ["src", "extra"]}]}],
+
+ %% check a beam corresponding to the src in the extra src_dir exists
+ Extra1Beam = filename:join([AppDir, "_build", "default", "lib", Name1, "ebin",
+ io_lib:format("~ts_extra.beam", [Name1])]),
+ Extra2Beam = filename:join([AppDir, "_build", "default", "lib", Name2, "ebin",
+ io_lib:format("~ts_extra.beam", [Name2])]),
+
+ %% check the extra src_dir was copied/linked into the _build dir
+ Extra1Dir = filename:join([AppDir, "_build", "default", "lib", Name1, "extra"]),
+ Extra2Dir = filename:join([AppDir, "_build", "default", "lib", Name2, "extra"]),
+
+ rebar_test_utils:run_and_check(
+ Config, RebarConfig, ["compile"],
+ {ok, [{app, Name1}, {app, Name2},
+ {file, Extra1Beam}, {file, Extra2Beam},
+ {dir, Extra1Dir}, {dir, Extra2Dir}]}
+ ).
+
+build_unbalanced_srcdirs(Config) ->
+ AppDir = ?config(apps, Config),
+ [Name1, Name2] = ?config(app_names, Config),
+
+ RebarConfig = [{erl_opts, [{src_dirs, ["src", "extra"]}]}],
+
+ %% check a beam corresponding to the src in the extra src_dir exists
+ Extra1Beam = filename:join([AppDir, "_build", "default", "lib", Name1, "ebin",
+ io_lib:format("~ts_extra.beam", [Name1])]),
+
+ %% check the extra src_dir was copied/linked into the _build dir
+ Extra1Dir = filename:join([AppDir, "_build", "default", "lib", Name1, "extra"]),
+
+ rebar_test_utils:run_and_check(
+ Config, RebarConfig, ["compile"],
+ {ok, [{app, Name1}, {app, Name2}, {file, Extra1Beam}, {dir, Extra1Dir}]}
+ ),
+
+ %% check no extra src_dir were copied/linked into the _build dir
+ Extra2Dir = filename:join([AppDir, "_build", "default", "lib", Name2, "extra"]),
+ false = filelib:is_dir(Extra2Dir),
+ %% check only expected beams are in the ebin dir
+ {ok, Files} = rebar_utils:list_dir(filename:join([AppDir, "_build", "default", "lib", Name2, "ebin"])),
+ lists:all(fun(Beam) -> lists:member(Beam, [Name2 ++ ".app", "not_a_real_src_" ++ Name2 ++ ".beam"]) end,
+ Files).
+
+build_basic_extra_dirs(Config) ->
+ AppDir = ?config(apps, Config),
+ [Name] = ?config(app_names, Config),
+
+ RebarConfig = [{erl_opts, [{extra_src_dirs, ["extra"]}]}],
+
+ %% check a beam corresponding to the src in the extra src_dir exists
+ ExtraBeam = filename:join([AppDir, "_build", "default", "lib", Name, "extra",
+ io_lib:format("~ts_extra.beam", [Name])]),
+
+ rebar_test_utils:run_and_check(
+ Config, RebarConfig, ["compile"],
+ {ok, [{app, Name}, {file, ExtraBeam}]}
+ ).
+
+build_release_extra_dirs(Config) ->
+ AppDir = ?config(apps, Config),
+ [Name1, Name2] = ?config(app_names, Config),
+
+ RebarConfig = [{erl_opts, [{extra_src_dirs, ["extra"]}]}],
+
+ %% check a beam corresponding to the src in the extra src_dir exists
+ Extra1Beam = filename:join([AppDir, "_build", "default", "lib", Name1, "extra",
+ io_lib:format("~ts_extra.beam", [Name1])]),
+ Extra2Beam = filename:join([AppDir, "_build", "default", "lib", Name2, "extra",
+ io_lib:format("~ts_extra.beam", [Name2])]),
+
+ rebar_test_utils:run_and_check(
+ Config, RebarConfig, ["compile"],
+ {ok, [{app, Name1}, {app, Name2}, {file, Extra1Beam}, {file, Extra2Beam}]}
+ ).
+
+build_unbalanced_extra_dirs(Config) ->
+ AppDir = ?config(apps, Config),
+ [Name1, Name2] = ?config(app_names, Config),
+
+ RebarConfig = [{erl_opts, [{extra_src_dirs, ["extra"]}]}],
+
+ %% check a beam corresponding to the src in the extra src_dir exists
+ Extra1Beam = filename:join([AppDir, "_build", "default", "lib", Name1, "extra",
+ io_lib:format("~ts_extra.beam", [Name1])]),
+
+ rebar_test_utils:run_and_check(
+ Config, RebarConfig, ["compile"],
+ {ok, [{app, Name1}, {app, Name2}, {file, Extra1Beam}]}
),
+
+ %% check no extra src_dir were copied/linked into the _build dir
+ false = filelib:is_dir(filename:join([AppDir, "_build", "default", "lib", Name2, "extra"])),
+ %% check only expected beams are in the ebin dir
+ {ok, Files} = rebar_utils:list_dir(filename:join([AppDir, "_build", "default", "lib", Name2, "ebin"])),
+ lists:all(fun(Beam) -> lists:member(Beam, [Name2 ++ ".app", "not_a_real_src_" ++ Name2 ++ ".beam"]) end,
+ Files).
+
+build_extra_dirs_in_project_root(Config) ->
+ AppDir = ?config(apps, Config),
+ [Name1, Name2] = ?config(app_names, Config),
+
+ RebarConfig = [{erl_opts, [{extra_src_dirs, ["extra"]}]}],
+
+ %% check a beam corresponding to the src in the extra src_dir exists
+ ExtraBeam = filename:join([AppDir, "_build", "default", "extras", "extra", "extra.beam"]),
+
+ rebar_test_utils:run_and_check(
+ Config, RebarConfig, ["compile"],
+ {ok, [{app, Name1}, {app, Name2}, {file, ExtraBeam}]}
+ ).
+
+paths_basic_app(Config) ->
+ [Name] = ?config(app_names, Config),
+ [Vsn] = ?config(vsns, Config),
+
+ {ok, State} = rebar_test_utils:run_and_check(Config, [], ["compile"], return),
+
+ code:add_paths(rebar_state:code_paths(State, all_deps)),
+ ok = application:load(list_to_atom(Name)),
+ Loaded = application:loaded_applications(),
+ {_, _, Vsn} = lists:keyfind(list_to_atom(Name), 1, Loaded).
+
+paths_release_apps(Config) ->
+ [Name1, Name2] = ?config(app_names, Config),
+ [Vsn1, Vsn2] = ?config(vsns, Config),
+
+ {ok, State} = rebar_test_utils:run_and_check(Config, [], ["compile"], return),
+
code:add_paths(rebar_state:code_paths(State, all_deps)),
+ ok = application:load(list_to_atom(Name1)),
ok = application:load(list_to_atom(Name2)),
Loaded = application:loaded_applications(),
+ {_, _, Vsn1} = lists:keyfind(list_to_atom(Name1), 1, Loaded),
{_, _, Vsn2} = lists:keyfind(list_to_atom(Name2), 1, Loaded).
-build_all_srcdirs(Config) ->
+paths_checkout_apps(Config) ->
+ [Name1, _Name2] = ?config(app_names, Config),
+ [Vsn1, _Vsn2] = ?config(vsns, Config),
+
+ {ok, State} = rebar_test_utils:run_and_check(Config, [], ["compile"], return),
+
+ code:add_paths(rebar_state:code_paths(State, all_deps)),
+ ok = application:load(list_to_atom(Name1)),
+ Loaded = application:loaded_applications(),
+ {_, _, Vsn1} = lists:keyfind(list_to_atom(Name1), 1, Loaded).
+
+paths_checkout_deps(Config) ->
AppDir = ?config(apps, Config),
+ [_Name1, Name2] = ?config(app_names, Config),
+ [_Vsn1, Vsn2] = ?config(vsns, Config),
+
+ %% rebar_test_utils:init_rebar_state/1,2 uses rebar_state:new/3 which
+ %% maybe incorrectly sets deps to [] (based on `rebar.lock`) instead of
+ %% to the checkapps
+ %% until that is sorted out the lock file has to be removed before
+ %% this test will pass
+ file:delete(filename:join([AppDir, "rebar.lock"])),
+
+ {ok, RebarConfig} = file:consult(filename:join([AppDir, "rebar.config"])),
+
+ {ok, State} = rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], return),
+
+ code:add_paths(rebar_state:code_paths(State, all_deps)),
+ ok = application:load(list_to_atom(Name2)),
+ Loaded = application:loaded_applications(),
+ {_, _, Vsn2} = lists:keyfind(list_to_atom(Name2), 1, Loaded).
+
+paths_basic_srcdirs(Config) ->
+ AppDir = ?config(apps, Config),
+ [Name] = ?config(app_names, Config),
RebarConfig = [{erl_opts, [{src_dirs, ["src", "extra"]}]}],
- 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]),
+ {ok, State} = rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], return),
- ExtraSrc = <<"-module(extra_src).\n"
- "-export([ok/0]).\n"
- "ok() -> ok.\n">>,
+ code:add_paths(rebar_state:code_paths(State, all_deps)),
+ Mod = list_to_atom(lists:flatten(io_lib:format("~ts_extra", [Name]))),
+ {module, Mod} = code:ensure_loaded(Mod),
- ok = filelib:ensure_dir(filename:join([AppDir, "extra", "dummy"])),
- ok = file:write_file(filename:join([AppDir, "extra", "extra_src.erl"]), ExtraSrc),
+ Expect = filename:join([AppDir, "_build", "default", "lib", Name, "ebin",
+ io_lib:format("~ts_extra.beam", [Name])]),
+ Expect = code:which(Mod).
- rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], {ok, [{app, Name}]}),
+paths_release_srcdirs(Config) ->
+ AppDir = ?config(apps, Config),
+ [Name1, Name2] = ?config(app_names, Config),
- %% check a beam corresponding to the src in the extra src_dir exists in ebin
- EbinDir = filename:join([AppDir, "_build", "default", "lib", Name, "ebin"]),
- true = filelib:is_file(filename:join([EbinDir, "extra_src.beam"])),
+ RebarConfig = [{erl_opts, [{src_dirs, ["src", "extra"]}]}],
- %% check the extra src_dir was linked into the _build dir
- true = filelib:is_dir(filename:join([AppDir, "_build", "default", "lib", Name, "extra"])).
+ {ok, State} = rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], return),
+
+ code:add_paths(rebar_state:code_paths(State, all_deps)),
+ Mod1 = list_to_atom(lists:flatten(io_lib:format("~ts_extra", [Name1]))),
+ {module, Mod1} = code:ensure_loaded(Mod1),
+ Mod2 = list_to_atom(lists:flatten(io_lib:format("~ts_extra", [Name2]))),
+ {module, Mod2} = code:ensure_loaded(Mod2),
+
+ ExpectOne = filename:join([AppDir, "_build", "default", "lib", Name1, "ebin",
+ io_lib:format("~ts_extra.beam", [Name1])]),
+ ExpectOne = code:which(Mod1),
+ ExpectTwo = filename:join([AppDir, "_build", "default", "lib", Name2, "ebin",
+ io_lib:format("~ts_extra.beam", [Name2])]),
+ ExpectTwo = code:which(Mod2).
+
+paths_unbalanced_srcdirs(Config) ->
+ AppDir = ?config(apps, Config),
+ [Name1, Name2] = ?config(app_names, Config),
+
+ RebarConfig = [{erl_opts, [{src_dirs, ["src", "extra"]}]}],
+
+ {ok, State} = rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], return),
+
+ code:add_paths(rebar_state:code_paths(State, all_deps)),
+ Mod1 = list_to_atom(lists:flatten(io_lib:format("~ts_extra", [Name1]))),
+ {module, Mod1} = code:ensure_loaded(Mod1),
+ Mod2 = list_to_atom(lists:flatten(io_lib:format("~ts_extra", [Name2]))),
+ {error, nofile} = code:ensure_loaded(Mod2),
+
+ ExpectOne = filename:join([AppDir, "_build", "default", "lib", Name1, "ebin",
+ io_lib:format("~ts_extra.beam", [Name1])]),
+ ExpectOne = code:which(Mod1).
+
+paths_basic_extra_dirs(Config) ->
+ AppDir = ?config(apps, Config),
+ [Name] = ?config(app_names, Config),
+
+ RebarConfig = [{erl_opts, [{extra_src_dirs, ["extra"]}]}],
+
+ {ok, State} = rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], return),
+
+ code:add_paths(rebar_state:code_paths(State, all_deps)),
+ Mod = list_to_atom(lists:flatten(io_lib:format("~ts_extra", [Name]))),
+ {module, Mod} = code:ensure_loaded(Mod),
+
+ Expect = filename:join([AppDir, "_build", "default", "lib", Name, "extra",
+ io_lib:format("~ts_extra.beam", [Name])]),
+ Expect = code:which(Mod).
+
+paths_release_extra_dirs(Config) ->
+ AppDir = ?config(apps, Config),
+ [Name1, Name2] = ?config(app_names, Config),
+
+ RebarConfig = [{erl_opts, [{extra_src_dirs, ["extra"]}]}],
+
+ {ok, State} = rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], return),
+
+ code:add_paths(rebar_state:code_paths(State, all_deps)),
+ Mod1 = list_to_atom(lists:flatten(io_lib:format("~ts_extra", [Name1]))),
+ {module, Mod1} = code:ensure_loaded(Mod1),
+ Mod2 = list_to_atom(lists:flatten(io_lib:format("~ts_extra", [Name2]))),
+ {module, Mod2} = code:ensure_loaded(Mod2),
+
+ ExpectOne = filename:join([AppDir, "_build", "default", "lib", Name1, "extra",
+ io_lib:format("~ts_extra.beam", [Name1])]),
+ ExpectOne = code:which(Mod1),
+ ExpectTwo = filename:join([AppDir, "_build", "default", "lib", Name2, "extra",
+ io_lib:format("~ts_extra.beam", [Name2])]),
+ ExpectTwo = code:which(Mod2).
+
+
+paths_unbalanced_extra_dirs(Config) ->
+ AppDir = ?config(apps, Config),
+ [Name1, Name2] = ?config(app_names, Config),
+
+ RebarConfig = [{erl_opts, [{extra_src_dirs, ["extra"]}]}],
+
+ {ok, State} = rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], return),
+
+ code:add_paths(rebar_state:code_paths(State, all_deps)),
+ Mod1 = list_to_atom(lists:flatten(io_lib:format("~ts_extra", [Name1]))),
+ {module, Mod1} = code:ensure_loaded(Mod1),
+ Mod2 = list_to_atom(lists:flatten(io_lib:format("~ts_extra", [Name2]))),
+ {error, nofile} = code:ensure_loaded(Mod2),
+
+ ExpectOne = filename:join([AppDir, "_build", "default", "lib", Name1, "extra",
+ io_lib:format("~ts_extra.beam", [Name1])]),
+ ExpectOne = code:which(Mod1).
+
+paths_extra_dirs_in_project_root(Config) ->
+ AppDir = ?config(apps, Config),
+
+ RebarConfig = [{erl_opts, [{extra_src_dirs, ["extra"]}]}],
+
+ {ok, State} = rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], return),
+
+ code:add_paths(rebar_state:code_paths(State, all_deps)),
+ {module, extra} = code:ensure_loaded(extra),
+
+ Expect = filename:join([AppDir, "_build", "default", "extras", "extra", "extra.beam"]),
+ Expect = code:which(extra).
+
+clean_basic_app(Config) ->
+ [Name] = ?config(app_names, Config),
+
+ rebar_test_utils:run_and_check(Config, [], ["clean"], {ok, [{app, Name, invalid}]}).
+
+clean_release_apps(Config) ->
+ [Name1, Name2] = ?config(app_names, Config),
+
+ rebar_test_utils:run_and_check(Config, [], ["clean"],
+ {ok, [{app, Name1, invalid}, {app, Name2, invalid}]}).
+
+clean_basic_extra_dirs(Config) ->
+ AppDir = ?config(apps, Config),
+ [Name] = ?config(app_names, Config),
+
+ rebar_test_utils:run_and_check(Config, [], ["clean"], {ok, [{app, Name, invalid}]}),
+
+ Beam = lists:flatten(io_lib:format("~ts_extra", [Name])),
+ false = ec_file:exists(filename:join([AppDir, "_build", "default", "lib", Name, "extras", Beam])).
+
+clean_release_extra_dirs(Config) ->
+ AppDir = ?config(apps, Config),
+ [Name1, Name2] = ?config(app_names, Config),
+
+ rebar_test_utils:run_and_check(Config, [], ["clean"],
+ {ok, [{app, Name1, invalid}, {app, Name2, invalid}]}),
+
+ Beam1 = lists:flatten(io_lib:format("~ts_extra", [Name1])),
+ false = ec_file:exists(filename:join([AppDir, "_build", "default", "lib", Name1, "extras", Beam1])),
+ Beam2 = lists:flatten(io_lib:format("~ts_extra", [Name2])),
+ false = ec_file:exists(filename:join([AppDir, "_build", "default", "lib", Name2, "extras", Beam2])).
+
+clean_extra_dirs_in_project_root(Config) ->
+ AppDir = ?config(apps, Config),
+ [Name1, Name2] = ?config(app_names, Config),
+
+ rebar_test_utils:run_and_check(Config, [], ["clean"],
+ {ok, [{app, Name1, invalid}, {app, Name2, invalid}]}),
+
+ false = ec_file:exists(filename:join([AppDir, "_build", "default", "extras"])).
recompile_when_hrl_changes(Config) ->
AppDir = ?config(apps, Config),
@@ -167,7 +652,7 @@ recompile_when_hrl_changes(Config) ->
rebar_test_utils:run_and_check(Config, [], ["compile"], {ok, [{app, Name}]}),
EbinDir = filename:join([AppDir, "_build", "default", "lib", Name, "ebin"]),
- {ok, Files} = file:list_dir(EbinDir),
+ {ok, Files} = rebar_utils:list_dir(EbinDir),
ModTime = [filelib:last_modified(filename:join([EbinDir, F]))
|| F <- Files, filename:extension(F) == ".beam"],
@@ -178,7 +663,7 @@ recompile_when_hrl_changes(Config) ->
rebar_test_utils:run_and_check(Config, [], ["compile"], {ok, [{app, Name}]}),
- {ok, NewFiles} = file:list_dir(EbinDir),
+ {ok, NewFiles} = rebar_utils:list_dir(EbinDir),
NewModTime = [filelib:last_modified(filename:join([EbinDir, F]))
|| F <- NewFiles, filename:extension(F) == ".beam"],
@@ -194,7 +679,7 @@ recompile_when_opts_change(Config) ->
rebar_test_utils:run_and_check(Config, [], ["compile"], {ok, [{app, Name}]}),
EbinDir = filename:join([AppDir, "_build", "default", "lib", Name, "ebin"]),
- {ok, Files} = file:list_dir(EbinDir),
+ {ok, Files} = rebar_utils:list_dir(EbinDir),
ModTime = [filelib:last_modified(filename:join([EbinDir, F]))
|| F <- Files, filename:extension(F) == ".beam"],
@@ -204,7 +689,7 @@ recompile_when_opts_change(Config) ->
rebar_test_utils:run_and_check(Config, [], ["compile"], {ok, [{app, Name}]}),
- {ok, NewFiles} = file:list_dir(EbinDir),
+ {ok, NewFiles} = rebar_utils:list_dir(EbinDir),
NewModTime = [filelib:last_modified(filename:join([EbinDir, F]))
|| F <- NewFiles, filename:extension(F) == ".beam"],
@@ -220,7 +705,7 @@ dont_recompile_when_opts_dont_change(Config) ->
rebar_test_utils:run_and_check(Config, [], ["compile"], {ok, [{app, Name}]}),
EbinDir = filename:join([AppDir, "_build", "default", "lib", Name, "ebin"]),
- {ok, Files} = file:list_dir(EbinDir),
+ {ok, Files} = rebar_utils:list_dir(EbinDir),
ModTime = [filelib:last_modified(filename:join([EbinDir, F]))
|| F <- Files, filename:extension(F) == ".beam"],
@@ -228,7 +713,7 @@ dont_recompile_when_opts_dont_change(Config) ->
rebar_test_utils:run_and_check(Config, [], ["compile"], {ok, [{app, Name}]}),
- {ok, NewFiles} = file:list_dir(EbinDir),
+ {ok, NewFiles} = rebar_utils:list_dir(EbinDir),
NewModTime = [filelib:last_modified(filename:join([EbinDir, F]))
|| F <- NewFiles, filename:extension(F) == ".beam"],
@@ -331,7 +816,8 @@ deps_in_path(Config) ->
%% find pkg name in there
?assertNotEqual([], [Path || Path <- code:get_path(),
{match, _} <- [re:run(Path, PkgName)]]),
- code:set_path(StartPaths),
+
+ true = code:set_path(lists:filter(fun(P) -> ec_file:exists(P) end, StartPaths)),
%% Make sure apps we look for are not visible again
%% Hope not to find src name
?assertEqual([], [Path || Path <- code:get_path(),
@@ -638,10 +1124,10 @@ clean_all(Config) ->
),
%% Clean all
- rebar_test_utils:run_and_check(
- Config, RConf, ["clean", "--all"],
- {ok, [{app, Name, invalid}, {app, DepName, invalid}, {app, PkgName, invalid}]}
- ).
+ rebar_test_utils:run_and_check(Config, [], ["clean", "--all"],
+ {ok, [{app, Name, invalid},
+ {app, DepName, invalid},
+ {app, PkgName, invalid}]}).
override_deps(Config) ->
mock_git_resource:mock([{deps, [{some_dep, "0.0.1"},{other_dep, "0.0.1"}]}]),
@@ -680,3 +1166,4 @@ profile_override_deps(Config) ->
Config, RebarConfig, ["as", "a", "compile"],
{ok, [{dep, "some_dep"},{dep_not_exist, "other_dep"}]}
).
+
diff --git a/test/rebar_cover_SUITE.erl b/test/rebar_cover_SUITE.erl
index 1fae92c..ba078c2 100644
--- a/test/rebar_cover_SUITE.erl
+++ b/test/rebar_cover_SUITE.erl
@@ -7,6 +7,9 @@
all/0,
flag_coverdata_written/1,
config_coverdata_written/1,
+ basic_extra_src_dirs/1,
+ release_extra_src_dirs/1,
+ root_extra_src_dirs/1,
index_written/1,
flag_verbose/1,
config_verbose/1]).
@@ -29,6 +32,8 @@ init_per_testcase(_, Config) ->
all() ->
[flag_coverdata_written, config_coverdata_written,
+ basic_extra_src_dirs, release_extra_src_dirs,
+ root_extra_src_dirs,
index_written,
flag_verbose, config_verbose].
@@ -62,6 +67,88 @@ config_coverdata_written(Config) ->
true = filelib:is_file(filename:join([AppDir, "_build", "test", "cover", "eunit.coverdata"])).
+basic_extra_src_dirs(Config) ->
+ AppDir = ?config(apps, Config),
+
+ Name = rebar_test_utils:create_random_name("cover_extra_"),
+ Vsn = rebar_test_utils:create_random_vsn(),
+ rebar_test_utils:create_eunit_app(AppDir, Name, Vsn, [kernel, stdlib]),
+
+ ExtraSrc = io_lib:format("-module(~ts_extra).\n-export([ok/0]).\nok() -> ok.\n", [Name]),
+
+ ok = filelib:ensure_dir(filename:join([AppDir, "extra", "dummy"])),
+ ok = file:write_file(filename:join([AppDir, "extra", io_lib:format("~ts_extra.erl", [Name])]),
+ ExtraSrc),
+
+ RebarConfig = [{erl_opts, [{d, some_define}]}, {extra_src_dirs, ["extra"]}],
+ rebar_test_utils:run_and_check(Config,
+ RebarConfig,
+ ["eunit", "--cover"],
+ {ok, [{app, Name}]}),
+
+ Mod = list_to_atom(lists:flatten(io_lib:format("~ts_extra", [Name]))),
+ {file, _} = cover:is_compiled(Mod).
+
+release_extra_src_dirs(Config) ->
+ AppDir = ?config(apps, Config),
+
+ Name1 = rebar_test_utils:create_random_name("relapp1_"),
+ Vsn1 = rebar_test_utils:create_random_vsn(),
+ rebar_test_utils:create_app(filename:join([AppDir, "apps", Name1]), Name1, Vsn1, [kernel, stdlib]),
+
+ Name2 = rebar_test_utils:create_random_name("relapp2_"),
+ Vsn2 = rebar_test_utils:create_random_vsn(),
+ rebar_test_utils:create_app(filename:join([AppDir, "apps", Name2]), Name2, Vsn2, [kernel, stdlib]),
+
+ ExtraOne = io_lib:format("-module(~ts_extra).\n-export([ok/0]).\nok() -> ok.\n", [Name1]),
+
+ ok = filelib:ensure_dir(filename:join([AppDir, "apps", Name1, "extra", "dummy"])),
+ ok = file:write_file(filename:join([AppDir, "apps", Name1, "extra",
+ io_lib:format("~ts_extra.erl", [Name1])]),
+ ExtraOne),
+
+ ExtraTwo = io_lib:format("-module(~ts_extra).\n-export([ok/0]).\nok() -> ok.\n", [Name2]),
+
+ ok = filelib:ensure_dir(filename:join([AppDir, "apps", Name2, "extra", "dummy"])),
+ ok = file:write_file(filename:join([AppDir, "apps", Name2, "extra",
+ io_lib:format("~ts_extra.erl", [Name2])]),
+ ExtraTwo),
+
+ RebarConfig = [{erl_opts, [{d, some_define}]}, {extra_src_dirs, ["extra"]}],
+ rebar_test_utils:run_and_check(Config,
+ RebarConfig,
+ ["eunit", "--cover"],
+ {ok, [{app, Name1}, {app, Name2}]}),
+
+ Mod1 = list_to_atom(lists:flatten(io_lib:format("~ts_extra", [Name1]))),
+ {file, _} = cover:is_compiled(Mod1),
+ Mod2 = list_to_atom(lists:flatten(io_lib:format("~ts_extra", [Name2]))),
+ {file, _} = cover:is_compiled(Mod2).
+
+root_extra_src_dirs(Config) ->
+ AppDir = ?config(apps, Config),
+
+ Name1 = rebar_test_utils:create_random_name("relapp1_"),
+ Vsn1 = rebar_test_utils:create_random_vsn(),
+ rebar_test_utils:create_app(filename:join([AppDir, "apps", Name1]), Name1, Vsn1, [kernel, stdlib]),
+
+ Name2 = rebar_test_utils:create_random_name("relapp2_"),
+ Vsn2 = rebar_test_utils:create_random_vsn(),
+ rebar_test_utils:create_app(filename:join([AppDir, "apps", Name2]), Name2, Vsn2, [kernel, stdlib]),
+
+ Extra = <<"-module(extra).\n-export([ok/0]).\nok() -> ok.\n">>,
+
+ ok = filelib:ensure_dir(filename:join([AppDir, "extra", "dummy"])),
+ ok = file:write_file(filename:join([AppDir, "extra", "extra.erl"]), Extra),
+
+ RebarConfig = [{erl_opts, [{d, some_define}]}, {extra_src_dirs, ["extra"]}],
+ rebar_test_utils:run_and_check(Config,
+ RebarConfig,
+ ["eunit", "--cover"],
+ {ok, [{app, Name1}, {app, Name2}]}),
+
+ {file, _} = cover:is_compiled(extra).
+
index_written(Config) ->
AppDir = ?config(apps, Config),
diff --git a/test/rebar_ct_SUITE.erl b/test/rebar_ct_SUITE.erl
index 95a411f..cdd3774 100644
--- a/test/rebar_ct_SUITE.erl
+++ b/test/rebar_ct_SUITE.erl
@@ -204,6 +204,7 @@ multi_app_default_beams(Config) ->
File3 = filename:join([AppDir,
"_build",
"test",
+ "extras",
"test",
"extras_SUITE.beam"]),
diff --git a/test/rebar_eunit_SUITE.erl b/test/rebar_eunit_SUITE.erl
index 903bd96..609be51 100644
--- a/test/rebar_eunit_SUITE.erl
+++ b/test/rebar_eunit_SUITE.erl
@@ -125,7 +125,9 @@ basic_app_files(Config) ->
AppDir = ?config(apps, Config),
lists:foreach(fun(F) -> true = ec_file:exists(filename:join([AppDir, "_build", "test", "lib", "basic_app", "ebin", F])) end,
- ["basic_app.app", "basic_app.beam", "basic_app_tests.beam", "basic_app_tests_helper.beam"]).
+ ["basic_app.app", "basic_app.beam"]),
+ lists:foreach(fun(F) -> true = ec_file:exists(filename:join([AppDir, "_build", "test", "lib", "basic_app", "test", F])) end,
+ ["basic_app_tests.beam", "basic_app_tests_helper.beam"]).
%% check that the correct tests are exported from modules for project
%% note that this implies `TEST` is set correctly
@@ -171,10 +173,14 @@ multi_app_files(Config) ->
AppDir = ?config(apps, Config),
lists:foreach(fun(F) -> true = ec_file:exists(filename:join([AppDir, "_build", "test", "lib", "multi_app_bar", "ebin", F])) end,
- ["multi_app_bar.app", "multi_app_bar.beam", "multi_app_bar_tests.beam", "multi_app_bar_tests_helper.beam"]),
+ ["multi_app_bar.app", "multi_app_bar.beam"]),
lists:foreach(fun(F) -> true = ec_file:exists(filename:join([AppDir, "_build", "test", "lib", "multi_app_baz", "ebin", F])) end,
- ["multi_app_baz.app", "multi_app_baz.beam", "multi_app_baz_tests.beam", "multi_app_baz_tests_helper.beam"]),
- lists:foreach(fun(F) -> true = ec_file:exists(filename:join([AppDir, "_build", "test", "test", F])) end,
+ ["multi_app_baz.app", "multi_app_baz.beam"]),
+ lists:foreach(fun(F) -> true = ec_file:exists(filename:join([AppDir, "_build", "test", "lib", "multi_app_bar", "test", F])) end,
+ ["multi_app_bar_tests.beam", "multi_app_bar_tests_helper.beam"]),
+ lists:foreach(fun(F) -> true = ec_file:exists(filename:join([AppDir, "_build", "test", "lib", "multi_app_baz", "test", F])) end,
+ ["multi_app_baz_tests.beam", "multi_app_baz_tests_helper.beam"]),
+ lists:foreach(fun(F) -> true = ec_file:exists(filename:join([AppDir, "_build", "test", "extras", "test", F])) end,
["multi_app_tests.beam", "multi_app_tests_helper.beam"]).
%% check that the correct tests are exported from modules for project
@@ -202,7 +208,9 @@ multi_app_testset(Config) ->
AppDir = ?config(apps, Config),
Result = ?config(result, Config),
- Set = {ok, [{application, multi_app_bar}, {application, multi_app_baz}, {dir, filename:join([AppDir, "_build", "test", "test"])}]},
+ Set = {ok, [{application, multi_app_bar},
+ {application, multi_app_baz},
+ {dir, filename:join([AppDir, "test"])}]},
Set = rebar_prv_eunit:prepare_tests(Result).
diff --git a/test/rebar_file_utils_SUITE.erl b/test/rebar_file_utils_SUITE.erl
index 4324a5f..a061325 100644
--- a/test/rebar_file_utils_SUITE.erl
+++ b/test/rebar_file_utils_SUITE.erl
@@ -64,7 +64,7 @@ reset_nonexistent_dir(Config) ->
?assertNot(filelib:is_dir(TmpDir)),
ok = rebar_file_utils:reset_dir(TmpDir),
?assert(filelib:is_dir(TmpDir)),
- {ok, []} = file:list_dir(TmpDir).
+ {ok, []} = rebar_utils:list_dir(TmpDir).
reset_empty_dir(Config) ->
TmpDir = ?config(tmpdir, Config),
@@ -73,7 +73,7 @@ reset_empty_dir(Config) ->
?assert(filelib:is_dir(TmpDir)),
ok = rebar_file_utils:reset_dir(TmpDir),
?assert(filelib:is_dir(TmpDir)),
- {ok, []} = file:list_dir(TmpDir).
+ {ok, []} = rebar_utils:list_dir(TmpDir).
reset_dir(Config) ->
TmpDir = ?config(tmpdir, Config),
@@ -86,7 +86,7 @@ reset_dir(Config) ->
["a", "b", "c"]),
ok = rebar_file_utils:reset_dir(TmpDir),
?assert(filelib:is_dir(TmpDir)),
- {ok, []} = file:list_dir(TmpDir).
+ {ok, []} = rebar_utils:list_dir(TmpDir).
path_from_ancestor(_Config) ->
?assertEqual({ok, "foo/bar/baz"}, rebar_file_utils:path_from_ancestor("/foo/bar/baz", "/")),
diff --git a/test/rebar_src_dirs_SUITE.erl b/test/rebar_src_dirs_SUITE.erl
index e29dcf0..5a00515 100644
--- a/test/rebar_src_dirs_SUITE.erl
+++ b/test/rebar_src_dirs_SUITE.erl
@@ -132,9 +132,9 @@ build_basic_app(Config) ->
rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], {ok, [{app, Name}]}),
- %% check that `extra.erl` was compiled to the `ebin` dir
- Ebin = filename:join([AppDir, "_build", "default", "lib", Name, "ebin"]),
- true = filelib:is_file(filename:join([Ebin, "extra.beam"])),
+ %% check that `extra.erl` was compiled to the `extra` dir
+ ExtraOut = filename:join([AppDir, "_build", "default", "lib", Name, "extra"]),
+ true = filelib:is_file(filename:join([ExtraOut, "extra.beam"])),
%% check that `extra.erl` is not in the `modules` key of the app
{ok, App} = file:consult(filename:join([AppDir,
@@ -176,11 +176,11 @@ build_multi_apps(Config) ->
),
%% check that `extraX.erl` was compiled to the `ebin` dir
- Ebin1 = filename:join([AppDir, "_build", "default", "lib", Name1, "ebin"]),
- true = filelib:is_file(filename:join([Ebin1, "extra1.beam"])),
+ ExtraOut1 = filename:join([AppDir, "_build", "default", "lib", Name1, "extra"]),
+ true = filelib:is_file(filename:join([ExtraOut1, "extra1.beam"])),
- Ebin2 = filename:join([AppDir, "_build", "default", "lib", Name2, "ebin"]),
- true = filelib:is_file(filename:join([Ebin2, "extra2.beam"])),
+ ExtraOut2 = filename:join([AppDir, "_build", "default", "lib", Name2, "extra"]),
+ true = filelib:is_file(filename:join([ExtraOut2, "extra2.beam"])),
%% check that `extraX.erl` is not in the `modules` key of the app
{ok, App1} = file:consult(filename:join([AppDir,
@@ -221,10 +221,9 @@ src_dir_takes_precedence_over_extra(Config) ->
rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], {ok, [{app, Name}]}),
- %% check that `extra.erl` was compiled to the `ebin` dir
- %% check that `extraX.erl` was compiled to the `ebin` dir
- Ebin = filename:join([AppDir, "_build", "default", "lib", Name, "ebin"]),
- true = filelib:is_file(filename:join([Ebin, "extra.beam"])),
+ %% check that `extra.erl` was compiled to the `extra` dir
+ ExtraOut = filename:join([AppDir, "_build", "default", "lib", Name, "extra"]),
+ true = filelib:is_file(filename:join([ExtraOut, "extra.beam"])),
%% check that `extra.erl` is in the `modules` key of the app
{ok, App} = file:consult(filename:join([AppDir,
diff --git a/test/rebar_test_utils.erl b/test/rebar_test_utils.erl
index ca5e91a..3943db7 100644
--- a/test/rebar_test_utils.erl
+++ b/test/rebar_test_utils.erl
@@ -334,7 +334,7 @@ check_results(AppDir, Expected, ProfileRun) ->
{ok, RelxState3} = rlx_prv_rel_discover:do(RelxState2),
LibDir = filename:join([ReleaseDir, Name, "lib"]),
- {ok, RelLibs} = file:list_dir(LibDir),
+ {ok, RelLibs} = rebar_utils:list_dir(LibDir),
IsSymLinkFun =
fun(X) ->
ec_file:is_symlink(filename:join(LibDir, X))
@@ -357,6 +357,9 @@ check_results(AppDir, Expected, ProfileRun) ->
; ({file, Filename}) ->
ct:pal("Filename: ~s", [Filename]),
?assert(filelib:is_file(Filename))
+ ; ({dir, Dirname}) ->
+ ct:pal("Directory: ~s", [Dirname]),
+ ?assert(filelib:is_dir(Dirname))
end, Expected).
write_src_file(Dir, Name) ->
@@ -422,7 +425,7 @@ get_app_metadata(Name, Vsn, Deps) ->
package_app(AppDir, DestDir, PkgName) ->
Name = PkgName++".tar",
- {ok, Fs} = file:list_dir(AppDir),
+ {ok, Fs} = rebar_utils:list_dir(AppDir),
ok = erl_tar:create(filename:join(DestDir, "contents.tar.gz"),
lists:zip(Fs, [filename:join(AppDir,F) || F <- Fs]),
[compressed]),