diff options
-rw-r--r-- | src/rebar.hrl | 1 | ||||
-rw-r--r-- | src/rebar3.erl | 2 | ||||
-rw-r--r-- | src/rebar_app_discover.erl | 8 | ||||
-rw-r--r-- | src/rebar_app_info.erl | 24 | ||||
-rw-r--r-- | src/rebar_app_utils.erl | 13 | ||||
-rw-r--r-- | src/rebar_dir.erl | 28 | ||||
-rw-r--r-- | src/rebar_erlc_compiler.erl | 26 | ||||
-rw-r--r-- | src/rebar_file_utils.erl | 21 | ||||
-rw-r--r-- | src/rebar_otp_app.erl | 25 | ||||
-rw-r--r-- | src/rebar_prv_clean.erl | 2 | ||||
-rw-r--r-- | src/rebar_prv_common_test.erl | 5 | ||||
-rw-r--r-- | src/rebar_prv_compile.erl | 36 | ||||
-rw-r--r-- | src/rebar_prv_eunit.erl | 5 | ||||
-rw-r--r-- | src/rebar_prv_install_deps.erl | 14 | ||||
-rw-r--r-- | src/rebar_prv_xref.erl | 1 | ||||
-rw-r--r-- | src/rebar_state.erl | 16 | ||||
-rw-r--r-- | test/rebar_compile_SUITE.erl | 14 | ||||
-rw-r--r-- | test/rebar_test_utils.erl | 25 | ||||
-rw-r--r-- | test/rebar_xref_SUITE.erl | 5 |
19 files changed, 183 insertions, 88 deletions
diff --git a/src/rebar.hrl b/src/rebar.hrl index bbd9a2f..0dfcad0 100644 --- a/src/rebar.hrl +++ b/src/rebar.hrl @@ -14,7 +14,6 @@ -define(FMT(Str, Args), lists:flatten(io_lib:format(Str, Args))). -define(DEFAULT_BASE_DIR, "_build"). --define(DEFAULT_PROFILE_DIR, "default"). -define(DEFAULT_PROJECT_APP_DIRS, ["_checkouts", "apps", "lib", "."]). -define(DEFAULT_DEPS_DIR, "lib"). -define(DEFAULT_PLUGINS_DIR, "plugins"). diff --git a/src/rebar3.erl b/src/rebar3.erl index bd52fee..d7597cd 100644 --- a/src/rebar3.erl +++ b/src/rebar3.erl @@ -120,7 +120,7 @@ run_aux(State, GlobalPluginProviders, RawArgs) -> end, %% Process each command, resetting any state between each one - BaseDir = rebar_dir:base_dir(State2), + BaseDir = rebar_state:get(State, base_dir, ?DEFAULT_BASE_DIR), State3 = rebar_state:set(State2, base_dir, filename:join(filename:absname(rebar_state:dir(State2)), BaseDir)), 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 3962bf8..fd80fa7 100644 --- a/src/rebar_dir.erl +++ b/src/rebar_dir.erl @@ -14,16 +14,18 @@ get_cwd/0, template_globals/1, template_dir/1, - src_dirs/1, - ebin_dir/0, processing_base_dir/1, - processing_base_dir/2]). + processing_base_dir/2, + make_relative_path/2]). -include("rebar.hrl"). -spec base_dir(rebar_state:t()) -> file:filename_all(). base_dir(State) -> - rebar_state:get(State, base_dir, ?DEFAULT_BASE_DIR). + Profiles = rebar_state:current_profiles(State), + ProfilesStrings = [ec_cnv:to_list(P) || P <- Profiles], + ProfilesDir = string:join(ProfilesStrings, "+"), + filename:join(rebar_state:get(State, base_dir, ?DEFAULT_BASE_DIR), ProfilesDir). -spec deps_dir(rebar_state:t()) -> file:filename_all(). deps_dir(State) -> @@ -78,15 +80,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). @@ -94,3 +87,12 @@ processing_base_dir(State) -> processing_base_dir(State, Dir) -> AbsDir = filename:absname(Dir), AbsDir =:= rebar_state:get(State, base_dir). + +make_relative_path(Source, Target) -> + do_make_relative_path(filename:split(Source), filename:split(Target)). + +do_make_relative_path([H|T1], [H|T2]) -> + do_make_relative_path(T1, T2); +do_make_relative_path(Source, Target) -> + Base = lists:duplicate(max(length(Target) - 1, 0), ".."), + filename:join(Base ++ Source). 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_file_utils.erl b/src/rebar_file_utils.erl index 8fe8965..ef2c70f 100644 --- a/src/rebar_file_utils.erl +++ b/src/rebar_file_utils.erl @@ -26,7 +26,8 @@ %% ------------------------------------------------------------------- -module(rebar_file_utils). --export([rm_rf/1, +-export([symlink_or_copy/2, + rm_rf/1, cp_r/2, mv/2, delete_each/1, @@ -41,6 +42,22 @@ %% Public API %% =================================================================== +symlink_or_copy(Source, Target) -> + Link = case os:type() of + {win32, _} -> + Source; + _ -> + rebar_dir:make_relative_path(Source, Target) + end, + case file:make_symlink(Link, Target) of + ok -> + ok; + {error, eexist} -> + ok; + {error, _} -> + cp_r([Source], Target) + end. + %% @doc Remove files and directories. %% Target is a single filename, directoryname or wildcard expression. -spec rm_rf(string()) -> 'ok'. @@ -127,7 +144,7 @@ write_file_if_contents_differ(Filename, Bytes) -> end. %% returns an os appropriate tmpdir given a path --spec system_tmpdir() -> file:filename(). +-spec system_tmpdir() -> file:filename(). -spec system_tmpdir(PathComponents) -> file:filename() when PathComponents :: [file:name()]. diff --git a/src/rebar_otp_app.erl b/src/rebar_otp_app.erl index 49579ae..278d7e5 100644 --- a/src/rebar_otp_app.erl +++ b/src/rebar_otp_app.erl @@ -40,18 +40,19 @@ 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, %% Load the app file and validate it. validate_app(State, App1). +format_error(invalid_app_file) -> + "Failed to read app file"; format_error({file_read, File, Reason}) -> io_lib:format("Failed to read ~s for processing: ~p", [File, Reason]); format_error({invalid_name, File, AppName}) -> @@ -92,13 +93,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 +115,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 @@ -172,11 +176,16 @@ ensure_registered(AppData) -> %% config. However, in the case of *.app, rebar should not manipulate %% that file. This enforces that dichotomy between app and app.src. consult_app_file(Filename) -> - case lists:suffix(".app.src", Filename) of + case filelib:is_file(Filename) of false -> - file:consult(Filename); + throw(?PRV_ERROR(invalid_app_file)); true -> - {ok, rebar_config:consult_file(Filename)} + case lists:suffix(".app.src", Filename) of + false -> + file:consult(Filename); + true -> + {ok, rebar_config:consult_file(Filename)} + end end. app_vsn(AppFile) -> 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_common_test.erl b/src/rebar_prv_common_test.erl index b697d37..c3f9163 100644 --- a/src/rebar_prv_common_test.erl +++ b/src/rebar_prv_common_test.erl @@ -43,13 +43,14 @@ do(State) -> ?DEBUG("Compiling Common Test suites 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 `common_test_first_files` and %% adjust compile opts to include `common_test_compile_opts` %% and `{src_dirs, "test"}` TestState = test_state(S, InDirs, 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, InDirs, OutDir), Path = code:get_path(), @@ -342,7 +343,7 @@ maybe_compile_extra_tests(TestApps, State, InDirs, OutDir) -> [{src_dirs, ["test"|InDirs]}] ++ 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_compile.erl b/src/rebar_prv_compile.erl index c4cca16..bce4aab 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(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,29 @@ 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(OldAppDir, AppDir) -> + case ec_cnv:to_binary(filename:absname(OldAppDir)) =/= + ec_cnv:to_binary(filename:absname(AppDir)) of + true -> + EbinDir = filename:join([OldAppDir, "ebin"]), + %% 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); + false -> + ok + end, + filelib:ensure_dir(filename:join(AppDir, "dummy")), + %% link to src to be adjacent to ebin is needed for R15 use of cover/xref + [symlink_or_copy(OldAppDir, AppDir, Dir) || Dir <- ["priv", "include", "src", "test"]]; + false -> + ok + end. + +symlink_or_copy(OldAppDir, AppDir, Dir) -> + Source = filename:join(OldAppDir, Dir), + Target = filename:join(AppDir, Dir), + rebar_file_utils:symlink_or_copy(Source, Target). 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_install_deps.erl b/src/rebar_prv_install_deps.erl index ab4cca1..f702936 100644 --- a/src/rebar_prv_install_deps.erl +++ b/src/rebar_prv_install_deps.erl @@ -374,7 +374,15 @@ maybe_fetch(AppInfo, Upgrade, Seen, State) -> false -> case rebar_app_discover:find_app(AppDir, all) of false -> - fetch_app(AppInfo, AppDir, State); + case in_default(AppInfo, State) of + false -> + fetch_app(AppInfo, AppDir, State); + {true, FoundApp} -> + ?INFO("Linking ~s to ~s", [rebar_app_info:dir(FoundApp), AppDir]), + filelib:ensure_dir(AppDir), + rebar_file_utils:symlink_or_copy(rebar_app_info:dir(FoundApp), AppDir), + true + end; {true, _} -> case sets:is_element(rebar_app_info:name(AppInfo), Seen) of true -> @@ -392,6 +400,10 @@ in_checkouts(AppInfo) -> error -> false end. +in_default(AppInfo, State) -> + Name = ec_cnv:to_list(rebar_app_info:name(AppInfo)), + DefaultAppDir = filename:join([rebar_state:get(State, base_dir), "default", "lib", Name]), + rebar_app_discover:find_app(DefaultAppDir, all). -spec parse_deps(binary(), list(), list(), list(), integer()) -> {[rebar_app_info:t()], [pkg_dep()]}. parse_deps(DepsDir, Deps, State, Locks, Level) -> 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 2f8ab59..39e0e88 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) -> diff --git a/test/rebar_compile_SUITE.erl b/test/rebar_compile_SUITE.erl index 9a21986..924ce5c 100644 --- a/test/rebar_compile_SUITE.erl +++ b/test/rebar_compile_SUITE.erl @@ -77,7 +77,7 @@ build_checkout_apps(Config) -> build_checkout_deps(Config) -> AppDir = ?config(apps, Config), CheckoutsDir = ?config(checkouts, Config), - DepsDir = filename:join([AppDir, "_build", "lib"]), + 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(filename:join([AppDir,Name1]), Name1, Vsn1, [kernel, stdlib]), @@ -96,7 +96,6 @@ build_checkout_deps(Config) -> recompile_when_opts_change(Config) -> AppDir = ?config(apps, Config), - EbinDir = filename:join([AppDir, "ebin"]), Name = rebar_test_utils:create_random_name("app1_"), Vsn = rebar_test_utils:create_random_vsn(), @@ -104,6 +103,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), ModTime = [filelib:last_modified(filename:join([EbinDir, F])) || F <- Files, filename:extension(F) == ".beam"], @@ -123,7 +123,6 @@ recompile_when_opts_change(Config) -> dont_recompile_when_opts_dont_change(Config) -> AppDir = ?config(apps, Config), - EbinDir = filename:join([AppDir, "ebin"]), Name = rebar_test_utils:create_random_name("app1_"), Vsn = rebar_test_utils:create_random_vsn(), @@ -131,6 +130,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), ModTime = [filelib:last_modified(filename:join([EbinDir, F])) || F <- Files, filename:extension(F) == ".beam"], @@ -141,20 +141,20 @@ dont_recompile_when_opts_dont_change(Config) -> {ok, NewFiles} = file:list_dir(EbinDir), NewModTime = [filelib:last_modified(filename:join([EbinDir, F])) - || F <- NewFiles, filename:extension(F) == ".beam"], + || F <- NewFiles, filename:extension(F) == ".beam"], ?assert(ModTime == NewModTime). dont_recompile_yrl_or_xrl(Config) -> AppDir = ?config(apps, Config), - + 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]), Xrl = filename:join([AppDir, "src", "not_a_real_xrl_" ++ Name ++ ".xrl"]), ok = filelib:ensure_dir(Xrl), - XrlBody = + XrlBody = "Definitions." "\n\n" "D = [0-9]" @@ -182,4 +182,4 @@ dont_recompile_yrl_or_xrl(Config) -> NewModTime = filelib:last_modified(XrlBeam), - ?assert(ModTime == NewModTime).
\ No newline at end of file + ?assert(ModTime == NewModTime). diff --git a/test/rebar_test_utils.erl b/test/rebar_test_utils.erl index a036619..157c2df 100644 --- a/test/rebar_test_utils.erl +++ b/test/rebar_test_utils.erl @@ -142,17 +142,18 @@ top_level_deps([{{Name, Vsn, Ref}, _} | Deps]) -> %%% Helpers %%% %%%%%%%%%%%%%%% check_results(AppDir, Expected) -> - BuildDir = filename:join([AppDir, "_build", "lib"]), + BuildDirs = filelib:wildcard(filename:join([AppDir, "_build", "*", "lib"])), CheckoutsDir = filename:join([AppDir, "_checkouts"]), LockFile = filename:join([AppDir, "rebar.lock"]), Locks = lists:flatten(rebar_config:consult_file(LockFile)), - Apps = rebar_app_discover:find_apps([AppDir]), - InvalidApps = rebar_app_discover:find_apps([AppDir], invalid), - ValidApps = rebar_app_discover:find_apps([AppDir], valid), - AppsNames = [{ec_cnv:to_list(rebar_app_info:name(App)), App} || App <- Apps], - InvalidAppsNames = [{ec_cnv:to_list(rebar_app_info:name(App)), App} || App <- InvalidApps], - ValidAppsNames = [{ec_cnv:to_list(rebar_app_info:name(App)), App} || App <- ValidApps], - Deps = rebar_app_discover:find_apps([BuildDir], all), + + InvalidApps = rebar_app_discover:find_apps(BuildDirs, invalid), + ValidApps = rebar_app_discover:find_apps(BuildDirs, valid), + + InvalidDepsNames = [{ec_cnv:to_list(rebar_app_info:name(App)), App} || App <- InvalidApps], + ValidDepsNames = [{ec_cnv:to_list(rebar_app_info:name(App)), App} || App <- ValidApps], + + Deps = rebar_app_discover:find_apps(BuildDirs, all), DepsNames = [{ec_cnv:to_list(rebar_app_info:name(App)), App} || App <- Deps], Checkouts = rebar_app_discover:find_apps([CheckoutsDir], all), CheckoutsNames = [{ec_cnv:to_list(rebar_app_info:name(App)), App} || App <- Checkouts], @@ -160,7 +161,7 @@ check_results(AppDir, Expected) -> lists:foreach( fun({app, Name}) -> ct:pal("Name: ~p", [Name]), - case lists:keyfind(Name, 1, AppsNames) of + case lists:keyfind(Name, 1, DepsNames) of false -> error({app_not_found, Name}); {Name, _App} -> @@ -168,7 +169,7 @@ check_results(AppDir, Expected) -> end ; ({app, Name, invalid}) -> ct:pal("Name: ~p", [Name]), - case lists:keyfind(Name, 1, InvalidAppsNames) of + case lists:keyfind(Name, 1, InvalidDepsNames) of false -> error({app_not_found, Name}); {Name, _App} -> @@ -176,7 +177,7 @@ check_results(AppDir, Expected) -> end ; ({app, Name, valid}) -> ct:pal("Name: ~p", [Name]), - case lists:keyfind(Name, 1, ValidAppsNames) of + case lists:keyfind(Name, 1, ValidDepsNames) of false -> error({app_not_found, Name}); {Name, _App} -> @@ -217,7 +218,7 @@ check_results(AppDir, Expected) -> {ok, Cwd} = file:get_cwd(), try file:set_cwd(AppDir), - ReleaseDir = filename:join([AppDir, "_build", "rel"]), + [ReleaseDir] = filelib:wildcard(filename:join([AppDir, "_build", "*", "rel"])), RelxState = rlx_state:new("", [], []), RelxState1 = rlx_state:base_output_dir(RelxState, ReleaseDir), {ok, RelxState2} = rlx_prv_app_discover:do(RelxState1), diff --git a/test/rebar_xref_SUITE.erl b/test/rebar_xref_SUITE.erl index 067be07..1b1d6d7 100644 --- a/test/rebar_xref_SUITE.erl +++ b/test/rebar_xref_SUITE.erl @@ -57,8 +57,9 @@ end_per_testcase(_, Config) -> %% we are about to remove the directory and there may be %% subsequent test cases that error out when the code path tries %% to include one of these soon-to-be nonexistent directories. - code:del_path(AppDir ++ "/."), - true = code:del_path(rebar_dir:ebin_dir()), + Name = ?config(app_name, Config), + EbinDir = filename:join([AppDir, "_build", "default" "lib", Name, "ebin"]), + true = code:del_path(EbinDir), file:set_cwd(OrigDir), ec_file:remove(AppDir, [recursive]), ok. |