summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/rebar_app_discover.erl8
-rw-r--r--src/rebar_app_info.erl24
-rw-r--r--src/rebar_app_utils.erl13
-rw-r--r--src/rebar_dir.erl11
-rw-r--r--src/rebar_erlc_compiler.erl26
-rw-r--r--src/rebar_otp_app.erl12
-rw-r--r--src/rebar_prv_clean.erl2
-rw-r--r--src/rebar_prv_compile.erl30
-rw-r--r--src/rebar_prv_eunit.erl5
-rw-r--r--src/rebar_prv_xref.erl1
-rw-r--r--src/rebar_state.erl16
11 files changed, 93 insertions, 55 deletions
diff --git a/src/rebar_app_discover.erl b/src/rebar_app_discover.erl
index f6ed91b..761c09e 100644
--- a/src/rebar_app_discover.erl
+++ b/src/rebar_app_discover.erl
@@ -14,14 +14,18 @@ do(State, LibDirs) ->
Dirs = [filename:join(BaseDir, LibDir) || LibDir <- LibDirs],
Apps = find_apps(Dirs, all),
ProjectDeps = rebar_state:deps_names(State),
+ DepsDir = rebar_dir:deps_dir(State),
%% Sort apps so we get the same merged deps config everytime
SortedApps = rebar_utils:sort_deps(Apps),
lists:foldl(fun(AppInfo, StateAcc) ->
StateAcc1 = merge_deps(AppInfo, StateAcc),
- ProjectDeps1 = lists:delete(rebar_app_info:name(AppInfo), ProjectDeps),
+ Name = rebar_app_info:name(AppInfo),
+ OutDir = filename:join(DepsDir, Name),
+ AppInfo1 = rebar_app_info:out_dir(AppInfo, OutDir),
+ ProjectDeps1 = lists:delete(Name, ProjectDeps),
rebar_state:project_apps(StateAcc1
- ,rebar_app_info:deps(AppInfo, ProjectDeps1))
+ ,rebar_app_info:deps(AppInfo1, ProjectDeps1))
end, State, SortedApps).
format_error({module_list, File}) ->
diff --git a/src/rebar_app_info.erl b/src/rebar_app_info.erl
index 7a01307..172170d 100644
--- a/src/rebar_app_info.erl
+++ b/src/rebar_app_info.erl
@@ -28,6 +28,8 @@
dep_level/2,
dir/1,
dir/2,
+ out_dir/1,
+ out_dir/2,
source/1,
source/2,
state/1,
@@ -48,6 +50,7 @@
profiles=[default] :: atom(),
dep_level=0 :: integer(),
dir :: file:name(),
+ out_dir :: file:name(),
source :: string() | tuple() | undefined,
state :: rebar_state:t() | undefined,
valid :: boolean()}).
@@ -79,7 +82,8 @@ new(AppName, Vsn) ->
new(AppName, Vsn, Dir) ->
{ok, #app_info_t{name=ec_cnv:to_binary(AppName),
original_vsn=Vsn,
- dir=ec_cnv:to_list(Dir)}}.
+ dir=ec_cnv:to_list(Dir),
+ out_dir=ec_cnv:to_list(Dir)}}.
%% @doc build a complete version of the app info with all fields set.
-spec new(atom() | binary() | string(), binary() | string(), file:name(), list()) ->
@@ -88,6 +92,7 @@ new(AppName, Vsn, Dir, Deps) ->
{ok, #app_info_t{name=ec_cnv:to_binary(AppName),
original_vsn=Vsn,
dir=ec_cnv:to_list(Dir),
+ out_dir=ec_cnv:to_list(Dir),
deps=Deps}}.
%% @doc discover a complete version of the app info with all fields set.
@@ -133,7 +138,7 @@ app_file_src(AppInfo=#app_info_t{}, AppFileSrc) ->
AppInfo#app_info_t{app_file_src=ec_cnv:to_list(AppFileSrc)}.
-spec app_file(t()) -> file:filename_all() | undefined.
-app_file(#app_info_t{app_file=undefined, dir=Dir, name=Name}) ->
+app_file(#app_info_t{app_file=undefined, out_dir=Dir, name=Name}) ->
AppFile = filename:join([ec_cnv:to_list(Dir), "ebin", ec_cnv:to_list(Name)++".app"]),
case filelib:is_file(AppFile) of
true ->
@@ -199,12 +204,23 @@ dir(#app_info_t{dir=Dir}) ->
Dir.
-spec dir(t(), file:name()) -> t().
+dir(AppInfo=#app_info_t{out_dir=undefined}, Dir) ->
+ AppInfo#app_info_t{dir=ec_cnv:to_list(Dir),
+ out_dir=ec_cnv:to_list(Dir)};
dir(AppInfo=#app_info_t{}, Dir) ->
AppInfo#app_info_t{dir=ec_cnv:to_list(Dir)}.
+-spec out_dir(t()) -> file:name().
+out_dir(#app_info_t{out_dir=OutDir}) ->
+ OutDir.
+
+-spec out_dir(t(), file:name()) -> t().
+out_dir(AppInfo=#app_info_t{}, OutDir) ->
+ AppInfo#app_info_t{out_dir=ec_cnv:to_list(OutDir)}.
+
-spec ebin_dir(t()) -> file:name().
-ebin_dir(#app_info_t{dir=Dir}) ->
- filename:join(Dir, "ebin").
+ebin_dir(#app_info_t{out_dir=OutDir}) ->
+ ec_cnv:to_list(filename:join(OutDir, "ebin")).
-spec source(t(), string() | tuple()) -> t().
source(AppInfo=#app_info_t{}, Source) ->
diff --git a/src/rebar_app_utils.erl b/src/rebar_app_utils.erl
index cd1124a..143d73d 100644
--- a/src/rebar_app_utils.erl
+++ b/src/rebar_app_utils.erl
@@ -29,9 +29,10 @@
-export([find/2,
find/3,
is_app_src/1,
- app_src_to_app/1,
+ app_src_to_app/2,
validate_application_info/1,
- validate_application_info/2]).
+ validate_application_info/2,
+ format_error/1]).
-include("rebar.hrl").
-include_lib("providers/include/providers.hrl").
@@ -56,9 +57,8 @@ is_app_src(Filename) ->
%% this is an .app.src file.
Filename =/= filename:rootname(Filename, ".app.src").
-app_src_to_app(Filename) ->
- Path = filename:join(rebar_utils:droplast(filename:split(filename:dirname(Filename)))),
- AppFile = filename:join([Path, "ebin", filename:basename(Filename, ".app.src") ++ ".app"]),
+app_src_to_app(OutDir, Filename) ->
+ AppFile = filename:join([OutDir, "ebin", filename:basename(Filename, ".app.src") ++ ".app"]),
filelib:ensure_dir(AppFile),
AppFile.
@@ -81,6 +81,9 @@ validate_application_info(AppInfo, AppDetail) ->
end
end.
+format_error(Error) ->
+ io_lib:format("~p", [Error]).
+
%% ===================================================================
%% Internal functions
%% ===================================================================
diff --git a/src/rebar_dir.erl b/src/rebar_dir.erl
index 388b4c6..acf79cd 100644
--- a/src/rebar_dir.erl
+++ b/src/rebar_dir.erl
@@ -14,8 +14,6 @@
get_cwd/0,
template_globals/1,
template_dir/1,
- src_dirs/1,
- ebin_dir/0,
processing_base_dir/1,
processing_base_dir/2]).
@@ -81,15 +79,6 @@ template_globals(State) ->
template_dir(State) ->
filename:join([global_config_dir(State), "templates"]).
--spec src_dirs([string()]) -> [file:filename(), ...].
-src_dirs([]) ->
- ["src"];
-src_dirs(SrcDirs) ->
- SrcDirs.
-
-ebin_dir() ->
- filename:join(get_cwd(), "ebin").
-
processing_base_dir(State) ->
Cwd = get_cwd(),
processing_base_dir(State, Cwd).
diff --git a/src/rebar_erlc_compiler.erl b/src/rebar_erlc_compiler.erl
index ce15ab0..9157e2a 100644
--- a/src/rebar_erlc_compiler.erl
+++ b/src/rebar_erlc_compiler.erl
@@ -26,7 +26,7 @@
%% -------------------------------------------------------------------
-module(rebar_erlc_compiler).
--export([compile/2,
+-export([compile/3,
clean/2]).
-include("rebar.hrl").
@@ -79,8 +79,8 @@
%% 'old_inets'}]}.
%%
--spec compile(rebar_state:t(), file:name()) -> 'ok'.
-compile(Config, Dir) ->
+-spec compile(rebar_state:t(), file:name(), file:name()) -> 'ok'.
+compile(Config, Dir, OutDir) ->
rebar_base_compiler:run(Config,
check_files(rebar_state:get(
Config, xrl_first_files, [])),
@@ -96,7 +96,7 @@ compile(Config, Dir) ->
Config, mib_first_files, [])),
filename:join(Dir, "mibs"), ".mib", filename:join([Dir, "priv", "mibs"]), ".bin",
fun compile_mib/3),
- doterl_compile(Config, Dir).
+ doterl_compile(Config, Dir, OutDir).
-spec clean(rebar_state:t(), file:filename()) -> 'ok'.
clean(Config, AppDir) ->
@@ -128,21 +128,19 @@ clean(Config, AppDir) ->
%% Internal functions
%% ===================================================================
--spec doterl_compile(rebar_state:t(), file:filename()) -> ok.
-doterl_compile(State, Dir) ->
+-spec doterl_compile(rebar_state:t(), file:filename(), file:filename()) -> ok.
+doterl_compile(State, Dir, ODir) ->
ErlOpts = rebar_utils:erl_opts(State),
- doterl_compile(State, Dir, [], ErlOpts).
+ doterl_compile(State, Dir, ODir, [], ErlOpts).
-doterl_compile(Config, Dir, MoreSources, ErlOpts) ->
- OutDir = filename:join(Dir, "ebin"),
+doterl_compile(Config, Dir, ODir, MoreSources, ErlOpts) ->
+ OutDir = filename:join(ODir, "ebin"),
ErlFirstFilesConf = rebar_state:get(Config, erl_first_files, []),
?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 = lists:map(fun(X) ->
- filename:join(Dir, X)
- end, rebar_dir:src_dirs(proplists:append_values(src_dirs, ErlOpts))),
+ SrcDirs = [filename:join(Dir, X) || X <- proplists:get_value(src_dirs, ErlOpts, ["src"])],
AllErlFiles = gather_src(SrcDirs, []) ++ MoreSources,
%% Issue: rebar/rebar3#140 (fix matching based on same path + order of
@@ -152,9 +150,9 @@ doterl_compile(Config, Dir, MoreSources, ErlOpts) ->
not lists:member(File, ErlFirstFiles) ],
%% Make sure that ebin/ exists and is on the path
- ok = filelib:ensure_dir(filename:join([Dir, "ebin", "dummy.beam"])),
+ ok = filelib:ensure_dir(filename:join(OutDir, "dummy.beam")),
CurrPath = code:get_path(),
- true = code:add_path(filename:absname(filename:join(Dir, "ebin"))),
+ true = code:add_path(filename:absname(OutDir)),
OutDir1 = proplists:get_value(outdir, ErlOpts, OutDir),
G = init_erlcinfo(Config, AllErlFiles),
%% Split RestErls so that files which are depended on are treated
diff --git a/src/rebar_otp_app.erl b/src/rebar_otp_app.erl
index 49579ae..f55ac6e 100644
--- a/src/rebar_otp_app.erl
+++ b/src/rebar_otp_app.erl
@@ -40,12 +40,11 @@ compile(State, App) ->
%% If we get an .app.src file, it needs to be pre-processed and
%% written out as a ebin/*.app file. That resulting file will then
%% be validated as usual.
- Dir = ec_cnv:to_list(rebar_app_info:dir(App)),
App1 = case rebar_app_info:app_file_src(App) of
undefined ->
App;
AppFileSrc ->
- File = preprocess(State, Dir, AppFileSrc),
+ File = preprocess(State, App, AppFileSrc),
rebar_app_info:app_file(App, File)
end,
@@ -92,13 +91,14 @@ validate_app_modules(State, App, AppData) ->
{ok, rebar_app_info:original_vsn(App, AppVsn)}
end.
-preprocess(State, Dir, AppSrcFile) ->
+preprocess(State, AppInfo, AppSrcFile) ->
case consult_app_file(AppSrcFile) of
{ok, [{application, AppName, AppData}]} ->
%% Look for a configuration file with vars we want to
%% substitute. Note that we include the list of modules available in
%% ebin/ and update the app data accordingly.
- AppVars = load_app_vars(State) ++ [{modules, ebin_modules(Dir)}],
+ OutDir = rebar_app_info:out_dir(AppInfo),
+ AppVars = load_app_vars(State) ++ [{modules, ebin_modules(OutDir)}],
A1 = apply_app_vars(AppVars, AppData),
%% AppSrcFile may contain instructions for generating a vsn number
@@ -113,7 +113,9 @@ preprocess(State, Dir, AppSrcFile) ->
Spec = io_lib:format("~p.\n", [{application, AppName, A3}]),
%% Setup file .app filename and write new contents
- AppFile = rebar_app_utils:app_src_to_app(AppSrcFile),
+ EbinDir = rebar_app_info:ebin_dir(AppInfo),
+ filelib:ensure_dir(filename:join(EbinDir, "dummy.beam")),
+ AppFile = rebar_app_utils:app_src_to_app(OutDir, AppSrcFile),
ok = rebar_file_utils:write_file_if_contents_differ(AppFile, Spec),
%% Make certain that the ebin/ directory is available
diff --git a/src/rebar_prv_clean.erl b/src/rebar_prv_clean.erl
index ccd126b..d670e4d 100644
--- a/src/rebar_prv_clean.erl
+++ b/src/rebar_prv_clean.erl
@@ -72,7 +72,7 @@ clean_apps(State, Apps) ->
?INFO("Cleaning out ~s...", [rebar_app_info:name(AppInfo)]),
%% Legacy hook support
rebar_hooks:run_compile_hooks(AppDir, pre_hooks, clean, S),
- rebar_erlc_compiler:clean(State, ec_cnv:to_list(rebar_app_info:dir(AppInfo))),
+ rebar_erlc_compiler:clean(State, rebar_app_info:out_dir(AppInfo)),
rebar_hooks:run_compile_hooks(AppDir, post_hooks, clean, S)
end, Apps).
diff --git a/src/rebar_prv_compile.erl b/src/rebar_prv_compile.erl
index c4cca16..2d11596 100644
--- a/src/rebar_prv_compile.erl
+++ b/src/rebar_prv_compile.erl
@@ -69,6 +69,10 @@ build_apps(State, Apps) ->
build_app(State, AppInfo) ->
AppDir = rebar_app_info:dir(AppInfo),
+ OutDir = rebar_app_info:out_dir(AppInfo),
+
+ copy_app_dirs(rebar_app_info:name(AppInfo), AppDir, OutDir),
+
S = case rebar_app_info:state(AppInfo) of
undefined ->
C = rebar_config:consult(AppDir),
@@ -81,12 +85,13 @@ build_app(State, AppInfo) ->
rebar_hooks:run_compile_hooks(AppDir, pre_hooks, compile, S),
AppInfo1 = compile(S, AppInfo),
rebar_hooks:run_compile_hooks(AppDir, post_hooks, compile, S),
- true = code:add_patha(filename:join(AppDir, "ebin")),
+
+ true = code:add_patha(rebar_app_info:ebin_dir(AppInfo1)),
AppInfo1.
compile(State, AppInfo) ->
?INFO("Compiling ~s", [rebar_app_info:name(AppInfo)]),
- rebar_erlc_compiler:compile(State, ec_cnv:to_list(rebar_app_info:dir(AppInfo))),
+ rebar_erlc_compiler:compile(State, ec_cnv:to_list(rebar_app_info:dir(AppInfo)), ec_cnv:to_list(rebar_app_info:out_dir(AppInfo))),
case rebar_otp_app:compile(State, AppInfo) of
{ok, AppInfo1} ->
AppInfo1;
@@ -94,7 +99,6 @@ compile(State, AppInfo) ->
throw(Error)
end.
-
%% ===================================================================
%% Internal functions
%% ===================================================================
@@ -103,3 +107,23 @@ handle_args(State) ->
{Args, _} = rebar_state:command_parsed_args(State),
Jobs = proplists:get_value(jobs, Args, ?DEFAULT_JOBS),
{ok, rebar_state:set(State, jobs, Jobs)}.
+
+copy_app_dirs(AppName, OldAppDir, AppDir) ->
+ case ec_cnv:to_binary(filename:absname(OldAppDir)) =/=
+ ec_cnv:to_binary(filename:absname(AppDir)) of
+ true ->
+ Name = ec_cnv:to_list(AppName),
+ AppFile = filename:join([OldAppDir, "ebin", Name++".app"]),
+ case filelib:is_file(AppFile) of
+ true ->
+ file:copy(AppFile,
+ filename:join([AppDir, "ebin", Name++".app"]));
+ false ->
+ ok
+ end,
+ filelib:ensure_dir(filename:join(AppDir, "dummy")),
+ [file:make_symlink(filename:join(OldAppDir, Dir), filename:join(AppDir, Dir))
+ || Dir <- ["priv", "include"]];
+ false ->
+ ok
+ end.
diff --git a/src/rebar_prv_eunit.erl b/src/rebar_prv_eunit.erl
index 13d00b9..cd1b0f8 100644
--- a/src/rebar_prv_eunit.erl
+++ b/src/rebar_prv_eunit.erl
@@ -42,13 +42,14 @@ do(State) ->
?DEBUG("Compiling EUnit instrumented modules in: ~p", [OutDir]),
lists:foreach(fun(App) ->
AppDir = rebar_app_info:dir(App),
+ AppOutDir = rebar_app_info:out_dir(App),
C = rebar_config:consult(AppDir),
S = rebar_state:new(State, C, AppDir),
%% combine `erl_first_files` and `eunit_first_files` and adjust
%% compile opts to include `eunit_compile_opts`, `{d, 'TEST'}`
%% and `{src_dirs, "test"}`
TestState = first_files(test_state(S, OutDir)),
- ok = rebar_erlc_compiler:compile(TestState, AppDir)
+ ok = rebar_erlc_compiler:compile(TestState, AppDir, AppOutDir)
end, TestApps),
ok = maybe_compile_extra_tests(TestApps, State, OutDir),
Path = code:get_path(),
@@ -167,7 +168,7 @@ maybe_compile_extra_tests(TestApps, State, OutDir) ->
[{src_dirs, ["test"]}] ++
safe_define_test_macro(lists:keydelete(src_dirs, 1, ErlOpts)),
TestState = first_files(rebar_state:set(State, erl_opts, TestOpts)),
- rebar_erlc_compiler:compile(TestState, rebar_dir:get_cwd());
+ rebar_erlc_compiler:compile(TestState, rebar_dir:get_cwd(), rebar_dir:get_cwd());
%% already compiled `./test` so do nothing
_ -> ok
end.
diff --git a/src/rebar_prv_xref.erl b/src/rebar_prv_xref.erl
index 49ae70e..142f8fd 100644
--- a/src/rebar_prv_xref.erl
+++ b/src/rebar_prv_xref.erl
@@ -102,7 +102,6 @@ prepare(State) ->
%% Save the code path prior to doing any further code path
%% manipulation
OriginalPath = code:get_path(),
- true = code:add_path(rebar_dir:ebin_dir()),
%% Get list of xref checks we want to run
ConfXrefChecks = rebar_state:get(State, xref_checks,
diff --git a/src/rebar_state.erl b/src/rebar_state.erl
index 09f1c43..9aafa8a 100644
--- a/src/rebar_state.erl
+++ b/src/rebar_state.erl
@@ -97,6 +97,7 @@ new(ParentState, Config, Dir) ->
D = proplists:get_value(deps, Config, []),
dict:from_list([{{deps, default}, D} | Config])
end,
+
NewOpts = dict:merge(fun(_Key, Value1, _Value2) ->
Value1
end, LocalOpts, Opts),
@@ -193,13 +194,14 @@ apply_profiles(State, [default]) ->
State;
apply_profiles(State=#state_t{opts=Opts, current_profiles=CurrentProfiles}, Profiles) ->
ConfigProfiles = rebar_state:get(State, profiles, []),
- NewOpts = lists:foldl(fun(default, OptsAcc) ->
- OptsAcc;
- (Profile, OptsAcc) ->
- ProfileOpts = dict:from_list(proplists:get_value(Profile, ConfigProfiles, [])),
- merge_opts(Profile, ProfileOpts, OptsAcc)
- end, Opts, Profiles),
- State#state_t{current_profiles=CurrentProfiles++Profiles, opts=NewOpts}.
+ {Profiles1, NewOpts} =
+ lists:foldl(fun(default, {ProfilesAcc, OptsAcc}) ->
+ {ProfilesAcc, OptsAcc};
+ (Profile, {ProfilesAcc, OptsAcc}) ->
+ ProfileOpts = dict:from_list(proplists:get_value(Profile, ConfigProfiles, [])),
+ {[Profile]++ProfilesAcc, merge_opts(Profile, ProfileOpts, OptsAcc)}
+ end, {[], Opts}, Profiles),
+ State#state_t{current_profiles=CurrentProfiles++Profiles1, opts=NewOpts}.
merge_opts(Profile, NewOpts, OldOpts) ->
Opts = dict:merge(fun(_Key, NewValue, OldValue) when is_list(NewValue) ->