diff options
author | Håkan Mattsson <[email protected]> | 2010-03-23 16:50:50 +0100 |
---|---|---|
committer | Håkan Mattsson <[email protected]> | 2010-04-19 13:17:33 +0200 |
commit | 534f334247163035b477293e74b78823f2d9b7f3 (patch) | |
tree | 10fba9717bb98da3212ee630ad4e63dd9fa60b86 | |
parent | 5217fb3d0816aa241d228f7ef14fb54f6a14a8f8 (diff) | |
download | otp-534f334247163035b477293e74b78823f2d9b7f3.tar.gz otp-534f334247163035b477293e74b78823f2d9b7f3.tar.bz2 otp-534f334247163035b477293e74b78823f2d9b7f3.zip |
Automatically include applications that must be started
Applications that are required to be started
before other applications according to their
app-file are now automatically included in
the release. The kernel and stdlib applications
are automatically included.
-rw-r--r-- | lib/reltool/bin/reltool.escript | 10 | ||||
-rw-r--r-- | lib/reltool/doc/src/reltool_examples.xml | 4 | ||||
-rw-r--r-- | lib/reltool/src/reltool_server.erl | 304 | ||||
-rw-r--r-- | lib/reltool/src/reltool_target.erl | 271 | ||||
-rw-r--r-- | lib/reltool/src/reltool_utils.erl | 24 | ||||
-rw-r--r-- | lib/reltool/test/reltool_app_SUITE.erl | 8 |
6 files changed, 378 insertions, 243 deletions
diff --git a/lib/reltool/bin/reltool.escript b/lib/reltool/bin/reltool.escript index 567cafbcad..1e5f34d99d 100644 --- a/lib/reltool/bin/reltool.escript +++ b/lib/reltool/bin/reltool.escript @@ -27,14 +27,14 @@ main(Args) -> {Options, Actions} = parse_args(Tokens, []), case invoke(Options, Actions) of ok -> - erlang:halt(0); + safe_stop(0); {error, ReasonString} -> fatal_error(ReasonString, 2) end catch throw:usage -> usage(), - erlang:halt(1); + safe_stop(1); exit:Reason -> String = lists:flatten(io_lib:format("EXIT: ~p", [Reason])), fatal_error(String, 3) @@ -59,6 +59,10 @@ usage() -> "See User's guide and Reference manual for more info.\n", [String]). +safe_stop(Code) -> + init:stop(Code), + timer:sleep(infinity). + invoke(Options, Actions) -> case Actions of [] -> @@ -174,7 +178,7 @@ script_name() -> fatal_error(String, Code) -> io:format(standard_error, "~s: ~s\n", [script_name(), String]), - erlang:halt(Code). + safe_stop(Code). write_file(File, IoList) -> case file:write_file(File, IoList) of diff --git a/lib/reltool/doc/src/reltool_examples.xml b/lib/reltool/doc/src/reltool_examples.xml index d6db246f6c..bce9413b52 100644 --- a/lib/reltool/doc/src/reltool_examples.xml +++ b/lib/reltool/doc/src/reltool_examples.xml @@ -249,11 +249,11 @@ Eshell V5.7.3 (abort with ^G) <pre> 5> {ok, Server} = reltool:start_server([{config, {sys, [{boot_rel, "NAME"}, {rel, "NAME", "VSN", - [kernel, stdlib, sasl]}]}}]). + [sasl]}]}}]). {ok,<0.1288.0>} 6> reltool:get_config(Server). {ok,{sys,[{boot_rel,"NAME"}, - {rel,"NAME","VSN",[kernel,stdlib,sasl]}]}} + {rel,"NAME","VSN",[sasl]}]}} 7> reltool:get_rel(Server, "NAME"). {ok,{release,{"NAME","VSN"}, {erts,"5.7"}, diff --git a/lib/reltool/src/reltool_server.erl b/lib/reltool/src/reltool_server.erl index 6a3122f879..a1e9c0193b 100644 --- a/lib/reltool/src/reltool_server.erl +++ b/lib/reltool/src/reltool_server.erl @@ -442,12 +442,13 @@ analyse(#state{common = C, MissingApp = default_app(?MISSING_APP, "missing"), ets:insert(C#common.app_tab, MissingApp), - RelApps = apps_in_rels(Rels), - {Apps2, Status2} = + {RevRelApps, Status2} = apps_in_rels(Rels, Apps, Status), + RelApps2 = lists:reverse(RevRelApps), + {Apps2, Status3} = lists:mapfoldl(fun(App, Acc) -> - app_init_is_included(C, Sys, App, RelApps, Acc) + app_init_is_included(C, Sys, App, RelApps2, Acc) end, - Status, + Status2, Apps), Apps3 = case app_propagate_is_included(C, Sys, Apps2, []) of @@ -467,17 +468,51 @@ analyse(#state{common = C, %% io:format("Missing app: ~p\n", %% [lists:keysearch(?MISSING_APP, #app.name, Apps4)]), Sys2 = Sys#sys{apps = Apps4}, - case verify_config(Sys2, Status2) of - {ok, _Warnings} = Status3 -> - {S#state{sys = Sys2}, Status3}; - {error, _} = Status3 -> - {S, Status3} + + case verify_config(RelApps2, Sys2, Status3) of + {ok, _Warnings} = Status4 -> + {S#state{sys = Sys2}, Status4}; + {error, _} = Status4 -> + {S, Status4} end. -apps_in_rels(Rels) -> - [{RelName, AppName} || #rel{name = RelName, rel_apps = RelApps} <- Rels, - RA <- RelApps, - AppName <- [RA#rel_app.name | RA#rel_app.incl_apps]]. +apps_in_rels(Rels, Apps, Status) -> + lists:foldl(fun(Rel, {RelApps, S}) -> + {MoreRelApps, S2} = apps_in_rel(Rel, Apps, S), + {MoreRelApps ++ RelApps, S2} + end, + {[], Status}, + Rels). + +apps_in_rel(#rel{name = RelName, rel_apps = RelApps}, Apps, Status) -> + Mandatory = [{RelName, kernel}, {RelName, stdlib}], + Other = [{RelName, AppName} || + RA <- RelApps, + AppName <- [RA#rel_app.name | RA#rel_app.incl_apps], + not lists:keymember(AppName, 2, Mandatory)], + more_apps_in_rels(Mandatory ++ Other, Apps, [], Status). + +more_apps_in_rels([{RelName, AppName} = RA | RelApps], Apps, Acc, Status) -> + case lists:member(RA, Acc) of + true -> + more_apps_in_rels(RelApps, Apps, Acc, Status); + false -> + case lists:keysearch(AppName, #app.name, Apps) of + {value, #app{info = #app_info{applications = InfoApps}}} -> + Extra = [{RelName, N} || N <- InfoApps], + {Acc2, Status2} = + more_apps_in_rels(Extra, Apps, [RA | Acc], Status), + more_apps_in_rels(RelApps, Apps, Acc2, Status2); + false -> + Text = lists:concat(["Release ", RelName, + " uses non existing application ", + AppName]), + Status2 = reltool_utils:return_first_error(Status, Text), + more_apps_in_rels(RelApps, Apps, Acc, Status2) + end + end; +more_apps_in_rels([], _Apps, Acc, Status) -> + {Acc, Status}. app_init_is_included(C, Sys, @@ -706,8 +741,6 @@ mod_propagate_is_used_by(_C, []) -> read_apps(C, Sys, [#app{mods = Mods, is_included = IsIncl} = A | Apps], Acc) -> {Mods2, IsIncl2} = read_apps(C, Sys, A, Mods, [], IsIncl), - %% reltool_utils:print(A#app.name, stdlib, "Mods2: ~p\n", - %% [[M#mod.status || M <- Mods2]]), Status = case lists:keysearch(missing, #mod.status, Mods2) of {value, _} -> missing; @@ -770,9 +803,7 @@ filter_app(A) -> Mods = [M#mod{is_app_mod = undefined, is_ebin_mod = undefined, uses_mods = undefined, - exists = false, - is_pre_included = undefined, - is_included = undefined} || + exists = false} || M <- A#app.mods, M#mod.incl_cond =/= undefined], if @@ -781,8 +812,7 @@ filter_app(A) -> label = undefined, info = undefined, mods = [], - uses_mods = undefined, - is_included = undefined}}; + uses_mods = undefined}}; Mods =:= [], A#app.mod_cond =:= undefined, A#app.incl_cond =:= undefined, @@ -812,8 +842,7 @@ filter_app(A) -> label = undefined, info = undefined, mods = Mods, - uses_mods = undefined, - is_included = undefined}} + uses_mods = undefined}} end. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -850,16 +879,16 @@ refresh_app(#app{name = AppName, end, %% Add non-existing modules + AppInfoMods = AppInfo#app_info.modules, AppModNames = case AppInfo#app_info.mod of {StartModName, _} -> - case lists:member(StartModName, - AppInfo#app_info.modules) of - true -> AppInfo#app_info.modules; - false -> [StartModName | AppInfo#app_info.modules] + case lists:member(StartModName, AppInfoMods) of + true -> AppInfoMods; + false -> [StartModName | AppInfoMods] end; undefined -> - AppInfo#app_info.modules + AppInfoMods end, MissingMods = add_missing_mods(AppName, EbinMods, AppModNames), @@ -1206,11 +1235,14 @@ decode(#sys{} = Sys, [{Key, Val} | KeyVals], Status) -> {Sys#sys{root_dir = Val}, Status}; lib_dirs when is_list(Val) -> {Sys#sys{lib_dirs = Val}, Status}; - mod_cond when Val =:= all; Val =:= app; - Val =:= ebin; Val =:= derived; + mod_cond when Val =:= all; + Val =:= app; + Val =:= ebin; + Val =:= derived; Val =:= none -> {Sys#sys{mod_cond = Val}, Status}; - incl_cond when Val =:= include; Val =:= exclude; + incl_cond when Val =:= include; + Val =:= exclude; Val =:= derived -> {Sys#sys{incl_cond = Val}, Status}; boot_rel when is_list(Val) -> @@ -1220,78 +1252,96 @@ decode(#sys{} = Sys, [{Key, Val} | KeyVals], Status) -> profile when Val =:= development -> Val = ?DEFAULT_PROFILE, % assert, {Sys#sys{profile = Val, - incl_sys_filters = dec_re(incl_sys_filters, - ?DEFAULT_INCL_SYS_FILTERS, - Sys#sys.incl_sys_filters), - excl_sys_filters = dec_re(excl_sys_filters, - ?DEFAULT_EXCL_SYS_FILTERS, - Sys#sys.excl_sys_filters), - incl_app_filters = dec_re(incl_app_filters, - ?DEFAULT_INCL_APP_FILTERS, - Sys#sys.incl_app_filters), - excl_app_filters = dec_re(excl_app_filters, - ?DEFAULT_EXCL_APP_FILTERS, - Sys#sys.excl_app_filters)}, + incl_sys_filters = + dec_re(incl_sys_filters, + ?DEFAULT_INCL_SYS_FILTERS, + Sys#sys.incl_sys_filters), + excl_sys_filters = + dec_re(excl_sys_filters, + ?DEFAULT_EXCL_SYS_FILTERS, + Sys#sys.excl_sys_filters), + incl_app_filters = + dec_re(incl_app_filters, + ?DEFAULT_INCL_APP_FILTERS, + Sys#sys.incl_app_filters), + excl_app_filters = + dec_re(excl_app_filters, + ?DEFAULT_EXCL_APP_FILTERS, + Sys#sys.excl_app_filters)}, Status}; profile when Val =:= embedded -> {Sys#sys{profile = Val, - incl_sys_filters = dec_re(incl_sys_filters, - ?EMBEDDED_INCL_SYS_FILTERS, - Sys#sys.incl_sys_filters), - excl_sys_filters = dec_re(excl_sys_filters, - ?EMBEDDED_EXCL_SYS_FILTERS, - Sys#sys.excl_sys_filters), - incl_app_filters = dec_re(incl_app_filters, - ?EMBEDDED_INCL_APP_FILTERS, - Sys#sys.incl_app_filters), - excl_app_filters = dec_re(excl_app_filters, - ?EMBEDDED_EXCL_APP_FILTERS, - Sys#sys.excl_app_filters)}, + incl_sys_filters = + dec_re(incl_sys_filters, + ?EMBEDDED_INCL_SYS_FILTERS, + Sys#sys.incl_sys_filters), + excl_sys_filters = + dec_re(excl_sys_filters, + ?EMBEDDED_EXCL_SYS_FILTERS, + Sys#sys.excl_sys_filters), + incl_app_filters = + dec_re(incl_app_filters, + ?EMBEDDED_INCL_APP_FILTERS, + Sys#sys.incl_app_filters), + excl_app_filters = + dec_re(excl_app_filters, + ?EMBEDDED_EXCL_APP_FILTERS, + Sys#sys.excl_app_filters)}, Status}; profile when Val =:= standalone -> {Sys#sys{profile = Val, - incl_sys_filters = dec_re(incl_sys_filters, - ?STANDALONE_INCL_SYS_FILTERS, - Sys#sys.incl_sys_filters), - excl_sys_filters = dec_re(excl_sys_filters, - ?STANDALONE_EXCL_SYS_FILTERS, - Sys#sys.excl_sys_filters), - incl_app_filters = dec_re(incl_app_filters, - ?STANDALONE_INCL_APP_FILTERS, - Sys#sys.incl_app_filters), - excl_app_filters = dec_re(excl_app_filters, - ?STANDALONE_EXCL_APP_FILTERS, - Sys#sys.excl_app_filters)}, + incl_sys_filters = + dec_re(incl_sys_filters, + ?STANDALONE_INCL_SYS_FILTERS, + Sys#sys.incl_sys_filters), + excl_sys_filters = + dec_re(excl_sys_filters, + ?STANDALONE_EXCL_SYS_FILTERS, + Sys#sys.excl_sys_filters), + incl_app_filters = + dec_re(incl_app_filters, + ?STANDALONE_INCL_APP_FILTERS, + Sys#sys.incl_app_filters), + excl_app_filters = + dec_re(excl_app_filters, + ?STANDALONE_EXCL_APP_FILTERS, + Sys#sys.excl_app_filters)}, Status}; incl_sys_filters -> - {Sys#sys{incl_sys_filters = dec_re(Key, - Val, - Sys#sys.incl_sys_filters)}, + {Sys#sys{incl_sys_filters = + dec_re(Key, + Val, + Sys#sys.incl_sys_filters)}, Status}; excl_sys_filters -> - {Sys#sys{excl_sys_filters = dec_re(Key, - Val, - Sys#sys.excl_sys_filters)}, + {Sys#sys{excl_sys_filters = + dec_re(Key, + Val, + Sys#sys.excl_sys_filters)}, Status}; incl_app_filters -> - {Sys#sys{incl_app_filters = dec_re(Key, - Val, - Sys#sys.incl_app_filters)}, + {Sys#sys{incl_app_filters = + dec_re(Key, + Val, + Sys#sys.incl_app_filters)}, Status}; excl_app_filters -> - {Sys#sys{excl_app_filters = dec_re(Key, - Val, - Sys#sys.excl_app_filters)}, + {Sys#sys{excl_app_filters = + dec_re(Key, + Val, + Sys#sys.excl_app_filters)}, Status}; incl_archive_filters -> - {Sys#sys{incl_archive_filters = dec_re(Key, - Val, - Sys#sys.incl_archive_filters)}, + {Sys#sys{incl_archive_filters = + dec_re(Key, + Val, + Sys#sys.incl_archive_filters)}, Status}; excl_archive_filters -> - {Sys#sys{excl_archive_filters = dec_re(Key, - Val, - Sys#sys.excl_archive_filters)}, + {Sys#sys{excl_archive_filters = + dec_re(Key, + Val, + Sys#sys.excl_archive_filters)}, Status}; archive_opts when is_list(Val) -> {Sys#sys{archive_opts = Val}, Status}; @@ -1300,7 +1350,8 @@ decode(#sys{} = Sys, [{Key, Val} | KeyVals], Status) -> app_type when Val =:= permanent; Val =:= transient; Val =:= temporary; - Val =:= load; Val =:= none -> + Val =:= load; + Val =:= none -> {Sys#sys{app_type = Val}, Status}; app_file when Val =:= keep; Val =:= strip, Val =:= all -> {Sys#sys{app_file = Val}, Status}; @@ -1341,24 +1392,28 @@ decode(#app{} = App, [{Key, Val} | KeyVals], Status) -> Val =:= none -> {App#app{app_type = Val}, Status}; incl_app_filters -> - {App#app{incl_app_filters = dec_re(Key, - Val, - App#app.incl_app_filters)}, + {App#app{incl_app_filters = + dec_re(Key, + Val, + App#app.incl_app_filters)}, Status}; excl_app_filters -> - {App#app{excl_app_filters = dec_re(Key, - Val, - App#app.excl_app_filters)}, + {App#app{excl_app_filters = + dec_re(Key, + Val, + App#app.excl_app_filters)}, Status}; incl_archive_filters -> - {App#app{incl_archive_filters = dec_re(Key, - Val, - App#app.incl_archive_filters)}, + {App#app{incl_archive_filters = + dec_re(Key, + Val, + App#app.incl_archive_filters)}, Status}; excl_archive_filters -> - {App#app{excl_archive_filters = dec_re(Key, - Val, - App#app.excl_archive_filters)}, + {App#app{excl_archive_filters = + dec_re(Key, + Val, + App#app.excl_archive_filters)}, Status}; archive_opts when is_list(Val) -> {App#app{archive_opts = Val}, Status}; @@ -1463,24 +1518,41 @@ merge_config(OldSys, NewSys, Force, Status) -> apps = PatchedApps}, {NewSys2, Status5}. -verify_config(Sys, Status) -> - case lists:keymember(Sys#sys.boot_rel, #rel.name, Sys#sys.rels) of +verify_config(RelApps, #sys{boot_rel = BootRel, rels = Rels, apps = Apps}, Status) -> + case lists:keymember(BootRel, #rel.name, Rels) of true -> - lists:foldl(fun(Rel, Acc)-> check_rel(Rel, Sys, Acc) end, - Status, - Sys#sys.rels); + Status2 = lists:foldl(fun(RA, Acc) -> + check_app(RA, Apps, Acc) end, + Status, + RelApps), + lists:foldl(fun(#rel{name = RelName}, Acc)-> + check_rel(RelName, RelApps, Acc) + end, + Status2, + Rels); false -> - Text = lists:concat(["Release ", Sys#sys.boot_rel, + Text = lists:concat(["Release ", BootRel, " is mandatory (used as boot_rel)"]), reltool_utils:return_first_error(Status, Text) end. -check_rel(#rel{name = RelName, rel_apps = RelApps}, - #sys{apps = Apps}, - Status) -> +check_app({RelName, AppName}, Apps, Status) -> + case lists:keysearch(AppName, #app.name, Apps) of + {value, App} when App#app.is_pre_included -> + Status; + {value, App} when App#app.is_included -> + Status; + _ -> + Text = lists:concat(["Release ", RelName, + " uses non included application ", + AppName]), + reltool_utils:return_first_error(Status, Text) + end. + +check_rel(RelName, RelApps, Status) -> EnsureApp = fun(AppName, Acc) -> - case lists:keymember(AppName, #rel_app.name, RelApps) of + case lists:member({RelName, AppName}, RelApps) of true -> Acc; false -> @@ -1492,23 +1564,7 @@ check_rel(#rel{name = RelName, rel_apps = RelApps}, end end, Mandatory = [kernel, stdlib], - Status2 = lists:foldl(EnsureApp, Status, Mandatory), - CheckRelApp = - fun(#rel_app{name = AppName}, Acc) -> - case lists:keysearch(AppName, #app.name, Apps) of - {value, App} when App#app.is_pre_included -> - Acc; - {value, App} when App#app.is_included -> - Acc; - _ -> - Text = lists:concat(["Release ", RelName, - " uses non included application ", - AppName]), - - reltool_utils:return_first_error(Acc, Text) - end - end, - lists:foldl(CheckRelApp, Status2, RelApps). + lists:foldl(EnsureApp, Status, Mandatory). patch_erts_version(RootDir, Apps, Status) -> AppName = erts, diff --git a/lib/reltool/src/reltool_target.erl b/lib/reltool/src/reltool_target.erl index 260c8a15f8..aaf9d99d2f 100644 --- a/lib/reltool/src/reltool_target.erl +++ b/lib/reltool/src/reltool_target.erl @@ -67,26 +67,26 @@ kernel_processes(KernelApp) -> gen_config(Sys, InclDefs) -> {ok, do_gen_config(Sys, InclDefs)}. -do_gen_config(#sys{root_dir = RootDir, - lib_dirs = LibDirs, - mod_cond = ModCond, - incl_cond = AppCond, - apps = Apps, - boot_rel = BootRel, - rels = Rels, - emu_name = EmuName, - profile = Profile, - incl_sys_filters = InclSysFiles, - excl_sys_filters = ExclSysFiles, - incl_app_filters = InclAppFiles, - excl_app_filters = ExclAppFiles, +do_gen_config(#sys{root_dir = RootDir, + lib_dirs = LibDirs, + mod_cond = ModCond, + incl_cond = AppCond, + apps = Apps, + boot_rel = BootRel, + rels = Rels, + emu_name = EmuName, + profile = Profile, + incl_sys_filters = InclSysFiles, + excl_sys_filters = ExclSysFiles, + incl_app_filters = InclAppFiles, + excl_app_filters = ExclAppFiles, incl_archive_filters = InclArchiveDirs, excl_archive_filters = ExclArchiveDirs, - archive_opts = ArchiveOpts, - relocatable = Relocatable, - app_type = AppType, - app_file = AppFile, - debug_info = DebugInfo}, + archive_opts = ArchiveOpts, + relocatable = Relocatable, + app_type = AppType, + app_file = AppFile, + debug_info = DebugInfo}, InclDefs) -> ErtsItems = case lists:keysearch(erts, #app.name, Apps) of @@ -96,12 +96,11 @@ do_gen_config(#sys{root_dir = RootDir, [] end, AppsItems = - [{app, A#app.name, do_gen_config(A, InclDefs)} + [do_gen_config(A, InclDefs) || A <- Apps, A#app.name =/= ?MISSING_APP, A#app.name =/= erts, - A#app.is_included =:= true, - A#app.is_escript =/= true], + not A#app.is_escript], EscriptItems = [{escript, A#app.active_dir, emit(incl_cond, A#app.incl_cond, undefined, InclDefs)} @@ -126,7 +125,7 @@ do_gen_config(#sys{root_dir = RootDir, emit(mod_cond, ModCond, ?DEFAULT_MOD_COND, InclDefs) ++ emit(incl_cond, AppCond, ?DEFAULT_INCL_COND, InclDefs) ++ ErtsItems ++ - AppsItems ++ + lists:flatten(AppsItems) ++ emit(boot_rel, BootRel, ?DEFAULT_REL_NAME, InclDefs) ++ RelsItems2 ++ emit(emu_name, EmuName, ?DEFAULT_EMU_NAME, InclDefs) ++ @@ -142,7 +141,7 @@ do_gen_config(#sys{root_dir = RootDir, emit(app_type, AppType, ?DEFAULT_APP_TYPE, InclDefs) ++ emit(app_file, AppFile, ?DEFAULT_APP_FILE, InclDefs) ++ emit(debug_info, DebugInfo, ?DEFAULT_DEBUG_INFO, InclDefs)}; -do_gen_config(#app{name = _Name, +do_gen_config(#app{name = Name, mod_cond = ModCond, incl_cond = AppCond, debug_info = DebugInfo, @@ -154,27 +153,49 @@ do_gen_config(#app{name = _Name, archive_opts = ArchiveOpts, use_selected_vsn = UseSelected, vsn = Vsn, - mods = Mods}, + mods = Mods, + is_included = IsIncl}, InclDefs) -> - emit(mod_cond, ModCond, undefined, InclDefs) ++ - emit(incl_cond, AppCond, undefined, InclDefs) ++ - emit(debug_info, DebugInfo, undefined, InclDefs) ++ - emit(app_file, AppFile, undefined, InclDefs) ++ - emit(incl_app_filters, InclAppFiles, undefined, InclDefs) ++ - emit(excl_app_filters, ExclAppFiles, undefined, InclDefs) ++ - emit(incl_archive_filters, InclArchiveDirs, undefined, InclDefs) ++ - emit(excl_archive_filters, ExclArchiveDirs, undefined, InclDefs) ++ - emit(archive_opts, ArchiveOpts, undefined, InclDefs) ++ - emit(vsn, Vsn, undefined, InclDefs orelse UseSelected =/= true) ++ - [{mod, M#mod.name, do_gen_config(M, InclDefs)} || - M <- Mods, - M#mod.is_included =:= true]; -do_gen_config(#mod{name = _Name, + AppConfig = + [ + emit(mod_cond, ModCond, undefined, InclDefs), + emit(incl_cond, AppCond, undefined, InclDefs), + emit(debug_info, DebugInfo, undefined, InclDefs), + emit(app_file, AppFile, undefined, InclDefs), + emit(incl_app_filters, InclAppFiles, undefined, InclDefs), + emit(excl_app_filters, ExclAppFiles, undefined, InclDefs), + emit(incl_archive_filters, InclArchiveDirs, undefined, InclDefs), + emit(excl_archive_filters, ExclArchiveDirs, undefined, InclDefs), + emit(archive_opts, ArchiveOpts, undefined, InclDefs), + if + IsIncl, InclDefs -> [{vsn, Vsn}]; + UseSelected -> [{vsn, Vsn}]; + true -> [] + end, + [do_gen_config(M, InclDefs) || M <- Mods] + ], + case lists:flatten(AppConfig) of + FlatAppConfig when FlatAppConfig =/= []; IsIncl -> + [{app, Name, FlatAppConfig}]; + [] -> + [] + end; +do_gen_config(#mod{name = Name, incl_cond = AppCond, - debug_info = DebugInfo}, + debug_info = DebugInfo, + is_included = IsIncl}, InclDefs) -> - emit(incl_cond, AppCond, undefined, InclDefs) ++ - emit(debug_info, DebugInfo, undefined, InclDefs); + ModConfig = + [ + emit(incl_cond, AppCond, undefined, InclDefs), + emit(debug_info, DebugInfo, undefined, InclDefs) + ], + case lists:flatten(ModConfig) of + FlatModConfig when FlatModConfig =/= []; IsIncl -> + [{mod, Name, FlatModConfig}]; + _ -> + [] + end; do_gen_config(#rel{name = _Name, vsn = _Vsn, rel_apps = RelApps}, @@ -247,30 +268,33 @@ gen_app(#app{name = Name, gen_rel(Rel, Sys) -> try - {ok, do_gen_rel(Rel, Sys)} + MergedApps = merge_apps(Rel, Sys), + {ok, do_gen_rel(Rel, Sys, MergedApps)} catch throw:{error, Text} -> {error, Text} end. -do_gen_rel(#rel{name = RelName, vsn = RelVsn, rel_apps = RelApps}, - #sys{apps = Apps}) -> +do_gen_rel(#rel{name = RelName, vsn = RelVsn}, + #sys{apps = Apps}, + MergedApps) -> ErtsName = erts, case lists:keysearch(ErtsName, #app.name, Apps) of {value, Erts} -> {release, {RelName, RelVsn}, - {erts, Erts#app.vsn}, - [app_to_rel(RA, Apps ) || RA <- RelApps]}; + {ErtsName, Erts#app.vsn}, + [strip_rel_info(App) || App <- MergedApps]}; false -> reltool_utils:throw_error("Mandatory application ~p is " "not included", [ErtsName]) end. -app_to_rel(#rel_app{name = Name, app_type = Type, incl_apps = InclApps}, - Apps) -> - {value, #app{vsn = Vsn}} = lists:keysearch(Name, #app.name, Apps), +strip_rel_info(#app{name = Name, + vsn = Vsn, + app_type = Type, + info = #app_info{incl_apps = InclApps}}) -> case {Type, InclApps} of {undefined, []} -> {Name, Vsn}; {undefined, _} -> {Name, Vsn, InclApps}; @@ -278,6 +302,79 @@ app_to_rel(#rel_app{name = Name, app_type = Type, incl_apps = InclApps}, {_, _} -> {Name, Vsn, Type, InclApps} end. +merge_apps(#rel{name = RelName, rel_apps = RelApps}, + #sys{apps = Apps, app_type = DefType}) -> + Mandatory = [kernel, stdlib], + MergedApps = do_merge_apps(RelName, Mandatory, Apps, permanent, []), + MergedApps2 = do_merge_apps(RelName, RelApps, Apps, DefType, MergedApps), + sort_apps(MergedApps2). + +do_merge_apps(RelName, [#rel_app{name = Name} = RA | RelApps], Apps, DefType, Acc) -> + case is_already_merged(Name, RelApps, Acc) of + true -> + do_merge_apps(RelName, RelApps, Apps, DefType, Acc); + false -> + {value, App} = lists:keysearch(Name, #app.name, Apps), + MergedApp = merge_app(RelName, RA, DefType, App), + MoreNames = (MergedApp#app.info)#app_info.applications, + Acc2 = [MergedApp | Acc], + do_merge_apps(RelName, MoreNames ++ RelApps, Apps, DefType, Acc2) + end; +do_merge_apps(RelName, [Name | RelApps], Apps, DefType, Acc) -> + case is_already_merged(Name, RelApps, Acc) of + true -> + do_merge_apps(RelName, RelApps, Apps, DefType, Acc); + false -> + RelApp = init_rel_app(Name, Apps), + do_merge_apps(RelName, [RelApp | RelApps], Apps, DefType, Acc) + end; +do_merge_apps(_RelName, [], _Apps, _DefType, Acc) -> + lists:reverse(Acc). + +init_rel_app(Name, Apps) -> + {value, App} = lists:keysearch(Name, #app.name, Apps), + Info = App#app.info, + #rel_app{name = Name, + app_type = undefined, + incl_apps = Info#app_info.incl_apps}. + +merge_app(RelName, + #rel_app{name = Name, + app_type = RelAppType, + incl_apps = InclApps}, + DefType, + App) -> + Type = + case {RelAppType, App#app.app_type} of + {undefined, undefined} -> DefType; + {undefined, AppType} -> AppType; + {_, _} -> RelAppType + end, + Info = App#app.info, + case InclApps -- Info#app_info.incl_apps of + [] -> + App#app{app_type = Type, info = Info#app_info{incl_apps = InclApps}}; + BadIncl -> + reltool_utils:throw_error("~p: These applications are " + "used by release ~s but are " + "missing as included_applications " + "in the app file: ~p", + [Name, RelName, BadIncl]) + end. + +is_already_merged(Name, [Name | _], _MergedApps) -> + true; +is_already_merged(Name, [#rel_app{name = Name} | _], _MergedApps) -> + true; +is_already_merged(Name, [_ | RelApps], MergedApps) -> + is_already_merged(Name, RelApps, MergedApps); +is_already_merged(Name, [], [#app{name = Name} | _MergedApps]) -> + true; +is_already_merged(Name, [] = RelApps, [_ | MergedApps]) -> + is_already_merged(Name, RelApps, MergedApps); +is_already_merged(_Name, [], []) -> + false. + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Generate the contents of a boot file %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -291,27 +388,24 @@ gen_boot({script, {_, _}, _} = Script) -> gen_script(Rel, Sys, PathFlag, Variables) -> try - do_gen_script(Rel, Sys, PathFlag, Variables) + MergedApps = merge_apps(Rel, Sys), + do_gen_script(Rel, Sys, MergedApps, PathFlag, Variables) catch throw:{error, Text} -> {error, Text} end. -do_gen_script(#rel{name = RelName, vsn = RelVsn, rel_apps = RelApps}, - #sys{apps = Apps, app_type = DefaultType}, +do_gen_script(#rel{name = RelName, vsn = RelVsn}, + #sys{apps = Apps}, + MergedApps, PathFlag, Variables) -> {value, Erts} = lists:keysearch(erts, #app.name, Apps), Preloaded = [Mod#mod.name || Mod <- Erts#app.mods], Mandatory = mandatory_modules(), Early = Mandatory ++ Preloaded, - MergedApps = [merge_app(RA, Apps, DefaultType) || RA <- RelApps], - SortedApps = sort_apps(MergedApps), - {value, KernelApp} = lists:keysearch(kernel, #app.name, SortedApps), - - InclApps = - lists:append([I || - #app{info = #app_info{incl_apps = I}} <- SortedApps]), + {value, KernelApp} = lists:keysearch(kernel, #app.name, MergedApps), + InclApps = [I || #app{info = #app_info{incl_apps = I}} <- MergedApps], %% Create the script DeepList = @@ -321,30 +415,30 @@ do_gen_script(#rel{name = RelName, vsn = RelVsn, rel_apps = RelApps}, {progress, preloaded}, %% Load mandatory modules - {path, create_mandatory_path(SortedApps, PathFlag, Variables)}, + {path, create_mandatory_path(MergedApps, PathFlag, Variables)}, {primLoad, lists:sort(Mandatory)}, {kernel_load_completed}, {progress, kernel_load_completed}, %% Load remaining modules - [load_app_mods(A, Early, PathFlag, Variables) || A <- SortedApps], + [load_app_mods(A, Early, PathFlag, Variables) || A <- MergedApps], {progress, modules_loaded}, %% Start kernel processes - {path, create_path(SortedApps, PathFlag, Variables)}, + {path, create_path(MergedApps, PathFlag, Variables)}, kernel_processes(gen_app(KernelApp)), {progress, init_kernel_started}, %% Load applications [{apply, {application, load, [gen_app(A)]}} || - A = #app{name = Name, app_type = Type} <- SortedApps, + A = #app{name = Name, app_type = Type} <- MergedApps, Name =/= kernel, Type =/= none], {progress, applications_loaded}, %% Start applications [{apply, {application, start_boot, [Name, Type]}} || - #app{name = Name, app_type = Type} <- SortedApps, + #app{name = Name, app_type = Type} <- MergedApps, Type =/= none, Type =/= load, not lists:member(Name, InclApps)], @@ -355,28 +449,6 @@ do_gen_script(#rel{name = RelName, vsn = RelVsn, rel_apps = RelApps}, ], {ok, {script, {RelName, RelVsn}, lists:flatten(DeepList)}}. -merge_app(#rel_app{name = Name, app_type = Type, incl_apps = RelIncl}, - Apps, - DefaultType) -> - {value, App} = lists:keysearch(Name, #app.name, Apps), - Type2 = - case {Type, App#app.app_type} of - {undefined, undefined} -> DefaultType; - {undefined, AppType} -> AppType; - {_, _} -> Type - end, - Info = App#app.info, - case RelIncl -- Info#app_info.incl_apps of - [] -> - App#app{app_type = Type2, - info = Info#app_info{incl_apps = RelIncl}}; - BadIncl -> - reltool_utils:throw_error("~p: These applications are " - "missing as included_applications " - "in the app file: ~p\n", - [Name, BadIncl]) - end. - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% load_app_mods(#app{mods = Mods} = App, Mand, PathFlag, Variables) -> @@ -459,13 +531,13 @@ sort_apps([], [], [], _) -> []; sort_apps([], Missing, [], _) -> %% this has already been checked before, but as we have the info... - reltool_utils:throw_error("Undefined applications: ~p\n", + reltool_utils:throw_error("Undefined applications: ~p", [make_set(Missing)]); sort_apps([], [], Circular, _) -> - reltool_utils:throw_error("Circular dependencies: ~p\n", + reltool_utils:throw_error("Circular dependencies: ~p", [make_set(Circular)]); sort_apps([], Missing, Circular, _) -> - reltool_utils:throw_error("Circular dependencies: ~p\n" + reltool_utils:throw_error("Circular dependencies: ~p" "Undefined applications: ~p\n", [make_set(Circular), make_set(Missing)]). @@ -624,14 +696,15 @@ gen_rel_files(Sys, TargetDir) -> spec_rel_files(#sys{rels = Rels} = Sys) -> lists:append([do_spec_rel_files(R, Sys) || R <- Rels]). -do_spec_rel_files(#rel{name = Name} = Rel, Sys) -> - RelFile = Name ++ ".rel", - ScriptFile = Name ++ ".script", - BootFile = Name ++ ".boot", - GenRel = do_gen_rel(Rel, Sys), +do_spec_rel_files(#rel{name = RelName} = Rel, Sys) -> + RelFile = RelName ++ ".rel", + ScriptFile = RelName ++ ".script", + BootFile = RelName ++ ".boot", + MergedApps = merge_apps(Rel, Sys), + GenRel = do_gen_rel(Rel, Sys, MergedApps), PathFlag = true, Variables = [], - {ok, Script} = do_gen_script(Rel, Sys, PathFlag, Variables), + {ok, Script} = do_gen_script(Rel, Sys, MergedApps, PathFlag, Variables), {ok, BootBin} = gen_boot(Script), Date = date(), Time = time(), @@ -978,13 +1051,13 @@ spec_dir(Dir) -> Base, [spec_dir(filename:join([Dir, F])) || F <- Files]}; error -> - reltool_utils:throw_error("list dir ~s failed\n", [Dir]) + reltool_utils:throw_error("list dir ~s failed", [Dir]) end; {ok, #file_info{type = regular}} -> %% Plain file {copy_file, Base}; _ -> - reltool_utils:throw_error("read file info ~s failed\n", [Dir]) + reltool_utils:throw_error("read file info ~s failed", [Dir]) end. spec_mod(Mod, DebugInfo) -> @@ -1118,7 +1191,7 @@ do_eval_spec({archive, Archive, Options, Files}, {ok, _} -> ok; {error, Reason} -> - reltool_utils:throw_error("create archive ~s failed: ~p\n", + reltool_utils:throw_error("create archive ~s failed: ~p", [ArchiveFile, Reason]) end; do_eval_spec({copy_file, File}, _OrigSourceDir, SourceDir, TargetDir) -> @@ -1320,7 +1393,7 @@ do_install(RelName, TargetDir) -> ok = release_handler:create_RELEASES(TargetDir2, RelFile), ok; _ -> - reltool_utils:throw_error("~s: Illegal data file syntax.\n", [DataFile]) + reltool_utils:throw_error("~s: Illegal data file syntax", [DataFile]) end. subst_src_scripts(Scripts, SrcDir, DestDir, Vars, Opts) -> diff --git a/lib/reltool/src/reltool_utils.erl b/lib/reltool/src/reltool_utils.erl index 1768ee0db3..b33820c568 100644 --- a/lib/reltool/src/reltool_utils.erl +++ b/lib/reltool/src/reltool_utils.erl @@ -125,16 +125,18 @@ prim_parse(Tokens, Acc) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% default_rels() -> - Kernel = #rel_app{name = kernel, incl_apps = []}, - Stdlib = #rel_app{name = stdlib, incl_apps = []}, - Sasl = #rel_app{name = sasl, incl_apps = []}, + %%Kernel = #rel_app{name = kernel, incl_apps = []}, + %%Stdlib = #rel_app{name = stdlib, incl_apps = []}, + Sasl = #rel_app{name = sasl, incl_apps = []}, [ #rel{name = ?DEFAULT_REL_NAME, vsn = "1.0", - rel_apps = [Kernel, Stdlib]}, + rel_apps = []}, + %%rel_apps = [Kernel, Stdlib]}, #rel{name = "start_sasl", vsn = "1.0", - rel_apps = [Kernel, Sasl, Stdlib]} + rel_apps = [Sasl]} + %%rel_apps = [Kernel, Sasl, Stdlib]} ]. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -401,7 +403,7 @@ create_dir(Dir) -> ok; {error, Reason} -> Text = file:format_error(Reason), - throw_error("create dir ~s: ~s\n", [Dir, Text]) + throw_error("create dir ~s: ~s", [Dir, Text]) end. list_dir(Dir) -> @@ -410,7 +412,7 @@ list_dir(Dir) -> Files; error -> Text = file:format_error(enoent), - throw_error("list dir ~s: ~s\n", [Dir, Text]) + throw_error("list dir ~s: ~s", [Dir, Text]) end. read_file_info(File) -> @@ -419,7 +421,7 @@ read_file_info(File) -> Info; {error, Reason} -> Text = file:format_error(Reason), - throw_error("read file info ~s: ~s\n", [File, Text]) + throw_error("read file info ~s: ~s", [File, Text]) end. write_file_info(File, Info) -> @@ -428,7 +430,7 @@ write_file_info(File, Info) -> ok; {error, Reason} -> Text = file:format_error(Reason), - throw_error("write file info ~s: ~s\n", [File, Text]) + throw_error("write file info ~s: ~s", [File, Text]) end. read_file(File) -> @@ -437,7 +439,7 @@ read_file(File) -> Bin; {error, Reason} -> Text = file:format_error(Reason), - throw_error("read file ~s: ~s\n", [File, Text]) + throw_error("read file ~s: ~s", [File, Text]) end. write_file(File, IoList) -> @@ -446,7 +448,7 @@ write_file(File, IoList) -> ok; {error, Reason} -> Text = file:format_error(Reason), - throw_error("write file ~s: ~s\n", [File, Text]) + throw_error("write file ~s: ~s", [File, Text]) end. recursive_delete(Dir) -> diff --git a/lib/reltool/test/reltool_app_SUITE.erl b/lib/reltool/test/reltool_app_SUITE.erl index 3944190953..f8433f73d0 100644 --- a/lib/reltool/test/reltool_app_SUITE.erl +++ b/lib/reltool/test/reltool_app_SUITE.erl @@ -70,7 +70,7 @@ all(suite) -> [ fields, modules, - exportall, + export_all, app_depend, undef_funcs ]. @@ -175,11 +175,11 @@ extra_modules(Mods, [Mod|Ebins], Extra) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -exportall(suite) -> +export_all(suite) -> []; -exportall(doc) -> +export_all(doc) -> []; -exportall(Config) when is_list(Config) -> +export_all(Config) when is_list(Config) -> AppFile = key1search(app_file, Config), Mods = key1search(modules, AppFile), check_export_all(Mods). |