summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CONTRIBUTING.md4
-rw-r--r--README.md10
-rw-r--r--priv/templates/app.erl3
-rw-r--r--src/rebar3.erl21
-rw-r--r--src/rebar_prv_common_test.erl20
-rw-r--r--src/rebar_prv_dialyzer.erl2
-rw-r--r--src/rebar_prv_eunit.erl20
-rw-r--r--src/rebar_prv_packages.erl32
-rw-r--r--src/rebar_prv_path.erl8
-rw-r--r--src/rebar_prv_report.erl2
-rw-r--r--src/rebar_prv_shell.erl18
-rw-r--r--test/rebar_ct_SUITE.erl32
-rw-r--r--test/rebar_eunit_SUITE.erl43
-rw-r--r--test/rebar_profiles_SUITE.erl14
14 files changed, 170 insertions, 59 deletions
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index f175cc2..8077813 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -23,7 +23,7 @@ All files without specific headers can safely be assumed to be under Apache
## Submitting a Bug
-Bugs can be submitted to the [Github issue page](https://github.com/rebar/rebar3/issues).
+Bugs can be submitted to the [Github issue page](https://github.com/erlang/rebar3/issues).
Rebar3 is not perfect software and will be buggy. When submitting a bug, be
careful to know the following:
@@ -58,7 +58,7 @@ Before requesting or implementing a new feature, please do the following:
- Take a look at our [list of plugins](http://www.rebar3.org/docs/using-available-plugins)
to know if the feature isn't already supported by the community.
-- Verify in existing [tickets](https://github.com/rebar/rebar3/issues) whether
+- Verify in existing [tickets](https://github.com/erlang/rebar3/issues) whether
the feature might already is in the works, has been moved to a plugin, or
has already been rejected.
diff --git a/README.md b/README.md
index 6e5f102..7560ab0 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
# Rebar3
-[![Build Status](https://travis-ci.org/rebar/rebar3.svg?branch=master)](https://travis-ci.org/rebar/rebar3) [![Windows build status](https://ci.appveyor.com/api/projects/status/yx4oitd9pvd2kab3?svg=true)](https://ci.appveyor.com/project/TristanSloughter/rebar3)
+[![Build Status](https://travis-ci.org/erlang/rebar3.svg?branch=master)](https://travis-ci.org/erlang/rebar3) [![Windows build status](https://ci.appveyor.com/api/projects/status/yx4oitd9pvd2kab3?svg=true)](https://ci.appveyor.com/project/TristanSloughter/rebar3)
1. [What is Rebar3?](#what-is-rebar3)
2. [Why Rebar3?](#why-rebar3)
@@ -64,12 +64,12 @@ $ wget https://s3.amazonaws.com/rebar3/rebar3 && chmod +x rebar3
From Source (assuming you have a full Erlang install):
```bash
-$ git clone https://github.com/rebar/rebar3.git
+$ git clone https://github.com/erlang/rebar3.git
$ cd rebar3
$ ./bootstrap
```
-Stable versions can be obtained from the [releases page](https://github.com/rebar/rebar3/releases).
+Stable versions can be obtained from the [releases page](https://github.com/erlang/rebar3/releases).
The rebar3 escript can also extract itself with a run script under the user's home directory:
@@ -159,13 +159,13 @@ quick feedback, you can try the #rebar channel on
asking about things with well known answers.
For bug reports, roadmaps, and issues, visit the [github issues
-page](https://github.com/rebar/rebar3/issues).
+page](https://github.com/erlang/rebar3/issues).
General rebar community resources and links:
- [Rebar Mailing List](http://lists.basho.com/pipermail/rebar_lists.basho.com/)
- #rebar on [irc.freenode.net](http://freenode.net/)
-- [issues](https://github.com/rebar/rebar3/issues)
+- [issues](https://github.com/erlang/rebar3/issues)
- [Documentation](http://www.rebar3.org/v3.0/docs)
To contribute to rebar3, please refer to [CONTRIBUTING](CONTRIBUTING.md).
diff --git a/priv/templates/app.erl b/priv/templates/app.erl
index 83eb9a3..62d2ddf 100644
--- a/priv/templates/app.erl
+++ b/priv/templates/app.erl
@@ -8,8 +8,7 @@
-behaviour(application).
%% Application callbacks
--export([start/2
- ,stop/1]).
+-export([start/2, stop/1]).
%%====================================================================
%% API
diff --git a/src/rebar3.erl b/src/rebar3.erl
index ab7d35a..c1a1ae4 100644
--- a/src/rebar3.erl
+++ b/src/rebar3.erl
@@ -337,19 +337,18 @@ state_from_global_config(Config, GlobalConfigFile) ->
test_state(State) ->
ErlOpts = rebar_state:get(State, erl_opts, []),
- TestOpts = safe_define_test_macro(ErlOpts, 'TEST'),
- MoreTestOpts = safe_define_test_macro(ErlOpts, 'EUNIT'),
- [{extra_src_dirs, ["test"]}, {erl_opts, TestOpts ++ MoreTestOpts}].
+ TestOpts = safe_define_test_macro(ErlOpts),
+ [{extra_src_dirs, ["test"]}, {erl_opts, TestOpts}].
-safe_define_test_macro(Opts, Macro) ->
+safe_define_test_macro(Opts) ->
%% defining a compile macro twice results in an exception so
- %% make sure 'TEST' or 'EUNIT' is only defined once
- case test_defined(Opts, Macro) of
+ %% make sure 'TEST' is only defined once
+ case test_defined(Opts) of
true -> [];
- false -> [{d, Macro}]
+ false -> [{d, 'TEST'}]
end.
-test_defined([{d, Macro}|_], Macro) -> true;
-test_defined([{d, Macro, true}|_], Macro) -> true;
-test_defined([_|Rest], Macro) -> test_defined(Rest, Macro);
-test_defined([], _) -> false.
+test_defined([{d, 'TEST'}|_]) -> true;
+test_defined([{d, 'TEST', true}|_]) -> true;
+test_defined([_|Rest]) -> test_defined(Rest);
+test_defined([]) -> false.
diff --git a/src/rebar_prv_common_test.erl b/src/rebar_prv_common_test.erl
index 784b682..6b94f79 100644
--- a/src/rebar_prv_common_test.erl
+++ b/src/rebar_prv_common_test.erl
@@ -329,9 +329,27 @@ include_files(Opts, Tests) ->
Is = lists:map(fun(I) -> {i, I} end, Includes),
case append(Is, ErlOpts) of
{error, _} = Error -> Error;
- NewIncludes -> rebar_opts:set(Opts, erl_opts, NewIncludes)
+ NewIncludes -> ct_macro(rebar_opts:set(Opts, erl_opts, NewIncludes))
end.
+ct_macro(Opts) ->
+ ErlOpts = opts(Opts, erl_opts, []),
+ NewOpts = safe_define_ct_macro(ErlOpts),
+ rebar_opts:set(Opts, erl_opts, NewOpts).
+
+safe_define_ct_macro(Opts) ->
+ %% defining a compile macro twice results in an exception so
+ %% make sure 'COMMON_TEST' is only defined once
+ case test_defined(Opts) of
+ true -> Opts;
+ false -> [{d, 'COMMON_TEST'}|Opts]
+ end.
+
+test_defined([{d, 'COMMON_TEST'}|_]) -> true;
+test_defined([{d, 'COMMON_TEST', true}|_]) -> true;
+test_defined([_|Rest]) -> test_defined(Rest);
+test_defined([]) -> false.
+
append({error, _} = Error, _) -> Error;
append(_, {error, _} = Error) -> Error;
append(A, B) -> A ++ B.
diff --git a/src/rebar_prv_dialyzer.erl b/src/rebar_prv_dialyzer.erl
index 834eb98..622ee60 100644
--- a/src/rebar_prv_dialyzer.erl
+++ b/src/rebar_prv_dialyzer.erl
@@ -97,7 +97,7 @@ do(State) ->
end.
%% This is used to workaround dialyzer quirk discussed here
-%% https://github.com/rebar/rebar3/pull/489#issuecomment-107953541
+%% https://github.com/erlang/rebar3/pull/489#issuecomment-107953541
%% Dialyzer gets default plt location wrong way by peeking HOME environment
%% variable which usually is not defined on Windows.
maybe_fix_env() ->
diff --git a/src/rebar_prv_eunit.erl b/src/rebar_prv_eunit.erl
index c085ee4..46ea48d 100644
--- a/src/rebar_prv_eunit.erl
+++ b/src/rebar_prv_eunit.erl
@@ -244,9 +244,27 @@ first_files(Opts) ->
EUnitFirstFiles = opts(Opts, eunit_first_files, []),
case append(EUnitFirstFiles, FirstFiles) of
{error, _} = Error -> Error;
- NewFirstFiles -> rebar_opts:set(Opts, erl_first_files, NewFirstFiles)
+ NewFirstFiles -> eunit_macro(rebar_opts:set(Opts, erl_first_files, NewFirstFiles))
end.
+eunit_macro(Opts) ->
+ ErlOpts = opts(Opts, erl_opts, []),
+ NewOpts = safe_define_eunit_macro(ErlOpts),
+ rebar_opts:set(Opts, erl_opts, NewOpts).
+
+safe_define_eunit_macro(Opts) ->
+ %% defining a compile macro twice results in an exception so
+ %% make sure 'EUNIT' is only defined once
+ case test_defined(Opts) of
+ true -> Opts;
+ false -> [{d, 'EUNIT'}|Opts]
+ end.
+
+test_defined([{d, 'EUNIT'}|_]) -> true;
+test_defined([{d, 'EUNIT', true}|_]) -> true;
+test_defined([_|Rest]) -> test_defined(Rest);
+test_defined([]) -> false.
+
append({error, _} = Error, _) -> Error;
append(_, {error, _} = Error) -> Error;
append(A, B) -> A ++ B.
diff --git a/src/rebar_prv_packages.erl b/src/rebar_prv_packages.erl
index 998320c..7217ab8 100644
--- a/src/rebar_prv_packages.erl
+++ b/src/rebar_prv_packages.erl
@@ -28,22 +28,19 @@ init(State) ->
-spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}.
do(State) ->
rebar_packages:packages(State),
- print_packages(),
+ case rebar_state:command_args(State) of
+ [Name] ->
+ print_packages(get_packages(iolist_to_binary(Name)));
+ _ ->
+ print_packages(sort_packages())
+ end,
{ok, State}.
-spec format_error(any()) -> iolist().
format_error(load_registry_fail) ->
"Failed to load package regsitry. Try running 'rebar3 update' to fix".
-print_packages() ->
- SortedPkgs = ets:foldl(fun({package_index_version, _}, Acc) ->
- Acc;
- ({Pkg, Vsns}, Acc) ->
- orddict:store(Pkg, Vsns, Acc);
- (_, Acc) ->
- Acc
- end, orddict:new(), ?PACKAGE_TABLE),
-
+print_packages(Pkgs) ->
orddict:map(fun(Name, Vsns) ->
SortedVsns = lists:sort(fun(A, B) ->
ec_semver:lte(ec_semver:parse(A)
@@ -51,7 +48,20 @@ print_packages() ->
end, Vsns),
VsnStr = join(SortedVsns, <<", ">>),
?CONSOLE("~s:~n Versions: ~s~n", [Name, VsnStr])
- end, SortedPkgs).
+ end, Pkgs).
+
+sort_packages() ->
+ ets:foldl(fun({package_index_version, _}, Acc) ->
+ Acc;
+ ({Pkg, Vsns}, Acc) ->
+ orddict:store(Pkg, Vsns, Acc);
+ (_, Acc) ->
+ Acc
+ end, orddict:new(), ?PACKAGE_TABLE).
+
+get_packages(Name) ->
+ ets:lookup(?PACKAGE_TABLE, Name).
+
-spec join([binary()], binary()) -> binary().
join([Bin], _Sep) ->
diff --git a/src/rebar_prv_path.erl b/src/rebar_prv_path.erl
index 37c9834..4e88496 100644
--- a/src/rebar_prv_path.erl
+++ b/src/rebar_prv_path.erl
@@ -95,10 +95,14 @@ print_paths_if_exist(Paths, State) ->
project_deps(State) ->
Profiles = rebar_state:current_profiles(State),
- List = lists:foldl(fun(Profile, Acc) -> rebar_state:get(State, {deps, Profile}, []) ++ Acc end, [], Profiles),
- Deps = [normalize(Name) || {Name, _} <- List],
+ DepList = lists:foldl(fun(Profile, Acc) -> rebar_state:get(State, {deps, Profile}, []) ++ Acc end, [], Profiles),
+ LockList = lists:foldl(fun(Profile, Acc) -> rebar_state:get(State, {locks, Profile}, []) ++ Acc end, [], Profiles),
+ Deps = [normalize(name(Dep)) || Dep <- DepList++LockList],
lists:usort(Deps).
+name(App) when is_tuple(App) -> element(1, App);
+name(Name) when is_binary(Name); is_list(Name); is_atom(Name) -> Name.
+
normalize(AppName) when is_list(AppName) -> AppName;
normalize(AppName) when is_atom(AppName) -> atom_to_list(AppName);
normalize(AppName) when is_binary(AppName) -> binary_to_list(AppName).
diff --git a/src/rebar_prv_report.erl b/src/rebar_prv_report.erl
index 587fad7..d6c8b60 100644
--- a/src/rebar_prv_report.erl
+++ b/src/rebar_prv_report.erl
@@ -13,7 +13,7 @@
-define(PROVIDER, report).
-define(DEPS, []).
--define(ISSUES_URL, "https://github.com/rebar/rebar3/issues").
+-define(ISSUES_URL, "https://github.com/erlang/rebar3/issues").
%% ===================================================================
%% Public API
diff --git a/src/rebar_prv_shell.erl b/src/rebar_prv_shell.erl
index 430d1e8..d67f940 100644
--- a/src/rebar_prv_shell.erl
+++ b/src/rebar_prv_shell.erl
@@ -133,11 +133,25 @@ kill_old_user() ->
%% fully die
[P] = [P || P <- element(2,process_info(whereis(user), links)), is_port(P)],
user ! {'EXIT', P, normal}, % pretend the port died, then the port can die!
+ exit(P, kill),
+ wait_for_port_death(1000, P),
OldUser.
+wait_for_port_death(N, _) when N < 0 ->
+ %% This risks displaying a warning!
+ whatever;
+wait_for_port_death(N, P) ->
+ case erlang:port_info(P) of
+ undefined ->
+ ok;
+ _ ->
+ timer:sleep(10),
+ wait_for_port_death(N-10, P)
+ end.
+
setup_new_shell() ->
- %% terminate the current user supervision structure
- ok = supervisor:terminate_child(kernel_sup, user),
+ %% terminate the current user supervision structure, if any
+ _ = supervisor:terminate_child(kernel_sup, user),
%% start a new shell (this also starts a new user under the correct group)
_ = user_drv:start(),
%% wait until user_drv and user have been registered (max 3 seconds)
diff --git a/test/rebar_ct_SUITE.erl b/test/rebar_ct_SUITE.erl
index 0e0de2e..1da7571 100644
--- a/test/rebar_ct_SUITE.erl
+++ b/test/rebar_ct_SUITE.erl
@@ -6,8 +6,10 @@
end_per_group/2]).
-export([basic_app_default_dirs/1,
basic_app_default_beams/1,
+ basic_app_ct_macro/1,
multi_app_default_dirs/1,
multi_app_default_beams/1,
+ multi_app_ct_macro/1,
single_app_dir/1,
single_extra_dir/1,
single_unmanaged_dir/1,
@@ -65,9 +67,11 @@ all() -> [{group, basic_app},
misspecified_ct_first_files].
groups() -> [{basic_app, [], [basic_app_default_dirs,
- basic_app_default_beams]},
+ basic_app_default_beams,
+ basic_app_ct_macro]},
{multi_app, [], [multi_app_default_dirs,
- multi_app_default_beams]},
+ multi_app_default_beams,
+ multi_app_ct_macro]},
{dirs_and_suites, [], [single_app_dir,
single_extra_dir,
single_unmanaged_dir,
@@ -121,7 +125,7 @@ init_per_group(basic_app, Config) ->
{ok, T} = Tests,
Opts = rebar_prv_common_test:translate_paths(NewState, T),
- [{result, Opts}, {appnames, [Name]}|C];
+ [{result, Opts}, {appnames, [Name]}, {compile_state, NewState}|C];
init_per_group(multi_app, Config) ->
C = rebar_test_utils:init_rebar_state(Config, "ct_"),
@@ -156,7 +160,7 @@ init_per_group(multi_app, Config) ->
{ok, T} = Tests,
Opts = rebar_prv_common_test:translate_paths(NewState, T),
- [{result, Opts}, {appnames, [Name1, Name2]}|C];
+ [{result, Opts}, {appnames, [Name1, Name2]}, {compile_state, NewState}|C];
init_per_group(dirs_and_suites, Config) ->
C = rebar_test_utils:init_rebar_state(Config, "ct_"),
@@ -255,6 +259,15 @@ basic_app_default_beams(Config) ->
true = filelib:is_file(File).
+basic_app_ct_macro(Config) ->
+ State = ?config(compile_state, Config),
+
+ [App] = rebar_state:project_apps(State),
+ Opts = rebar_app_info:opts(App),
+ ErlOpts = dict:fetch(erl_opts, Opts),
+ true = lists:member({d, 'COMMON_TEST'}, ErlOpts).
+
+
multi_app_default_dirs(Config) ->
AppDir = ?config(apps, Config),
[Name1, Name2] = ?config(appnames, Config),
@@ -296,6 +309,16 @@ multi_app_default_beams(Config) ->
true = filelib:is_file(File2),
true = filelib:is_file(File3).
+multi_app_ct_macro(Config) ->
+ State = ?config(compile_state, Config),
+
+ Apps = rebar_state:project_apps(State),
+ lists:foreach(fun(App) ->
+ Opts = rebar_app_info:opts(App),
+ ErlOpts = dict:fetch(erl_opts, Opts),
+ true = lists:member({d, 'COMMON_TEST'}, ErlOpts)
+ end, Apps).
+
single_app_dir(Config) ->
AppDir = ?config(apps, Config),
[Name1, _Name2] = ?config(appnames, Config),
@@ -1158,6 +1181,7 @@ misspecified_ct_first_files(Config) ->
{badconfig, {"Value `~p' of option `~p' must be a list", {some_file, ct_first_files}}} = Error.
+
%% helper for generating test data
test_suite(Name) ->
io_lib:format("-module(~ts_SUITE).\n"
diff --git a/test/rebar_eunit_SUITE.erl b/test/rebar_eunit_SUITE.erl
index cb2c911..41ab6ff 100644
--- a/test/rebar_eunit_SUITE.erl
+++ b/test/rebar_eunit_SUITE.erl
@@ -2,8 +2,12 @@
-export([all/0, groups/0]).
-export([init_per_suite/1, init_per_group/2, end_per_group/2]).
--export([basic_app_compiles/1, basic_app_files/1, basic_app_exports/1, basic_app_testset/1]).
--export([multi_app_compiles/1, multi_app_files/1, multi_app_exports/1, multi_app_testset/1]).
+-export([basic_app_compiles/1, basic_app_files/1]).
+-export([basic_app_exports/1, basic_app_testset/1]).
+-export([basic_app_eunit_macro/1]).
+-export([multi_app_compiles/1, multi_app_files/1]).
+-export([multi_app_exports/1, multi_app_testset/1]).
+-export([multi_app_eunit_macro/1]).
-export([eunit_tests/1, eunit_opts/1, eunit_first_files/1]).
-export([single_application_arg/1, multi_application_arg/1, missing_application_arg/1]).
-export([single_module_arg/1, multi_module_arg/1, missing_module_arg/1]).
@@ -27,9 +31,15 @@ all() ->
groups() ->
[{basic_app, [sequence], [basic_app_compiles, {group, basic_app_results}]},
- {basic_app_results, [], [basic_app_files, basic_app_exports, basic_app_testset]},
+ {basic_app_results, [], [basic_app_files,
+ basic_app_exports,
+ basic_app_testset,
+ basic_app_eunit_macro]},
{multi_app, [sequence], [multi_app_compiles, {group, multi_app_results}]},
- {multi_app_results, [], [multi_app_files, multi_app_exports, multi_app_testset]},
+ {multi_app_results, [], [multi_app_files,
+ multi_app_exports,
+ multi_app_testset,
+ multi_app_eunit_macro]},
{cmd_line_args, [], [eunit_tests, eunit_opts, eunit_first_files,
single_application_arg, multi_application_arg, missing_application_arg,
single_module_arg, multi_module_arg, missing_module_arg,
@@ -160,7 +170,16 @@ basic_app_testset(Config) ->
{module, basic_app_tests_helper}]},
Set = rebar_prv_eunit:prepare_tests(Result).
-
+basic_app_eunit_macro(_Config) ->
+ Macro = fun(Mod) ->
+ begin
+ Path = code:which(Mod),
+ {ok, {Mod, [{compile_info, CompileInfo}]}} = beam_lib:chunks(Path, [compile_info]),
+ Opts = proplists:get_value(options, CompileInfo, []),
+ true = lists:member({d, 'EUNIT'}, Opts)
+ end
+ end,
+ lists:foreach(Macro, [basic_app, basic_app_tests, basic_app_tests_helper]).
%% === tests for multiple applications in the `apps' directory of a project ===
@@ -220,7 +239,19 @@ multi_app_testset(Config) ->
{module, multi_app_tests_helper}]},
Set = rebar_prv_eunit:prepare_tests(Result).
-
+multi_app_eunit_macro(_Config) ->
+ Macro = fun(Mod) ->
+ begin
+ Path = code:which(Mod),
+ {ok, {Mod, [{compile_info, CompileInfo}]}} = beam_lib:chunks(Path, [compile_info]),
+ Opts = proplists:get_value(options, CompileInfo, []),
+ true = lists:member({d, 'EUNIT'}, Opts)
+ end
+ end,
+ lists:foreach(Macro, [multi_app_bar, multi_app_bar_tests,
+ multi_app_baz, multi_app_baz_tests,
+ multi_app_tests, multi_app_tests_helper,
+ multi_app_bar_tests_helper, multi_app_baz_tests_helper]).
%% === tests for command line arguments ===
diff --git a/test/rebar_profiles_SUITE.erl b/test/rebar_profiles_SUITE.erl
index fb7b140..a31a4c9 100644
--- a/test/rebar_profiles_SUITE.erl
+++ b/test/rebar_profiles_SUITE.erl
@@ -377,8 +377,7 @@ test_profile_applied_at_completion(Config) ->
[App] = rebar_state:project_apps(State),
ErlOpts = rebar_app_info:get(App, erl_opts),
- true = lists:member({d, 'TEST'}, ErlOpts),
- true = lists:member({d, 'EUNIT'}, ErlOpts).
+ true = lists:member({d, 'TEST'}, ErlOpts).
test_profile_applied_before_compile(Config) ->
AppDir = ?config(apps, Config),
@@ -394,9 +393,7 @@ test_profile_applied_before_compile(Config) ->
code:add_paths(rebar_state:code_paths(State, all_deps)),
S = list_to_atom("not_a_real_src_" ++ Name),
- Opts = proplists:get_value(options, S:module_info(compile), []),
- true = lists:member({d, 'TEST'}, Opts),
- true = lists:member({d, 'EUNIT'}, Opts).
+ true = lists:member({d, 'TEST'}, proplists:get_value(options, S:module_info(compile), [])).
test_profile_applied_before_eunit(Config) ->
AppDir = ?config(apps, Config),
@@ -412,9 +409,7 @@ test_profile_applied_before_eunit(Config) ->
code:add_paths(rebar_state:code_paths(State, all_deps)),
T = list_to_atom("not_a_real_src_" ++ Name ++ "_tests"),
- Opts = proplists:get_value(options, T:module_info(compile), []),
- true = lists:member({d, 'TEST'}, Opts),
- true = lists:member({d, 'EUNIT'}, Opts).
+ true = lists:member({d, 'TEST'}, proplists:get_value(options, T:module_info(compile), [])).
test_profile_applied_to_apps(Config) ->
AppDir = ?config(apps, Config),
@@ -435,6 +430,5 @@ test_profile_applied_to_apps(Config) ->
lists:foreach(fun(App) ->
Opts = rebar_app_info:opts(App),
ErlOpts = dict:fetch(erl_opts, Opts),
- true = lists:member({d, 'TEST'}, ErlOpts),
- true = lists:member({d, 'EUNIT'}, ErlOpts)
+ true = lists:member({d, 'TEST'}, ErlOpts)
end, Apps).