diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/rebar.erl | 56 | ||||
-rw-r--r-- | src/rebar_abnfc_compiler.erl | 17 | ||||
-rw-r--r-- | src/rebar_appups.erl | 10 | ||||
-rw-r--r-- | src/rebar_asn1_compiler.erl | 20 | ||||
-rw-r--r-- | src/rebar_base_compiler.erl | 2 | ||||
-rw-r--r-- | src/rebar_cleaner.erl | 17 | ||||
-rw-r--r-- | src/rebar_core.erl | 113 | ||||
-rw-r--r-- | src/rebar_ct.erl | 49 | ||||
-rw-r--r-- | src/rebar_deps.erl | 36 | ||||
-rw-r--r-- | src/rebar_dia_compiler.erl | 20 | ||||
-rw-r--r-- | src/rebar_edoc.erl | 11 | ||||
-rw-r--r-- | src/rebar_erlc_compiler.erl | 43 | ||||
-rw-r--r-- | src/rebar_erlydtl_compiler.erl | 31 | ||||
-rw-r--r-- | src/rebar_escripter.erl | 27 | ||||
-rw-r--r-- | src/rebar_eunit.erl | 39 | ||||
-rw-r--r-- | src/rebar_lfe_compiler.erl | 11 | ||||
-rw-r--r-- | src/rebar_neotoma_compiler.erl | 16 | ||||
-rw-r--r-- | src/rebar_otp_app.erl | 20 | ||||
-rw-r--r-- | src/rebar_port_compiler.erl | 31 | ||||
-rw-r--r-- | src/rebar_protobuffs_compiler.erl | 21 | ||||
-rw-r--r-- | src/rebar_qc.erl | 17 | ||||
-rw-r--r-- | src/rebar_reltool.erl | 29 | ||||
-rw-r--r-- | src/rebar_require_vsn.erl | 22 | ||||
-rw-r--r-- | src/rebar_templater.erl | 48 | ||||
-rw-r--r-- | src/rebar_upgrade.erl | 10 | ||||
-rw-r--r-- | src/rebar_utils.erl | 2 | ||||
-rw-r--r-- | src/rebar_xref.erl | 19 |
27 files changed, 656 insertions, 81 deletions
diff --git a/src/rebar.erl b/src/rebar.erl index c872ade..ded5ebe 100644 --- a/src/rebar.erl +++ b/src/rebar.erl @@ -76,8 +76,18 @@ run(BaseConfig, Commands) -> %% Internal functions %% ==================================================================== +run(["help"|RawCmds]) when RawCmds =/= [] -> + ok = load_rebar_app(), + Cmds = unabbreviate_command_names(RawCmds), + Args = parse_args(Cmds), + BaseConfig = init_config(Args), + {BaseConfig1, _} = save_options(BaseConfig, Args), + BaseConfig2 = init_config1(BaseConfig1), + rebar_core:help(BaseConfig2, [list_to_atom(C) || C <- Cmds]); run(["help"]) -> help(); +run(["info"|_]) -> + help(); run(["version"]) -> ok = load_rebar_app(), %% Display vsn and build time info @@ -138,6 +148,16 @@ init_config({Options, _NonOptArgs}) -> %% Initialize vsn cache rebar_config:set_xconf(BaseConfig1, vsn_cache, dict:new()). +init_config1(BaseConfig) -> + %% Determine the location of the rebar executable; important for pulling + %% resources out of the escript + ScriptName = filename:absname(escript:script_name()), + BaseConfig1 = rebar_config:set_xconf(BaseConfig, escript, ScriptName), + ?DEBUG("Rebar location: ~p\n", [ScriptName]), + %% Note the top-level directory for reference + AbsCwd = filename:absname(rebar_utils:get_cwd()), + rebar_config:set_xconf(BaseConfig1, base_dir, AbsCwd). + run_aux(BaseConfig, Commands) -> %% Make sure crypto is running case crypto:start() of @@ -148,18 +168,10 @@ run_aux(BaseConfig, Commands) -> %% Convert command strings to atoms CommandAtoms = [list_to_atom(C) || C <- Commands], - %% Determine the location of the rebar executable; important for pulling - %% resources out of the escript - ScriptName = filename:absname(escript:script_name()), - BaseConfig1 = rebar_config:set_xconf(BaseConfig, escript, ScriptName), - ?DEBUG("Rebar location: ~p\n", [ScriptName]), - - %% Note the top-level directory for reference - AbsCwd = filename:absname(rebar_utils:get_cwd()), - BaseConfig2 = rebar_config:set_xconf(BaseConfig1, base_dir, AbsCwd), + BaseConfig1 = init_config1(BaseConfig), %% Process each command, resetting any state between each one - rebar_core:process_commands(CommandAtoms, BaseConfig2). + rebar_core:process_commands(CommandAtoms, BaseConfig1). %% %% print help/usage string @@ -169,7 +181,29 @@ help() -> getopt:usage(OptSpecList, "rebar", "[var=value,...] <command,...>", [{"var=value", "rebar global variables (e.g. force=1)"}, - {"command", "Command to run (e.g. compile)"}]). + {"command", "Command to run (e.g. compile)"}]), + ?CONSOLE( + "Core rebar.config options:~n" + " ~p~n" + " ~p~n" + " ~p~n" + " ~p~n" + " ~p~n" + " ~p~n", + [ + {lib_dirs, []}, + {sub_dirs, ["dir1", "dir2"]}, + {plugins, [plugin1, plugin2]}, + {plugin_dir, "some_other_directory"}, + {pre_hooks, [{clean, "./prepare_package_files.sh"}, + {"linux", compile, "c_src/build_linux.sh"}, + {compile, "escript generate_headers"}, + {compile, "escript check_headers"}]}, + {post_hooks, [{clean, "touch file1.out"}, + {"freebsd", compile, "c_src/freebsd_tweaks.sh"}, + {eunit, "touch file2.out"}, + {compile, "touch postcompile.out"}]} + ]). %% %% Parse command line arguments using getopt and also filtering out any diff --git a/src/rebar_abnfc_compiler.erl b/src/rebar_abnfc_compiler.erl index 0e6749a..37731b5 100644 --- a/src/rebar_abnfc_compiler.erl +++ b/src/rebar_abnfc_compiler.erl @@ -47,6 +47,9 @@ -export([compile/2]). +%% for internal use only +-export([info/2]). + -include("rebar.hrl"). %% =================================================================== @@ -62,11 +65,23 @@ compile(Config, _AppFile) -> option(module_ext, DtlOpts) ++ ".erl", fun compile_abnfc/3). - %% =================================================================== %% Internal functions %% =================================================================== +info(help, compile) -> + ?CONSOLE( + "Build ABNF (*.abnf) sources.~n" + "~n" + "Valid rebar.config options:~n" + " ~p~n", + [ + {abnfc_opts, [{doc_root, "src"}, + {out_dir, "src"}, + {source_ext, ".abnfc"}, + {module_ext, ""}]} + ]). + abnfc_opts(Config) -> rebar_config:get(Config, abnfc_opts, []). diff --git a/src/rebar_appups.erl b/src/rebar_appups.erl index 0aeccb6..722f161 100644 --- a/src/rebar_appups.erl +++ b/src/rebar_appups.erl @@ -31,6 +31,9 @@ -export(['generate-appups'/2]). +%% for internal use only +-export([info/2]). + -define(APPUPFILEFORMAT, "%% appup generated for ~p by rebar (~p)~n" "{~p, [{~p, ~p}], [{~p, []}]}.~n"). @@ -82,6 +85,13 @@ %% Internal functions %% =================================================================== +info(help, 'generate-appups') -> + ?CONSOLE("Generate appup files.~n" + "~n" + "Valid command line options:~n" + " previous_release=path~n", + []). + get_apps(Name, OldVerPath, NewVerPath) -> OldApps = rebar_rel_utils:get_rel_apps(Name, OldVerPath), ?DEBUG("Old Version Apps: ~p~n", [OldApps]), diff --git a/src/rebar_asn1_compiler.erl b/src/rebar_asn1_compiler.erl index d93a2e8..25e3fd3 100644 --- a/src/rebar_asn1_compiler.erl +++ b/src/rebar_asn1_compiler.erl @@ -30,6 +30,9 @@ -export([compile/2, clean/2]). +%% for internal use only +-export([info/2]). + -include("rebar.hrl"). %% =================================================================== @@ -48,6 +51,23 @@ clean(_Config, _AppFile) -> ok = rebar_file_utils:delete_each(GeneratedFiles), ok. +%% =================================================================== +%% Internal functions +%% =================================================================== + +info(help, compile) -> + info_help("Build ASN.1 (*.asn1) sources"); +info(help, clean) -> + info_help("Delete ASN.1 (*.asn1) results"). + +info_help(Description) -> + ?CONSOLE( + "~s.~n" + "~n" + "Valid rebar.config options:~n" + " {asn1_opts, []} (see asn1ct:compile/2 documentation)~n", + [Description]). + -spec compile_asn1(file:filename(), file:filename(), rebar_config:config()) -> ok. compile_asn1(Source, Target, Config) -> diff --git a/src/rebar_base_compiler.erl b/src/rebar_base_compiler.erl index 260cdaf..a0dec30 100644 --- a/src/rebar_base_compiler.erl +++ b/src/rebar_base_compiler.erl @@ -226,6 +226,8 @@ format_warnings(Config, Source, Warnings, Opts) -> maybe_report([{error, {error, _Es, _Ws}=ErrorsAndWarnings}, {source, _}]) -> maybe_report(ErrorsAndWarnings); +maybe_report([{error, E}, {source, S}]) -> + report(["unexpected error compiling " ++ S, io_lib:fwrite("~n~p~n", [E])]); maybe_report({error, Es, Ws}) -> report(Es), report(Ws); diff --git a/src/rebar_cleaner.erl b/src/rebar_cleaner.erl index 9ddeb8a..7a762f5 100644 --- a/src/rebar_cleaner.erl +++ b/src/rebar_cleaner.erl @@ -28,6 +28,9 @@ -export([clean/2]). +%% for internal use only +-export([info/2]). + -include("rebar.hrl"). %% =================================================================== @@ -37,3 +40,17 @@ clean(Config, _AppFile) -> %% Get a list of files to delete from config and remove them FilesToClean = rebar_config:get(Config, clean_files, []), lists:foreach(fun (F) -> rebar_file_utils:rm_rf(F) end, FilesToClean). + +%% =================================================================== +%% Internal functions +%% =================================================================== + +info(help, clean) -> + ?CONSOLE( + "Delete list of files.~n" + "~n" + "Valid rebar.config options:~n" + " ~p~n", + [ + {clean_files, ["file", "file2"]} + ]). diff --git a/src/rebar_core.erl b/src/rebar_core.erl index 5396dd5..3172d64 100644 --- a/src/rebar_core.erl +++ b/src/rebar_core.erl @@ -26,7 +26,7 @@ %% ------------------------------------------------------------------- -module(rebar_core). --export([process_commands/2]). +-export([process_commands/2, help/2]). -include("rebar.hrl"). @@ -34,6 +34,35 @@ %% Internal functions %% =================================================================== +help(ParentConfig, Commands) -> + %% get all core modules + {ok, AnyDirModules} = application:get_env(rebar, any_dir_modules), + {ok, RawCoreModules} = application:get_env(rebar, modules), + AppDirModules = proplists:get_value(app_dir, RawCoreModules), + RelDirModules = proplists:get_value(rel_dir, RawCoreModules), + CoreModules = AnyDirModules ++ AppDirModules ++ RelDirModules, + + %% get plugin modules + Predirs = [], + Dir = rebar_utils:get_cwd(), + PredirsAssoc = remember_cwd_predirs(Dir, Predirs), + Config = maybe_load_local_config(Dir, ParentConfig), + {ok, PluginModules} = plugin_modules(Config, PredirsAssoc), + + AllModules = CoreModules ++ PluginModules, + + lists:foreach( + fun(Cmd) -> + ?CONSOLE("==> help ~p~n~n", [Cmd]), + CmdModules = select_modules(AllModules, Cmd, []), + Modules = select_modules(CmdModules, info, []), + lists:foreach(fun(M) -> + ?CONSOLE("=== ~p:~p ===~n", [M, Cmd]), + M:info(help, Cmd), + ?CONSOLE("~n", []) + end, Modules) + end, Commands). + process_commands([], ParentConfig) -> AbortTrapped = rebar_config:get_xconf(ParentConfig, abort_trapped, false), case {get_operations(ParentConfig), AbortTrapped} of @@ -110,21 +139,21 @@ process_dir(Dir, ParentConfig, Command, DirSet) -> {ok, AvailModuleSets} = application:get_env(rebar, modules), ModuleSet = choose_module_set(AvailModuleSets, Dir), skip_or_process_dir(ModuleSet, Config, CurrentCodePath, - Dir, Command, DirSet) + Dir, Command, DirSet) end. skip_or_process_dir({[], undefined}=ModuleSet, Config, CurrentCodePath, - Dir, Command, DirSet) -> + Dir, Command, DirSet) -> process_dir1(Dir, Command, DirSet, Config, CurrentCodePath, ModuleSet); skip_or_process_dir({_, ModuleSetFile}=ModuleSet, Config, CurrentCodePath, - Dir, Command, DirSet) -> + Dir, Command, DirSet) -> case lists:suffix(".app.src", ModuleSetFile) orelse lists:suffix(".app", ModuleSetFile) of true -> %% .app or .app.src file, check if is_skipped_app skip_or_process_dir1(ModuleSetFile, ModuleSet, - Config, CurrentCodePath, Dir, - Command, DirSet); + Config, CurrentCodePath, Dir, + Command, DirSet); false -> %% not an app dir, no need to consider apps=/skip_apps= process_dir1(Dir, Command, DirSet, Config, @@ -132,7 +161,7 @@ skip_or_process_dir({_, ModuleSetFile}=ModuleSet, Config, CurrentCodePath, end. skip_or_process_dir1(AppFile, ModuleSet, Config, CurrentCodePath, - Dir, Command, DirSet) -> + Dir, Command, DirSet) -> case rebar_app_utils:is_skipped_app(Config, AppFile) of {Config1, {true, SkippedApp}} -> ?DEBUG("Skipping app: ~p~n", [SkippedApp]), @@ -158,11 +187,12 @@ process_dir1(Dir, Command, DirSet, Config0, CurrentCodePath, {Config1, Predirs} = acc_modules(Modules, preprocess, Config0, ModuleSetFile), - SubdirAssoc = remember_cwd_subdir(Dir, Predirs), + %% Remember associated pre-dirs (used for plugin lookup) + PredirsAssoc = remember_cwd_predirs(Dir, Predirs), %% Get the list of plug-in modules from rebar.config. These %% modules may participate in preprocess and postprocess. - {ok, PluginModules} = plugin_modules(Config1, SubdirAssoc), + {ok, PluginModules} = plugin_modules(Config1, PredirsAssoc), {Config2, PluginPredirs} = acc_modules(PluginModules, preprocess, Config1, ModuleSetFile), @@ -224,7 +254,7 @@ process_dir1(Dir, Command, DirSet, Config0, CurrentCodePath, %% Return the updated {config, dirset} as result Res. -remember_cwd_subdir(Cwd, Subdirs) -> +remember_cwd_predirs(Cwd, Predirs) -> Store = fun(Dir, Dict) -> case dict:find(Dir, Dict) of error -> @@ -235,11 +265,10 @@ remember_cwd_subdir(Cwd, Subdirs) -> ?ABORT("Internal consistency assertion failed.~n" "sub_dir ~s already associated with ~s.~n" "Duplicate sub_dirs or deps entries?", - [Dir, Existing]), - Dict + [Dir, Existing]) end end, - lists:foldl(Store, dict:new(), Subdirs). + lists:foldl(Store, dict:new(), Predirs). maybe_load_local_config(Dir, ParentConfig) -> %% We need to ensure we don't overwrite custom @@ -459,9 +488,9 @@ acc_modules([Module | Rest], Command, Config, File, Acc) -> %% %% Return a flat list of rebar plugin modules. %% -plugin_modules(Config, SubdirAssoc) -> +plugin_modules(Config, PredirsAssoc) -> Modules = lists:flatten(rebar_config:get_all(Config, plugins)), - plugin_modules(Config, SubdirAssoc, ulist(Modules)). + plugin_modules(Config, PredirsAssoc, ulist(Modules)). ulist(L) -> ulist(L, []). @@ -476,16 +505,16 @@ ulist([H | T], Acc) -> ulist(T, [H | Acc]) end. -plugin_modules(_Config, _SubdirAssoc, []) -> +plugin_modules(_Config, _PredirsAssoc, []) -> {ok, []}; -plugin_modules(Config, SubdirAssoc, Modules) -> +plugin_modules(Config, PredirsAssoc, Modules) -> FoundModules = [M || M <- Modules, code:which(M) =/= non_existing], - plugin_modules(Config, SubdirAssoc, FoundModules, Modules -- FoundModules). + plugin_modules(Config, PredirsAssoc, FoundModules, Modules -- FoundModules). -plugin_modules(_Config, _SubdirAssoc, FoundModules, []) -> +plugin_modules(_Config, _PredirsAssoc, FoundModules, []) -> {ok, FoundModules}; -plugin_modules(Config, SubdirAssoc, FoundModules, MissingModules) -> - {Loaded, NotLoaded} = load_plugin_modules(Config, SubdirAssoc, +plugin_modules(Config, PredirsAssoc, FoundModules, MissingModules) -> + {Loaded, NotLoaded} = load_plugin_modules(Config, PredirsAssoc, MissingModules), AllViablePlugins = FoundModules ++ Loaded, case NotLoaded =/= [] of @@ -499,37 +528,43 @@ plugin_modules(Config, SubdirAssoc, FoundModules, MissingModules) -> end, {ok, AllViablePlugins}. -load_plugin_modules(Config, SubdirAssoc, Modules) -> +load_plugin_modules(Config, PredirsAssoc, Modules) -> Cwd = rebar_utils:get_cwd(), - PluginDir = case rebar_config:get_local(Config, plugin_dir, undefined) of - undefined -> - filename:join(Cwd, "plugins"); - Dir -> - Dir - end, + PluginDirs = case rebar_config:get_local(Config, plugin_dir, undefined) of + undefined -> + % Plugin can be in the project's "plugins" folder + [filename:join(Cwd, "plugins")]; + Dir -> + [Dir] + end ++ + % We also want to include this case: + % Plugin can be in "plugins" directory of the plugin base directory. For + % example, Cwd depends on Plugin, and deps/Plugin/plugins/Plugin.erl is the + % plugin. + [ + filename:join(Dir, "plugins") || + Dir <- get_plugin_base_dirs(Cwd, PredirsAssoc) + ], %% Find relevant sources in base_dir and plugin_dir Erls = string:join([atom_to_list(M)++"\\.erl" || M <- Modules], "|"), RE = "^" ++ Erls ++ "\$", - BaseDir = get_plugin_base_dir(Cwd, SubdirAssoc), %% If a plugin is found both in base_dir and plugin_dir, the clash %% will provoke an error and we'll abort. - Sources = rebar_utils:find_files(PluginDir, RE, false) - ++ rebar_utils:find_files(BaseDir, RE, false), + Sources = [rebar_utils:find_files(PD, RE, false) || PD <- PluginDirs], %% Compile and load plugins - Loaded = [load_plugin(Src) || Src <- Sources], + Loaded = [load_plugin(Src) || Src <- lists:append(Sources)], FilterMissing = is_missing_plugin(Loaded), NotLoaded = [V || V <- Modules, FilterMissing(V)], {Loaded, NotLoaded}. -get_plugin_base_dir(Cwd, SubdirAssoc) -> - case dict:find(Cwd, SubdirAssoc) of - {ok, BaseDir} -> - BaseDir; - error -> - Cwd - end. +%% @doc PredirsAssoc is a dictionary of plugindir -> 'parent' pairs +%% 'parent' in this case depends on plugin; therefore we have to give +%% all plugins that Cwd ('parent' in this case) depends on. +get_plugin_base_dirs(Cwd, PredirsAssoc) -> + [PluginDir || {PluginDir, Master} <- dict:to_list(PredirsAssoc), + Master =:= Cwd]. is_missing_plugin(Loaded) -> fun(Mod) -> not lists:member(Mod, Loaded) end. diff --git a/src/rebar_ct.erl b/src/rebar_ct.erl index 749d025..9951f8e 100644 --- a/src/rebar_ct.erl +++ b/src/rebar_ct.erl @@ -39,6 +39,9 @@ -export([ct/2]). +%% for internal use only +-export([info/2]). + -include("rebar.hrl"). %% =================================================================== @@ -53,6 +56,26 @@ ct(Config, File) -> %% =================================================================== %% Internal functions %% =================================================================== + +info(help, ct) -> + ?CONSOLE( + "Run common_test suites.~n" + "~n" + "Valid rebar.config options:~n" + " ~p~n" + " ~p~n" + " ~p~n" + " ~p~n" + "Valid command line options:~n" + " suites=foo,bar - run <test>/foo_SUITE and <test>/bar_SUITE~n" + " case=\"mycase\" - run individual test case foo_SUITE:mycase~n", + [ + {ct_dir, "itest"}, + {ct_log_dir, "test/logs"}, + {ct_extra_params, "-boot start_sasl -s myapp"}, + {ct_use_short_names, true} + ]). + run_test_if_present(TestDir, LogDir, Config, File) -> case filelib:is_dir(TestDir) of false -> @@ -85,8 +108,16 @@ run_test(TestDir, LogDir, Config, _File) -> " 2>&1 | tee -a " ++ RawLog end, - rebar_utils:sh(Cmd ++ Output, [{env,[{"TESTDIR", TestDir}]}]), - check_log(Config, RawLog). + case rebar_utils:sh(Cmd ++ Output, [{env,[{"TESTDIR", TestDir}]}, return_on_error]) of + {ok,_} -> + %% in older versions of ct_run, this could have been a failure + %% that returned a non-0 code. Check for that! + check_success_log(Config, RawLog); + {error,Res} -> + %% In newer ct_run versions, this may be a sign of a good compile + %% that failed cases. In older version, it's a worse error. + check_fail_log(Config, RawLog, Cmd ++ Output, Res) + end. clear_log(LogDir, RawLog) -> case filelib:ensure_dir(filename:join(LogDir, "index.html")) of @@ -101,7 +132,16 @@ clear_log(LogDir, RawLog) -> %% calling ct with erl does not return non-zero on failure - have to check %% log results -check_log(Config, RawLog) -> +check_success_log(Config, RawLog) -> + check_log(Config, RawLog, fun(Msg) -> ?CONSOLE("DONE.\n~s\n", [Msg]) end). + +check_fail_log(Config, RawLog, Command, {Rc, Output}) -> + check_log(Config, RawLog, fun(_Msg) -> + ?ABORT("~s failed with error: ~w and output:~n~s~n", + [Command, Rc, Output]) + end). + +check_log(Config,RawLog,Fun) -> {ok, Msg} = rebar_utils:sh("grep -e 'TEST COMPLETE' -e '{error,make_failed}' " ++ RawLog, [{use_stdout, false}]), @@ -119,9 +159,10 @@ check_log(Config, RawLog) -> ?FAIL; true -> - ?CONSOLE("DONE.\n~s\n", [Msg]) + Fun(Msg) end. + %% Show the log if it hasn't already been shown because verbose was on show_log(Config, RawLog) -> ?CONSOLE("Showing log\n", []), diff --git a/src/rebar_deps.erl b/src/rebar_deps.erl index 074e929..313deaa 100644 --- a/src/rebar_deps.erl +++ b/src/rebar_deps.erl @@ -38,6 +38,8 @@ 'delete-deps'/2, 'list-deps'/2]). +%% for internal use only +-export([info/2]). -record(dep, { dir, app, @@ -203,6 +205,40 @@ do_check_deps(Config) -> %% Internal functions %% =================================================================== +info(help, compile) -> + info_help("Display to be fetched dependencies"); +info(help, 'check-deps') -> + info_help("Display to be fetched dependencies"); +info(help, 'get-deps') -> + info_help("Fetch dependencies"); +info(help, 'update-deps') -> + info_help("Update fetched dependencies"); +info(help, 'delete-deps') -> + info_help("Delete fetched dependencies"); +info(help, 'list-deps') -> + info_help("List dependencies"). + +info_help(Description) -> + ?CONSOLE( + "~s.~n" + "~n" + "Valid rebar.config options:~n" + " ~p~n" + " ~p~n" + "Valid command line options:~n" + " deps_dir=\"deps\" (override default or rebar.config deps_dir)~n", + [ + Description, + {deps_dir, "deps"}, + {deps, [application_name, + {application_name, "1.0.*"}, + {application_name, "1.0.*", + {git, "git://github.com/rebar/rebar.git", {branch, "master"}}}, + {application_name, "", + {git, "git://github.com/rebar/rebar.git", {branch, "master"}}, + [raw]}]} + ]). + %% Added because of trans deps, %% need all deps in same dir and should be the one set by the root rebar.config %% Sets a default if root config has no deps_dir set diff --git a/src/rebar_dia_compiler.erl b/src/rebar_dia_compiler.erl index 51c075b..f81c734 100644 --- a/src/rebar_dia_compiler.erl +++ b/src/rebar_dia_compiler.erl @@ -28,6 +28,9 @@ -export([compile/2, clean/2]). +%% for internal use only +-export([info/2]). + -include("rebar.hrl"). %% =================================================================== @@ -46,6 +49,23 @@ clean(_Config, _AppFile) -> ok = rebar_file_utils:delete_each(GeneratedFiles), ok. +%% =================================================================== +%% Internal functions +%% =================================================================== + +info(help, compile) -> + info_help("Build Diameter (*.dia) sources"); +info(help, clean) -> + info_help("Delete generated Diameter files"). + +info_help(Description) -> + ?CONSOLE( + "~s.~n" + "~n" + "Valid rebar.config options:~n" + " {dia_opts, []} (see diameter_codegen:from_dict/4 documentation)~n", + [Description]). + -spec compile_dia(file:filename(), file:filename(), rebar_config:config()) -> ok. compile_dia(Source, Target, Config) -> diff --git a/src/rebar_edoc.erl b/src/rebar_edoc.erl index cf0239c..c828d27 100644 --- a/src/rebar_edoc.erl +++ b/src/rebar_edoc.erl @@ -39,6 +39,9 @@ -export([doc/2]). +%% for internal use only +-export([info/2]). + -include("rebar.hrl"). %% =================================================================== @@ -71,6 +74,14 @@ doc(Config, File) -> %% Internal functions %% =================================================================== +info(help, doc) -> + ?CONSOLE( + "Generate Erlang program documentation.~n" + "~n" + "Valid rebar.config options:~n" + " {edoc_opts, []} (see edoc:application/3 documentation)~n", + []). + setup_code_path() -> %% Setup code path prior to calling edoc so that edown, asciiedoc, %% and the like can work properly when generating their own diff --git a/src/rebar_erlc_compiler.erl b/src/rebar_erlc_compiler.erl index 91f8354..caef0d2 100644 --- a/src/rebar_erlc_compiler.erl +++ b/src/rebar_erlc_compiler.erl @@ -29,8 +29,9 @@ -export([compile/2, clean/2]). -%% for internal use by only eunit and qc --export([test_compile/3]). +%% for internal use only +-export([test_compile/3, + info/2]). -include("rebar.hrl"). @@ -116,8 +117,6 @@ clean(_Config, _AppFile) -> test_compile(Config, Cmd, OutDir) -> %% Obtain all the test modules for inclusion in the compile stage. - %% Notice: this could also be achieved with the following - %% rebar.config option: {test_compile_opts, [{src_dirs, ["src", "test"]}]} TestErls = rebar_utils:find_files("test", ".*\\.erl\$"), %% Copy source files to eunit dir for cover in case they are not directly @@ -165,6 +164,42 @@ test_compile(Config, Cmd, OutDir) -> %% Internal functions %% =================================================================== +info(help, compile) -> + info_help("Build *.erl, *.yrl, *.xrl, and *.mib sources"); +info(help, clean) -> + info_help("Delete *.erl, *.yrl, *.xrl, and *.mib build results"). + +info_help(Description) -> + ?CONSOLE( + "~s.~n" + "~n" + "Valid rebar.config options:~n" + " ~p~n" + " ~p~n" + " ~p~n" + " ~p~n" + " ~p~n" + " ~p~n" + " ~p~n" + " ~p~n", + [ + Description, + {erl_opts, [no_debug_info, + {i, "myinclude"}, + {src_dirs, ["src", "src2", "src3"]}, + {platform_define, + "(linux|solaris|freebsd|darwin)", 'HAVE_SENDFILE'}, + {platform_define, "(linux|freebsd)", 'BACKLOG', 128}, + {platform_define, "R13", 'old_inets'}]}, + {erl_first_files, ["mymib1", "mymib2"]}, + {mib_opts, []}, + {mib_first_files, []}, + {xrl_opts, []}, + {xrl_first_files, []}, + {yrl_opts, []}, + {yrl_first_files, []} + ]). + test_compile_config(Config, Cmd) -> {Config1, TriqOpts} = triq_opts(Config), {Config2, PropErOpts} = proper_opts(Config1), diff --git a/src/rebar_erlydtl_compiler.erl b/src/rebar_erlydtl_compiler.erl index aef41c5..4449be6 100644 --- a/src/rebar_erlydtl_compiler.erl +++ b/src/rebar_erlydtl_compiler.erl @@ -96,6 +96,9 @@ -export([compile/2]). +%% for internal use only +-export([info/2]). + -include("rebar.hrl"). %% =================================================================== @@ -123,11 +126,24 @@ compile(Config, _AppFile) -> true = code:set_path(OrigPath), Result. - %% =================================================================== %% Internal functions %% =================================================================== +info(help, compile) -> + ?CONSOLE( + "Build ErlyDtl (*.dtl) sources.~n" + "~n" + "Valid rebar.config options:~n" + " ~p~n", + [ + {erlydtl_opts, [{doc_root, "templates"}, + {out_dir, "ebin"}, + {source_ext, ".dtl"}, + {module_ext, "_dtl"}, + {recursive, true}]} + ]). + erlydtl_opts(Config) -> Opts = rebar_config:get(Config, erlydtl_opts, []), Tuples = [{K,V} || {K,V} <- Opts], @@ -135,11 +151,14 @@ erlydtl_opts(Config) -> [] -> [lists:keysort(1, Tuples)]; Lists -> - lists:map(fun(L) -> - lists:keysort(1, lists:foldl(fun({K,T}, Acc) -> - lists:keystore(K, 1, Acc, {K, T}) - end, Tuples, L)) - end, Lists) + lists:map( + fun(L) -> + lists:keysort(1, + lists:foldl( + fun({K,T}, Acc) -> + lists:keystore(K, 1, Acc, {K, T}) + end, Tuples, L)) + end, Lists) end. option(Opt, DtlOpts) -> diff --git a/src/rebar_escripter.erl b/src/rebar_escripter.erl index 706cf7c..0cc43ef 100644 --- a/src/rebar_escripter.erl +++ b/src/rebar_escripter.erl @@ -29,6 +29,9 @@ -export([escriptize/2, clean/2]). +%% for internal use only +-export([info/2]). + -include("rebar.hrl"). -include_lib("kernel/include/file.hrl"). @@ -108,6 +111,30 @@ clean(Config0, AppFile) -> %% Internal functions %% =================================================================== +info(help, escriptize) -> + info_help("Generate escript archive"); +info(help, clean) -> + info_help("Delete generated escript archive"). + +info_help(Description) -> + ?CONSOLE( + "~s.~n" + "~n" + "Valid rebar.config options:~n" + " ~p~n" + " ~p~n" + " ~p~n" + " ~p~n" + " ~p~n", + [ + Description, + {escript_name, "application"}, + {escript_incl_apps, []}, + {escript_shebang, "#!/usr/bin/env escript\n"}, + {escript_comment, "%%\n"}, + {escript_emu_args, "%%! -pa application/application/ebin\n"} + ]). + get_app_beams([], Acc) -> Acc; get_app_beams([App | Rest], Acc) -> diff --git a/src/rebar_eunit.erl b/src/rebar_eunit.erl index a7f4aca..cdc0787 100644 --- a/src/rebar_eunit.erl +++ b/src/rebar_eunit.erl @@ -61,7 +61,7 @@ %% Additionally, for projects that have separate folders for the core %% implementation, and for the unit tests, then the following %% <code>rebar.config</code> option can be provided: -%% <code>{test_compile_opts, [{src_dirs, ["dir"]}]}.</code>. +%% <code>{eunit_compile_opts, [{src_dirs, ["src", "dir"]}]}.</code>. %% @copyright 2009, 2010 Dave Smith %% ------------------------------------------------------------------- -module(rebar_eunit). @@ -69,6 +69,9 @@ -export([eunit/2, clean/2]). +%% for internal use only +-export([info/2]). + -include("rebar.hrl"). -define(EUNIT_DIR, ".eunit"). @@ -100,6 +103,40 @@ clean(_Config, _File) -> %% Internal functions %% =================================================================== +info(help, eunit) -> + info_help("Run eunit tests"); +info(help, clean) -> + Description = ?FMT("Delete eunit test dir (~s)", [?EUNIT_DIR]), + info_help(Description). + +info_help(Description) -> + ?CONSOLE( + "~s.~n" + "~n" + "Valid rebar.config options:~n" + " ~p~n" + " ~p~n" + " ~p~n" + " ~p~n" + " ~p~n" + " ~p~n" + "Valid command line options:~n" + " suites=\"foo,bar\" (Run tests in foo.erl, test/foo_tests.erl and~n" + " tests in bar.erl, test/bar_tests.erl)~n" + " tests=\"baz\" (For every existing suite, run the first test whose~n" + " name starts with bar and, if no such test exists,~n" + " run the test whose name starts with bar in the~n" + " suite's _tests module)~n", + [ + Description, + {eunit_opts, []}, + {eunit_compile_opts, []}, + {eunit_first_files, []}, + {cover_enabled, false}, + {cover_print_enabled, false}, + {cover_export_enabled, false} + ]). + run_eunit(Config, CodePath, SrcErls) -> %% Build a list of all the .beams in ?EUNIT_DIR -- use this for %% cover and eunit testing. Normally you can just tell cover diff --git a/src/rebar_lfe_compiler.erl b/src/rebar_lfe_compiler.erl index d288ca5..2a047d8 100644 --- a/src/rebar_lfe_compiler.erl +++ b/src/rebar_lfe_compiler.erl @@ -30,6 +30,9 @@ -export([compile/2]). +%% for internal use only +-export([info/2]). + -include("rebar.hrl"). %% =================================================================== @@ -45,6 +48,14 @@ compile(Config, _AppFile) -> %% Internal functions %% =================================================================== +info(help, compile) -> + ?CONSOLE( + "Build Lisp Flavoured Erlang (*.lfe) sources.~n" + "~n" + "Valid rebar.config options:~n" + " erl_opts is reused.'~n", + []). + compile_lfe(Source, _Target, Config) -> case code:which(lfe_comp) of non_existing -> diff --git a/src/rebar_neotoma_compiler.erl b/src/rebar_neotoma_compiler.erl index 33f32e3..5607aa4 100644 --- a/src/rebar_neotoma_compiler.erl +++ b/src/rebar_neotoma_compiler.erl @@ -42,6 +42,9 @@ -export([compile/2]). +%% for internal use only +-export([info/2]). + -include("rebar.hrl"). %% ============================================================================ @@ -60,6 +63,19 @@ compile(Config, _AppFile) -> %% Internal functions %% ============================================================================ +info(help, compile) -> + ?CONSOLE( + "Build Neotoma (*.peg) sources.~n" + "~n" + "Valid rebar.config options:~n" + " ~p~n", + [ + {neotom_opts, [{doc_root, "src"}, + {out_dir, "src"}, + {source_ext, ".peg"}, + {module_ext, ""}]} + ]). + neotoma_opts(Config) -> rebar_config:get(Config, neotoma_opts, []). diff --git a/src/rebar_otp_app.erl b/src/rebar_otp_app.erl index a62f584..6c52336 100644 --- a/src/rebar_otp_app.erl +++ b/src/rebar_otp_app.erl @@ -29,6 +29,9 @@ -export([compile/2, clean/2]). +%% for internal use only +-export([info/2]). + -include("rebar.hrl"). %% =================================================================== @@ -82,11 +85,26 @@ clean(_Config, File) -> ok end. - %% =================================================================== %% Internal functions %% =================================================================== +info(help, compile) -> + info_help("Validate .app file"); +info(help, clean) -> + info_help("Delete .app file if generated from .app.src"). + +info_help(Description) -> + ?CONSOLE( + "~s.~n" + "~n" + "Valid rebar.config options:~n" + " ~p~n", + [ + Description, + {validate_app_modules, true} + ]). + preprocess(Config, AppSrcFile) -> case rebar_app_utils:load_app_file(Config, AppSrcFile) of {ok, Config1, AppName, AppData} -> diff --git a/src/rebar_port_compiler.erl b/src/rebar_port_compiler.erl index 06a79bc..0abb044 100644 --- a/src/rebar_port_compiler.erl +++ b/src/rebar_port_compiler.erl @@ -27,8 +27,11 @@ -module(rebar_port_compiler). -export([compile/2, - clean/2, - setup_env/1]). + clean/2]). + +%% for internal use only +-export([setup_env/1, + info/2]). -include("rebar.hrl"). @@ -97,7 +100,8 @@ compile(Config, AppFile) -> [] -> ok; Specs -> - SharedEnv = rebar_config:get_env(Config, ?MODULE), + SharedEnv = rebar_config:get_env(Config, rebar_deps) ++ + rebar_config:get_env(Config, ?MODULE), %% Compile each of the sources NewBins = compile_sources(Config, Specs, SharedEnv), @@ -149,6 +153,27 @@ setup_env(Config) -> %% Internal functions %% =================================================================== +info(help, compile) -> + info_help("Build port sources"); +info(help, clean) -> + info_help("Delete port build results"). + +info_help(Description) -> + ?CONSOLE( + "~s.~n" + "~n" + "Valid rebar.config options:~n" + " ~p~n" + " ~p~n", + [ + Description, + {port_env, [{"CFLAGS", "$CFLAGS -Ifoo"}, + {"freebsd", "LDFLAGS", "$LDFLAGS -lfoo"}]}, + {port_specs, [{"priv/so_name.so", ["c_src/*.c"]}, + {"linux", "priv/hello_linux", ["c_src/hello_linux.c"]}, + {"linux", "priv/hello_linux", ["c_src/*.c"], [{env, []}]}]} + ]). + setup_env(Config, ExtraEnv) -> %% Extract environment values from the config (if specified) and %% merge with the default for this operating system. This enables diff --git a/src/rebar_protobuffs_compiler.erl b/src/rebar_protobuffs_compiler.erl index 7ef58d6..579ecfb 100644 --- a/src/rebar_protobuffs_compiler.erl +++ b/src/rebar_protobuffs_compiler.erl @@ -29,6 +29,9 @@ -export([compile/2, clean/2]). +%% for internal use only +-export([info/2]). + -include("rebar.hrl"). %% =================================================================== @@ -57,7 +60,6 @@ compile(Config, _AppFile) -> end end. - clean(_Config, _AppFile) -> %% Get a list of generated .beam and .hrl files and then delete them Protos = rebar_utils:find_files("src", ".*\\.proto$"), @@ -71,11 +73,24 @@ clean(_Config, _AppFile) -> delete_each(Targets) end. - %% =================================================================== %% Internal functions %% =================================================================== +info(help, compile) -> + info_help("Build Protobuffs (*.proto) sources"); +info(help, clean) -> + info_help("Delete Protobuffs (*.proto) build results"). + +info_help(Description) -> + ?CONSOLE( + "~s.~n" + "~n" + "Valid rebar.config options:~n" + " erl_opts is passed as compile_flags to " + "protobuffs_compile:scan_file/2~n", + [Description]). + protobuffs_is_present() -> code:which(protobuffs_compile) =/= non_existing. @@ -115,7 +130,7 @@ compile_each(Config, [{Proto, Beam, Hrl} | Rest]) -> ok = rebar_file_utils:mv(Hrl, "include"), ok; Other -> - ?ERROR("Protobuff compile of ~s failed: ~p\n", + ?ERROR("Protobuffs compile of ~s failed: ~p\n", [Proto, Other]), ?FAIL end; diff --git a/src/rebar_qc.erl b/src/rebar_qc.erl index 09e48e4..53a6f52 100644 --- a/src/rebar_qc.erl +++ b/src/rebar_qc.erl @@ -28,6 +28,9 @@ -export([qc/2, triq/2, eqc/2, clean/2]). +%% for internal use only +-export([info/2]). + -include("rebar.hrl"). -define(QC_DIR, ".qc"). @@ -57,6 +60,19 @@ clean(_Config, _File) -> %% Internal functions %% =================================================================== +info(help, qc) -> + ?CONSOLE( + "Test QuickCheck properties.~n" + "~n" + "Valid rebar.config options:~n" + " {qc_opts, [{qc_mod, module()}, Options]}~n" + " ~p~n" + " ~p~n", + [ + {qc_compile_opts, []}, + {qc_first_files, []} + ]). + -define(TRIQ_MOD, triq). -define(EQC_MOD, eqc). @@ -159,6 +175,7 @@ qc_module(QC=triq, _QCOpts, M) -> Failed -> [Failed] end; +qc_module(QC=eqc, [], M) -> QC:module(M); qc_module(QC=eqc, QCOpts, M) -> QC:module(QCOpts, M). find_prop_mods() -> diff --git a/src/rebar_reltool.erl b/src/rebar_reltool.erl index 3c9b728..18b0702 100644 --- a/src/rebar_reltool.erl +++ b/src/rebar_reltool.erl @@ -30,6 +30,9 @@ overlay/2, clean/2]). +%% for internal use only +-export([info/2]). + -include("rebar.hrl"). -include_lib("kernel/include/file.hrl"). @@ -80,6 +83,32 @@ clean(Config, ReltoolFile) -> %% Internal functions %% =================================================================== +info(help, generate) -> + info_help("Build release with reltool"); +info(help, clean) -> + info_help("Delete release"); +info(help, overlay) -> + info_help("Run reltool overlays only"). + +info_help(Description) -> + ?CONSOLE( + "~s.~n" + "~n" + "Valid rebar.config options:~n" + " ~n" + "Valid reltool.config options:~n" + " {sys, []}~n" + " {target_dir, \"target\"}~n" + " {overlay_vars, \"overlay\"}~n" + " {overlay, []}~n" + "Valid command line options:~n" + " target_dir=target~n" + " overlay_vars=VarsFile~n" + " dump_spec=1 (write reltool target spec to reltool.spec)~n", + [ + Description + ]). + check_vsn() -> %% TODO: use application:load and application:get_key once we require %% R14A or newer. There's no reltool.app before R14A. diff --git a/src/rebar_require_vsn.erl b/src/rebar_require_vsn.erl index 9a0a005..385f55c 100644 --- a/src/rebar_require_vsn.erl +++ b/src/rebar_require_vsn.erl @@ -33,6 +33,9 @@ -export([compile/2, eunit/2]). +%% for internal use only +-export([info/2]). + %% =================================================================== %% Public API %% =================================================================== @@ -47,6 +50,25 @@ eunit(Config, _) -> %% Internal functions %% ==================================================================== +info(help, compile) -> + info_help(); +info(help, eunit) -> + info_help(). + +info_help() -> + ?CONSOLE( + "Check required ERTS or OTP release version.~n" + "~n" + "Valid rebar.config options:~n" + " ~p~n" + " ~p~n" + " ~p~n", + [ + {require_erts_vsn, ".*"}, + {require_otp_vsn, ".*"}, + {require_min_otp_vsn, ".*"} + ]). + check_versions(Config) -> ErtsRegex = rebar_config:get(Config, require_erts_vsn, ".*"), ReOpts = [{capture, none}], diff --git a/src/rebar_templater.erl b/src/rebar_templater.erl index 0e1eef1..e997975 100644 --- a/src/rebar_templater.erl +++ b/src/rebar_templater.erl @@ -35,6 +35,9 @@ -export([resolve_variables/2, render/2]). +%% for internal use only +-export([info/2]). + -include("rebar.hrl"). -define(TEMPLATE_RE, ".*\\.template\$"). @@ -81,6 +84,9 @@ resolve_variables([], Dict) -> resolve_variables([{Key, Value0} | Rest], Dict) when is_list(Value0) -> Value = render(list_to_binary(Value0), Dict), resolve_variables(Rest, dict:store(Key, Value, Dict)); +resolve_variables([{Key, {list, Dicts}} | Rest], Dict) when is_list(Dicts) -> + %% just un-tag it so mustache can use it + resolve_variables(Rest, dict:store(Key, Dicts, Dict)); resolve_variables([_Pair | Rest], Dict) -> resolve_variables(Rest, Dict). @@ -98,6 +104,27 @@ render(Bin, Context) -> %% Internal functions %% =================================================================== +info(help, create) -> + ?CONSOLE( + "Create skel based on template and vars.~n" + "~n" + "Valid command line options:~n" + " template= [var=foo,...]~n", []); +info(help, 'create-app') -> + ?CONSOLE( + "Create simple app skel.~n" + "~n" + "Valid command line options:~n" + " [appid=myapp]~n", []); +info(help, 'create-node') -> + ?CONSOLE( + "Create simple node skel.~n" + "~n" + "Valid command line options:~n" + " [nodeid=mynode]~n", []); +info(help, 'list-templates') -> + ?CONSOLE("List available templates.~n", []). + create1(Config, TemplateId) -> {AvailTemplates, Files} = find_templates(Config), ?DEBUG("Available templates: ~p\n", [AvailTemplates]), @@ -134,14 +161,14 @@ create1(Config, TemplateId) -> undefined -> Context0; File -> - case file:consult(File) of - {ok, Terms} -> - %% TODO: Cleanup/merge with similar code in rebar_reltool - M = fun(_Key, _Base, Override) -> Override end, - dict:merge(M, Context0, dict:from_list(Terms)); + case consult(load_file([], file, File)) of {error, Reason} -> ?ABORT("Unable to load template_vars from ~s: ~p\n", - [File, Reason]) + [File, Reason]); + Terms -> + %% TODO: Cleanup/merge with similar code in rebar_reltool + M = fun(_Key, _Base, Override) -> Override end, + dict:merge(M, Context0, dict:from_list(Terms)) end end, @@ -275,7 +302,7 @@ consult(Cont, Str, Acc) -> case Result of {ok, Tokens, _} -> {ok, Term} = erl_parse:parse_term(Tokens), - consult([], Remaining, [Term | Acc]); + consult([], Remaining, [maybe_dict(Term) | Acc]); {eof, _Other} -> lists:reverse(Acc); {error, Info, _} -> @@ -286,6 +313,13 @@ consult(Cont, Str, Acc) -> end. +maybe_dict({Key, {list, Dicts}}) -> + %% this is a 'list' element; a list of lists representing dicts + {Key, {list, [dict:from_list(D) || D <- Dicts]}}; +maybe_dict(Term) -> + Term. + + write_file(Output, Data, Force) -> %% determine if the target file already exists FileExists = filelib:is_regular(Output), diff --git a/src/rebar_upgrade.erl b/src/rebar_upgrade.erl index 14ea758..d18603c 100644 --- a/src/rebar_upgrade.erl +++ b/src/rebar_upgrade.erl @@ -32,6 +32,9 @@ -export(['generate-upgrade'/2]). +%% for internal use only +-export([info/2]). + -define(TMP, "_tmp"). %% ==================================================================== @@ -80,6 +83,13 @@ %% Internal functions %% ================================================================== +info(help, 'generate-upgrade') -> + ?CONSOLE("Build an upgrade package.~n" + "~n" + "Valid command line options:~n" + " previous_release=path~n", + []). + run_checks(Config, OldVerPath, ReltoolConfig) -> true = rebar_utils:prop_check(filelib:is_dir(OldVerPath), "Release directory doesn't exist (~p)~n", diff --git a/src/rebar_utils.erl b/src/rebar_utils.erl index bb58460..fd93f98 100644 --- a/src/rebar_utils.erl +++ b/src/rebar_utils.erl @@ -195,7 +195,7 @@ expand_env_variable(InStr, VarName, RawVarValue) -> %% Use a regex to match/replace: %% Given variable "FOO": match $FOO\s | $FOOeol | ${FOO} RegEx = io_lib:format("\\\$(~s(\\s|$)|{~s})", [VarName, VarName]), - ReOpts = [global, {return, list}], + ReOpts = [global, {return, list}, unicode], re:replace(InStr, RegEx, [VarValue, "\\2"], ReOpts) end. diff --git a/src/rebar_xref.erl b/src/rebar_xref.erl index a55d71d..8c0a872 100644 --- a/src/rebar_xref.erl +++ b/src/rebar_xref.erl @@ -37,6 +37,9 @@ -export([xref/2]). +%% for internal use only +-export([info/2]). + %% =================================================================== %% Public API %% =================================================================== @@ -100,6 +103,22 @@ xref(Config, _) -> %% Internal functions %% =================================================================== +info(help, xref) -> + ?CONSOLE( + "Run cross reference analysis.~n" + "~n" + "Valid rebar.config options:~n" + " ~p~n" + " ~p~n" + " ~p~n", + [ + {xref_warnings, false}, + {xref_checks, [exports_not_used, undefined_function_calls]}, + {xref_queries, + [{"(xc - uc) || (xu - x - b" + " - (\"mod\":\".*foo\"/\"4\"))",[]}]} + ]). + check_exports_not_used() -> {ok, UnusedExports0} = xref:analyze(xref, exports_not_used), UnusedExports = filter_away_ignored(UnusedExports0), |