From ba3e53ef71cc127d4df9c53f9f401645814e3fb7 Mon Sep 17 00:00:00 2001 From: Siri Hansen Date: Thu, 15 Mar 2012 11:52:41 +0100 Subject: [reltool] Fix problems with sorting of applications OTP-9792 The following problems have been solved: * reltool_target:do_merge_apps - in recursive calls to this function, the accumulator was reverted each time causing the order of applications listed after kernel and stdlib in the rel specification in the configuration to sometimes be messed up. * There are several ways to specify wich applications to include in an application: 1) in the .app file for the including applications 2a) in the .rel file, when listing applications 2b) in the rel specification in the reltool configuration 2a (systools) and 2b (reltool) should have the same effect and overwrite 1. According to the documentation of systools (sasl), the default value in 2a is an empty list. This should mean that if included applications are not mentioned in the .rel file, then any included application listed in the .app file will be disregarded. This is NOT the way systools actually works. The implementation sets the default for the .rel file to the same list as in the .app file. Reltool earlier implemented 2b as described in the systools documentation. However, after some discussion we decided to change this so that reltool handles 2b in the same way as systools handles 2a since this seems more intuitive. The sasl documentation will be altered accordingly (internal ref OTP-9980). * If the rel specification in the reltool configuration explicitly specified included applications to be an empty list, and the .app file had a non-empty list, then the empty list from the rel specification was discarded. This has been corrected so the rel specification now, if set, always overwrites the value of included_applications in the .app file. * reltool would earlier add load instructions in the script/boot files for ALL modules in the ebin directory of an application even if mod_cond was set to app (include only modules listed in the .app file). This has been corrected - now only modules with #mod.is_included==true are loaded. * reltool would earlier add start instructions in the script/boot file for included applications. This has been corrected - included applications shall only be loaded since the including application is responsible for starting them. --- lib/reltool/src/reltool.hrl | 2 +- lib/reltool/src/reltool_server.erl | 30 +++++++++++++--- lib/reltool/src/reltool_target.erl | 72 ++++++++++++++++++++++---------------- lib/reltool/src/reltool_utils.erl | 8 ++--- 4 files changed, 69 insertions(+), 43 deletions(-) (limited to 'lib/reltool/src') diff --git a/lib/reltool/src/reltool.hrl b/lib/reltool/src/reltool.hrl index fc0078715a..4e5c5b2849 100644 --- a/lib/reltool/src/reltool.hrl +++ b/lib/reltool/src/reltool.hrl @@ -206,7 +206,7 @@ { name :: app_name(), app_type :: app_type() | undefined, - incl_apps = [] :: [incl_app()] + incl_apps :: [incl_app()] | undefined }). -record(rel, diff --git a/lib/reltool/src/reltool_server.erl b/lib/reltool/src/reltool_server.erl index 29df619955..c99180a613 100644 --- a/lib/reltool/src/reltool_server.erl +++ b/lib/reltool/src/reltool_server.erl @@ -560,10 +560,30 @@ apps_in_rels(Rels, Apps) -> apps_in_rel(#rel{name = RelName, rel_apps = RelApps}, Apps) -> 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)], + Other = + [{RelName, AppName} || + RA <- RelApps, + AppName <- [RA#rel_app.name | + %% Included applications in rel shall overwrite included + %% applications in .app. I.e. included applications in + %% .app shall only be used if it is not defined in rel. + case RA#rel_app.incl_apps of + undefined -> + case lists:keyfind(RA#rel_app.name, + #app.name, + Apps) of + #app{info = #app_info{incl_apps = IA}} -> + IA; + false -> + reltool_utils:throw_error( + "Release ~p uses non existing " + "application ~p", + [RelName,RA#rel_app.name]) + end; + IA -> + IA + end], + not lists:keymember(AppName, 2, Mandatory)], more_apps_in_rels(Mandatory ++ Other, Apps, []). more_apps_in_rels([{RelName, AppName} = RA | RelApps], Apps, Acc) -> @@ -1505,7 +1525,7 @@ decode(#rel{rel_apps = RelApps} = Rel, [RelApp | KeyVals]) -> {VT andalso VI, #rel_app{name = Name, app_type = Type, incl_apps = InclApps}}; _ -> - {false, #rel_app{incl_apps = []}} + {false, #rel_app{}} end, case ValidTypesAssigned of true -> diff --git a/lib/reltool/src/reltool_target.erl b/lib/reltool/src/reltool_target.erl index 40d1009733..3d83a77d99 100644 --- a/lib/reltool/src/reltool_target.erl +++ b/lib/reltool/src/reltool_target.erl @@ -208,10 +208,10 @@ do_gen_config(#rel_app{name = Name, incl_apps = InclApps}, _InclDefs) -> case {Type, InclApps} of - {undefined, []} -> Name; - {undefined, _} -> {Name, InclApps}; - {_, []} -> {Name, Type}; - {_, _} -> {Name, Type, InclApps} + {undefined, undefined} -> Name; + {undefined, _} -> {Name, InclApps}; + {_, undefined} -> {Name, Type}; + {_, _} -> {Name, Type, InclApps} end; do_gen_config({Tag, Val}, InclDefs) -> emit(Tag, Val, undefined, InclDefs); @@ -279,7 +279,7 @@ gen_rel(Rel, Sys) -> {error, Text} end. -do_gen_rel(#rel{name = RelName, vsn = RelVsn}, +do_gen_rel(#rel{name = RelName, vsn = RelVsn, rel_apps = RelApps}, #sys{apps = Apps}, MergedApps) -> ErtsName = erts, @@ -288,7 +288,7 @@ do_gen_rel(#rel{name = RelName, vsn = RelVsn}, {release, {RelName, RelVsn}, {ErtsName, Erts#app.vsn}, - [strip_rel_info(App) || App <- MergedApps]}; + [strip_rel_info(App, RelApps) || App <- MergedApps]}; false -> reltool_utils:throw_error("Mandatory application ~p is " "not included", @@ -298,13 +298,17 @@ do_gen_rel(#rel{name = RelName, vsn = RelVsn}, strip_rel_info(#app{name = Name, vsn = Vsn, app_type = Type, - info = #app_info{incl_apps = InclApps}}) - when Type =/= undefined -> - case {Type, InclApps} of - {permanent, []} -> {Name, Vsn}; - {permanent, _} -> {Name, Vsn, InclApps}; - {_, []} -> {Name, Vsn, Type}; - {_, _} -> {Name, Vsn, Type, InclApps} + info = #app_info{incl_apps = AppInclApps}}, + RelApps) when Type =/= undefined -> + RelInclApps = case lists:keyfind(Name,#rel_app.name,RelApps) of + #rel_app{incl_apps = RIA} when RIA =/= undefined -> RIA; + _ -> undefined + end, + case {Type, RelInclApps} of + {permanent, undefined} -> {Name, Vsn}; + {permanent, _} -> {Name, Vsn, AppInclApps}; + {_, undefined} -> {Name, Vsn, Type}; + {_, _} -> {Name, Vsn, Type, AppInclApps} end. merge_apps(#rel{name = RelName, @@ -323,7 +327,7 @@ merge_apps(#rel{name = RelName, A#app.name =/= ?MISSING_APP_NAME, not lists:keymember(A#app.name, #app.name, MergedApps2)], MergedApps3 = do_merge_apps(RelName, Embedded, Apps, EmbAppType, MergedApps2), - sort_apps(MergedApps3). + sort_apps(lists:reverse(MergedApps3)). do_merge_apps(RelName, [#rel_app{name = Name} = RA | RelApps], Apps, RelAppType, Acc) -> case is_already_merged(Name, RelApps, Acc) of @@ -341,25 +345,18 @@ do_merge_apps(RelName, [Name | RelApps], Apps, RelAppType, Acc) -> true -> do_merge_apps(RelName, RelApps, Apps, RelAppType, Acc); false -> - RelApp = init_rel_app(Name, Apps), + RelApp = #rel_app{name = Name}, do_merge_apps(RelName, [RelApp | RelApps], Apps, RelAppType, Acc) end; do_merge_apps(_RelName, [], _Apps, _RelAppType, 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}. + Acc. merge_app(RelName, - #rel_app{name = Name, - app_type = Type, - incl_apps = InclApps}, - RelAppType, - App) -> + #rel_app{name = Name, + app_type = Type, + incl_apps = InclApps0}, + RelAppType, + App) -> Type2 = case {Type, App#app.app_type} of {undefined, undefined} -> RelAppType; @@ -367,6 +364,11 @@ merge_app(RelName, {_, _} -> Type end, Info = App#app.info, + InclApps = + case InclApps0 of + undefined -> Info#app_info.incl_apps; + _ -> InclApps0 + end, case InclApps -- Info#app_info.incl_apps of [] -> App#app{app_type = Type2, info = Info#app_info{incl_apps = InclApps}}; @@ -421,7 +423,10 @@ do_gen_script(#rel{name = RelName, vsn = RelVsn}, Mandatory = mandatory_modules(), Early = Mandatory ++ Preloaded, {value, KernelApp} = lists:keysearch(kernel, #app.name, MergedApps), - InclApps = [I || #app{info = #app_info{incl_apps = I}} <- MergedApps], + InclApps = lists:flatmap(fun(#app{info = #app_info{incl_apps = I}}) -> + I + end, + MergedApps), %% Create the script DeepList = @@ -471,7 +476,7 @@ load_app_mods(#app{mods = Mods} = App, Mand, PathFlag, Variables) -> Path = cr_path(App, PathFlag, Variables), PartNames = lists:sort([{packages:split(M),M} || - #mod{name = M} <- Mods, + #mod{name = M, is_included=true} <- Mods, not lists:member(M, Mand)]), SplitMods = lists:foldl( @@ -513,7 +518,12 @@ sort_apps([#app{name = Name, info = Info} = App | Apps], Circular, Visited) -> {Uses, Apps1, NotFnd1} = - find_all(Name, Info#app_info.applications, Apps, Visited, [], []), + find_all(Name, + lists:reverse(Info#app_info.applications), + Apps, + Visited, + [], + []), {Incs, Apps2, NotFnd2} = find_all(Name, lists:reverse(Info#app_info.incl_apps), diff --git a/lib/reltool/src/reltool_utils.erl b/lib/reltool/src/reltool_utils.erl index 9cf9bd1418..3e50324011 100644 --- a/lib/reltool/src/reltool_utils.erl +++ b/lib/reltool/src/reltool_utils.erl @@ -126,18 +126,14 @@ 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 and stdlib are added automatically in every release [ #rel{name = ?DEFAULT_REL_NAME, vsn = "1.0", rel_apps = []}, - %%rel_apps = [Kernel, Stdlib]}, #rel{name = "start_sasl", vsn = "1.0", - rel_apps = [Sasl]} - %%rel_apps = [Kernel, Sasl, Stdlib]} + rel_apps = [#rel_app{name = sasl}]} ]. choose_default(Tag, Profile, InclDefs) -- cgit v1.2.3