aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/reltool/bin/reltool.escript10
-rw-r--r--lib/reltool/doc/src/reltool_examples.xml4
-rw-r--r--lib/reltool/src/reltool_server.erl304
-rw-r--r--lib/reltool/src/reltool_target.erl271
-rw-r--r--lib/reltool/src/reltool_utils.erl24
-rw-r--r--lib/reltool/test/reltool_app_SUITE.erl8
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&gt; {ok, Server} = reltool:start_server([{config, {sys, [{boot_rel, "NAME"},
{rel, "NAME", "VSN",
- [kernel, stdlib, sasl]}]}}]).
+ [sasl]}]}}]).
{ok,&lt;0.1288.0&gt;}
6&gt; reltool:get_config(Server).
{ok,{sys,[{boot_rel,"NAME"},
- {rel,"NAME","VSN",[kernel,stdlib,sasl]}]}}
+ {rel,"NAME","VSN",[sasl]}]}}
7&gt; 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).