From 067785da7c85152aa8d2436935e77fef3efaaa2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5kan=20Mattsson?= Date: Thu, 18 Feb 2010 17:06:58 +0100 Subject: Created escript for simplified usage from makefiles --- lib/reltool/bin/reltool.escript | 245 +++++++++++++++++++++++++++++++++++++ lib/reltool/doc/src/reltool.xml | 18 ++- lib/reltool/src/reltool.erl | 36 ++---- lib/reltool/src/reltool.hrl | 118 +++++++++--------- lib/reltool/src/reltool_server.erl | 5 +- 5 files changed, 333 insertions(+), 89 deletions(-) create mode 100644 lib/reltool/bin/reltool.escript (limited to 'lib') diff --git a/lib/reltool/bin/reltool.escript b/lib/reltool/bin/reltool.escript new file mode 100644 index 0000000000..567cafbcad --- /dev/null +++ b/lib/reltool/bin/reltool.escript @@ -0,0 +1,245 @@ +#!/usr/bin/env escript +%% -*- erlang -*- +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% + +-include_lib("reltool/src/reltool.hrl"). + +main(Args) -> + process_flag(trap_exit, true), + try + Tokens = scan_args(Args, [], []), + {Options, Actions} = parse_args(Tokens, []), + case invoke(Options, Actions) of + ok -> + erlang:halt(0); + {error, ReasonString} -> + fatal_error(ReasonString, 2) + end + catch + throw:usage -> + usage(), + erlang:halt(1); + exit:Reason -> + String = lists:flatten(io_lib:format("EXIT: ~p", [Reason])), + fatal_error(String, 3) + end. + +usage() -> + Usage = + [ + "[Config] [--window]", + "[Config] --create_config [-defaults] [-derived] [ConfigFile]", + "[Config] --create_rel RelName [RelFile]", + "[Config] --create_script RelName [ScriptFile]", + "[Config] --create_target TargetDir", + "[Config] --create_target_spec [SpecFile]", + "[Config] --eval_target_spec Spec TargetDir RootDir" + ], + Script = script_name(), + String = lists:flatten([[Script, " ", U, "\n"] || U <- Usage]), + io:format("Erlang/OTP release management tool\n\n" + "~s\nConfig = ConfigFile | '{sys, [sys()]}'\n" + "Spec = SpecFile | '{spec, [target_spec()}']\n\n" + "See User's guide and Reference manual for more info.\n", + [String]). + +invoke(Options, Actions) -> + case Actions of + [] -> + invoke(Options, [["--window"]]); + [["--window"]] -> + start_window(Options); + [["--create_config" | OptArgs]] -> + DefArg = "-defaults", + DerivArg = "-derived", + InclDef = lists:member(DefArg, OptArgs), + InclDeriv = lists:member(DerivArg, OptArgs), + case reltool:get_config(Options, InclDef, InclDeriv) of + {ok, Config} -> + String = pretty("config", Config), + case OptArgs -- [DefArg, DerivArg] of + [] -> + format("~s", [String]); + [ConfigFile] -> + write_file(ConfigFile, String); + _ -> + throw(usage) + end; + {error, Reason} -> + {error, Reason} + end; + [["--create_rel", RelName | OptArgs]] -> + case reltool:get_rel(Options, RelName) of + {ok, Rel} -> + String = pretty("rel", Rel), + case OptArgs of + [] -> + format("~s", [String]); + [RelFile] -> + write_file(RelFile, String); + _ -> + throw(usage) + end; + {error, Reason} -> + {error, Reason} + end; + [["--create_script", RelName | OptArgs]] -> + case reltool:get_script(Options, RelName) of + {ok, Script} -> + String = pretty("script", Script), + case OptArgs of + [] -> + format("~s", [String]); + [ScriptFile] -> + write_file(ScriptFile, String); + _ -> + throw(usage) + end; + {error, Reason} -> + {error, Reason} + end; + [["--create_target", TargetDir]] -> + reltool:create_target(Options, TargetDir); + [["--create_target_spec" | OptArgs]] -> + case reltool:get_target_spec(Options) of + {ok, Script} -> + String = pretty("target_spec", Script), + case OptArgs of + [] -> + format("~s", [String]); + [SpecFile] -> + write_file(SpecFile, String); + _ -> + throw(usage) + end; + {error, Reason} -> + {error, Reason} + end; + [["--eval_target_spec", TargetSpec, TargetDir, RootDir]] -> + try + {ok, Tokens, _} = erl_scan:string(TargetSpec ++ ". "), + {ok, {spec, Spec}} = erl_parse:parse_term(Tokens), + reltool:eval_target_spec(Spec, TargetDir, RootDir) + catch + error:{badmatch, _} -> + case file:consult(TargetSpec) of + {ok, Spec2} -> + reltool:eval_target_spec(Spec2, TargetDir, RootDir); + {error, Reason} -> + Text = file:format_error(Reason), + {error, TargetSpec ++ ": " ++ Text} + end + end; + _ -> + throw(usage) + end. + +start_window(Options) -> + case reltool:start_link(Options) of + {ok, WinPid} -> + receive + {'EXIT', WinPid, shutdown} -> + ok; + {'EXIT', WinPid, normal} -> + ok; + {'EXIT', WinPid, Reason} -> + exit(Reason) + end; + {error, Reason} -> + {error, Reason} + end. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Helpers +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +script_name() -> + filename:basename(escript:script_name(), ".escript"). + +fatal_error(String, Code) -> + io:format(standard_error, "~s: ~s\n", [script_name(), String]), + erlang:halt(Code). + +write_file(File, IoList) -> + case file:write_file(File, IoList) of + ok -> + ok; + {error, Reason} -> + {error, file:format_error(Reason)} + end. + +format(Format, Args) -> + io:format(Format, Args), + %% Wait a while for the I/O to be processed + timer:sleep(timer:seconds(1)). + +pretty(Tag, Term) -> + lists:flatten(io_lib:format("%% ~s generated at ~w ~w\n~p.\n\n", + [Tag, date(), time(), Term])). + +scan_args([H | T], Single, Multi) -> + case H of + "--" ++ _ when Single =:= [] -> + scan_args(T, [H], Multi); + "--" ++ _ -> + scan_args(T, [H], [lists:reverse(Single) | Multi]); + _ -> + scan_args(T, [H | Single], Multi) + end; +scan_args([], [], Multi) -> + lists:reverse(Multi); +scan_args([], Single, Multi) -> + lists:reverse([lists:reverse(Single) | Multi]). + +parse_args([H | T] = Args, Options) -> + case H of + ["--wx_debug" | Levels] -> + Dbg = + fun(L) -> + case catch list_to_integer(L) of + {'EXIT', _} -> + case catch list_to_atom(L) of + {'EXIT', _} -> + exit("Illegal wx debug level: " ++ L); + Atom -> + Atom + end; + Int -> + Int + end + end, + Levels2 = lists:map(Dbg, Levels), + parse_args(T, [{wx_debug, Levels2} | Options]); + ["--" ++ _ | _] -> + %% No more options + {lists:reverse(Options), Args}; + [Config] -> + try + {ok, Tokens, _} = erl_scan:string(Config ++ ". "), + {ok, {sys, _} = Sys} = erl_parse:parse_term(Tokens), + parse_args(T, [{config, Sys} | Options]) + catch + error:{badmatch, _} -> + parse_args(T, [{config, Config} | Options]); + X:Y -> + io:format("\n\n~p\n\n", [{X, Y}]) + end + end; +parse_args([], Options) -> + {lists:reverse(Options), []}. diff --git a/lib/reltool/doc/src/reltool.xml b/lib/reltool/doc/src/reltool.xml index 9786928ae8..15beec52d6 100644 --- a/lib/reltool/doc/src/reltool.xml +++ b/lib/reltool/doc/src/reltool.xml @@ -477,7 +477,9 @@ mod_name() = atom() profile() = development | embedded | standalone re_regexp() = string() reason() = string() -regexps() = [re_regexp()] | {add, [re_regexp()]} | {del, [re_regexp()]} +regexps() = [re_regexp()] + | {add, [re_regexp()]} + | {del, [re_regexp()]} rel_file() = term() rel_name() = string() rel_vsn() = string() @@ -487,7 +489,19 @@ script_file() = term() server() = server_pid() | options() server_pid() = pid() target_dir() = file() -window_pid() = pid()]]> +window_pid() = pid() +base_dir() = dir() +base_file() = file() +top_dir() = file() +top_file() = file() +target_spec() = [target_spec()] + | {create_dir, base_dir(), [target_spec()]} + | {create_dir, base_dir(), top_dir(), [target_spec()]} + | {archive, base_file(), [archive_opt()], [target_spec()]} + | {copy_file, base_file()} + | {copy_file, base_file(), top_file()} + | {write_file, base_file(), iolist()} + | {strip_beam_file, base_file()}]]> diff --git a/lib/reltool/src/reltool.erl b/lib/reltool/src/reltool.erl index e6a8bca069..ff200d0eb8 100644 --- a/lib/reltool/src/reltool.erl +++ b/lib/reltool/src/reltool.erl @@ -20,7 +20,6 @@ %% Public -export([ - main/1, % Escript start/0, start/1, start_link/1, debug/0, % GUI start_server/1, get_server/1, stop/1, get_config/1, get_config/3, get_rel/2, get_script/2, @@ -32,39 +31,26 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% Main function for escript --spec main([escript_arg()]) -> ok. -main(_) -> - process_flag(trap_exit, true), - {ok, WinPid} = start_link([]), - receive - {'EXIT', WinPid, shutdown} -> - ok; - {'EXIT', WinPid, normal} -> - ok; - {'EXIT', WinPid, Reason} -> - io:format("EXIT: ~p\n", [Reason]), - erlang:halt(1) - end. - %% Start main window process --spec start() -> {ok, window_pid()}. +-spec start() -> {ok, window_pid()} | {error, reason()}. start() -> start([]). %% Start main window process --spec start(options()) -> {ok, window_pid() | {error, reason()}}. +-spec start(options()) -> {ok, window_pid()} | {error, reason()}. start(Options)when is_list(Options) -> - {ok, WinPid} = start_link(Options), - unlink(WinPid), - {ok, WinPid}. + case start_link(Options) of + {ok, WinPid} -> + unlink(WinPid), + {ok, WinPid}; + Other-> + Other + end. %% Start main window process with wx debugging enabled --spec debug() -> {ok, window_pid()}. +-spec debug() -> {ok, window_pid()} | {error, reason()}. debug() -> - {ok, WinPid} = start_link([{wx_debug, 2}]), - unlink(WinPid), - {ok, WinPid}. + start([{wx_debug, 2}]). %% Start main window process with options -spec start_link(options()) -> {ok, window_pid() | {error, reason()}}. diff --git a/lib/reltool/src/reltool.hrl b/lib/reltool/src/reltool.hrl index 8a6a2142fd..d0a4c77657 100644 --- a/lib/reltool/src/reltool.hrl +++ b/lib/reltool/src/reltool.hrl @@ -104,7 +104,7 @@ -type rel_file() :: term(). -type script_file() :: term(). -type reason() :: string(). --type escript_arg() :: string(). + -type base_dir() :: dir(). -type base_file() :: file(). -type top_dir() :: file(). @@ -112,10 +112,7 @@ -type target_spec() :: [target_spec()] | {create_dir, base_dir(), [target_spec()]} | {create_dir, base_dir(), top_dir(), [target_spec()]} - | {archive, - base_file(), - [archive_opt()], - [target_spec()]} + | {archive, base_file(), [archive_opt()], [target_spec()]} | {copy_file, base_file()} | {copy_file, base_file(), top_file()} | {write_file, base_file(), iolist()} @@ -139,57 +136,58 @@ -record(mod, {%% Static - name :: mod_name(), - app_name :: app_name(), - incl_cond :: incl_cond() | undefined, - debug_info :: debug_info() | undefined, - is_app_mod :: boolean(), + name :: mod_name(), + app_name :: app_name(), + incl_cond :: incl_cond() | undefined, + debug_info :: debug_info() | undefined, + is_app_mod :: boolean(), is_ebin_mod :: boolean(), - uses_mods :: [mod_name()], - exists :: boolean(), + uses_mods :: [mod_name()], + exists :: boolean(), + %% Dynamic - status :: status(), - used_by_mods :: [mod_name()], + status :: status(), + used_by_mods :: [mod_name()], is_pre_included :: boolean() | undefined, - is_included :: boolean() | undefined + is_included :: boolean() | undefined }). -record(app_info, { - description = "", - id = "", - vsn = "", - modules = [], - maxP = infinity, - maxT = infinity, - registered = [], - incl_apps = [], - applications = [], - env = [], - mod = undefined, - start_phases = undefined + description = "" :: string(), + id = "" :: string(), + vsn = "" :: app_vsn(), + modules = [] :: [mod_name()], + maxP = infinity :: integer() | infinity, + maxT = infinity :: integer() | infinity, + registered = [] :: [atom()], + incl_apps = [] :: [app_name()], + applications = [] :: [app_name()], + env = [] :: [{atom(), term()}], + mod = undefined :: {mod_name(), [term()]} | undefined, + start_phases = undefined :: [{atom(), term()}] | undefined }). -record(app, {%% Static info - name :: app_name(), - is_escript :: boolean(), + name :: app_name(), + is_escript :: boolean(), use_selected_vsn :: boolean() | undefined, - active_dir :: dir(), - sorted_dirs :: [dir()], - vsn :: app_vsn(), - label :: app_label(), - info :: #app_info{} | undefined, - mods :: [#mod{}], + active_dir :: dir(), + sorted_dirs :: [dir()], + vsn :: app_vsn(), + label :: app_label(), + info :: #app_info{} | undefined, + mods :: [#mod{}], %% Static source cond - mod_cond :: mod_cond() | undefined, + mod_cond :: mod_cond() | undefined, incl_cond :: incl_cond() | undefined, %% Static target cond - debug_info :: debug_info() | undefined, - app_file :: app_file() | undefined, - app_type :: app_type(), + debug_info :: debug_info() | undefined, + app_file :: app_file() | undefined, + app_type :: app_type(), incl_app_filters :: incl_app_filters(), excl_app_filters :: excl_app_filters(), incl_archive_filters :: incl_archive_filters(), @@ -197,19 +195,19 @@ archive_opts :: [archive_opt()], %% Dynamic - status :: status(), - uses_mods :: [mod_name()], - used_by_mods :: [mod_name()], - uses_apps :: [app_name()], - used_by_apps :: [app_name()], + status :: status(), + uses_mods :: [mod_name()], + used_by_mods :: [mod_name()], + uses_apps :: [app_name()], + used_by_apps :: [app_name()], is_pre_included :: boolean(), - is_included :: boolean() + is_included :: boolean() }). -record(rel_app, { - name :: app_name(), - app_type :: app_type(), + name :: app_name(), + app_type :: app_type(), incl_apps :: [incl_app()] }). @@ -231,21 +229,21 @@ apps :: [#app{}], %% Target cond - boot_rel :: boot_rel(), - rels :: [#rel{}], - emu_name :: emu_name(), - profile :: profile(), - incl_sys_filters :: incl_sys_filters(), - excl_sys_filters :: excl_sys_filters(), - incl_app_filters :: incl_app_filters(), - excl_app_filters :: excl_app_filters(), + boot_rel :: boot_rel(), + rels :: [#rel{}], + emu_name :: emu_name(), + profile :: profile(), + incl_sys_filters :: incl_sys_filters(), + excl_sys_filters :: excl_sys_filters(), + incl_app_filters :: incl_app_filters(), + excl_app_filters :: excl_app_filters(), incl_archive_filters :: incl_archive_filters(), excl_archive_filters :: excl_archive_filters(), - archive_opts :: [archive_opt()], - relocatable :: boolean(), - app_type :: app_type(), - app_file :: app_file(), - debug_info :: debug_info() + archive_opts :: [archive_opt()], + relocatable :: boolean(), + app_type :: app_type(), + app_file :: app_file(), + debug_info :: debug_info() }). -record(regexp, {source, compiled}). diff --git a/lib/reltool/src/reltool_server.erl b/lib/reltool/src/reltool_server.erl index a7064f7651..a9985677ba 100644 --- a/lib/reltool/src/reltool_server.erl +++ b/lib/reltool/src/reltool_server.erl @@ -1093,8 +1093,9 @@ read_config(OldSys, Filename, Status) when is_list(Filename) -> {error, Reason} -> Text = file:format_error(Reason), {OldSys, - reltool_utils:return_first_error(Status, "File access: " ++ - Text)} + reltool_utils:return_first_error(Status, + "Illegal config file " ++ + Filename ++ ": " ++ Text)} end; read_config(OldSys, {sys, KeyVals}, Status) -> {NewSys, Status2} = -- cgit v1.2.3 From 2846d03cb026ec9f33ea32747b4a231e1239b1ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5kan=20Mattsson?= Date: Fri, 5 Mar 2010 15:56:02 +0100 Subject: Improved handling of applications explicitly included releases Applications that are listed in a release are now automatically included. --- lib/reltool/src/reltool.hrl | 7 +- lib/reltool/src/reltool_server.erl | 420 +++++++++++++++++++------------------ lib/reltool/src/reltool_target.erl | 217 +++++++++++-------- 3 files changed, 350 insertions(+), 294 deletions(-) (limited to 'lib') diff --git a/lib/reltool/src/reltool.hrl b/lib/reltool/src/reltool.hrl index d0a4c77657..b3f06e8753 100644 --- a/lib/reltool/src/reltool.hrl +++ b/lib/reltool/src/reltool.hrl @@ -177,11 +177,11 @@ sorted_dirs :: [dir()], vsn :: app_vsn(), label :: app_label(), - info :: #app_info{} | undefined, + info :: #app_info{} | undefined, mods :: [#mod{}], %% Static source cond - mod_cond :: mod_cond() | undefined, + mod_cond :: mod_cond() | undefined, incl_cond :: incl_cond() | undefined, %% Static target cond @@ -201,7 +201,8 @@ uses_apps :: [app_name()], used_by_apps :: [app_name()], is_pre_included :: boolean(), - is_included :: boolean() + is_included :: boolean(), + rels :: [rel_name()] }). -record(rel_app, diff --git a/lib/reltool/src/reltool_server.erl b/lib/reltool/src/reltool_server.erl index a9985677ba..6a3122f879 100644 --- a/lib/reltool/src/reltool_server.erl +++ b/lib/reltool/src/reltool_server.erl @@ -138,11 +138,12 @@ do_init(Options) -> proc_lib:init_ack(ParentPid, {ok, self(), C, Sys#sys{apps = undefined}}), {S2, Status2} = refresh(S, true, Status), - {S3, Status3} = analyse(S2#state{old_sys = S2#state.sys}, Status2), - case Status3 of - {ok, _Warnings} -> - loop(S3#state{status = Status3, old_status = {ok, []}}); - {error, Reason} -> + {S3, Status3} = + analyse(S2#state{old_sys = S2#state.sys}, Status2), + case Status3 of + {ok, _Warnings} -> % BUGBUG: handle warnings + loop(S3#state{status = Status3, old_status = {ok, []}}); + {error, Reason} -> exit(Reason) end end. @@ -161,33 +162,27 @@ parse_options(Opts) -> rels = reltool_utils:default_rels(), emu_name = ?DEFAULT_EMU_NAME, profile = ?DEFAULT_PROFILE, - incl_sys_filters = - reltool_utils:decode_regexps(incl_sys_filters, - ?DEFAULT_INCL_SYS_FILTERS, - []), - excl_sys_filters = - reltool_utils:decode_regexps(excl_sys_filters, - ?DEFAULT_EXCL_SYS_FILTERS, - []), - incl_app_filters = - reltool_utils:decode_regexps(incl_app_filters, - ?DEFAULT_INCL_APP_FILTERS, - []), - excl_app_filters = - reltool_utils:decode_regexps(excl_app_filters, - ?DEFAULT_EXCL_APP_FILTERS, - []), + incl_sys_filters = dec_re(incl_sys_filters, + ?DEFAULT_INCL_SYS_FILTERS, + []), + excl_sys_filters = dec_re(excl_sys_filters, + ?DEFAULT_EXCL_SYS_FILTERS, + []), + incl_app_filters = dec_re(incl_app_filters, + ?DEFAULT_INCL_APP_FILTERS, + []), + excl_app_filters = dec_re(excl_app_filters, + ?DEFAULT_EXCL_APP_FILTERS, + []), relocatable = ?DEFAULT_RELOCATABLE, app_type = ?DEFAULT_APP_TYPE, app_file = ?DEFAULT_APP_FILE, - incl_archive_filters = - reltool_utils:decode_regexps(incl_archive_filters, - ?DEFAULT_INCL_ARCHIVE_FILTERS, - []), - excl_archive_filters = - reltool_utils:decode_regexps(excl_archive_filters, - ?DEFAULT_EXCL_ARCHIVE_FILTERS, - []), + incl_archive_filters = dec_re(incl_archive_filters, + ?DEFAULT_INCL_ARCHIVE_FILTERS, + []), + excl_archive_filters = dec_re(excl_archive_filters, + ?DEFAULT_EXCL_ARCHIVE_FILTERS, + []), archive_opts = ?DEFAULT_ARCHIVE_OPTS, debug_info = ?DEFAULT_DEBUG_INFO}, C2 = #common{sys_debug = [], @@ -199,6 +194,9 @@ parse_options(Opts) -> S = #state{options = Opts}, parse_options(Opts, S, C2, Sys, {ok, []}). +dec_re(Key, Regexps, _Old) -> + reltool_utils:decode_regexps(Key, Regexps, _Old). + parse_options([{Key, Val} | KeyVals], S, C, Sys, Status) -> case Key of parent -> @@ -261,6 +259,7 @@ loop(#state{common = C, sys = Sys} = S) -> {ok, _Warnings} -> S5#state{status = Status3, old_status = S#state.status}; {error, _} -> + %% Keep old state S end, reltool_utils:reply(ReplyTo, Ref, Status3), @@ -277,9 +276,9 @@ loop(#state{common = C, sys = Sys} = S) -> Reply = case lists:keysearch(RelName, #rel.name, Sys#sys.rels) of {value, Rel} -> - {ok, reltool_target:gen_rel(Rel, Sys)}; + reltool_target:gen_rel(Rel, Sys); false -> - {error, "No such release"} + {error, "No such release: " ++ RelName} end, reltool_utils:reply(ReplyTo, Ref, Reply), ?MODULE:loop(S); @@ -292,7 +291,7 @@ loop(#state{common = C, sys = Sys} = S) -> Vars = [], reltool_target:gen_script(Rel, Sys, PathFlag, Vars); false -> - {error, "No such release"} + {error, "No such release: " ++ RelName} end, reltool_utils:reply(ReplyTo, Ref, Reply), ?MODULE:loop(S); @@ -312,7 +311,8 @@ loop(#state{common = C, sys = Sys} = S) -> {value, App} -> {ok, App}; false -> - {error, enoent} + {error, "No such application: " ++ + atom_to_list(AppName)} end, reltool_utils:reply(ReplyTo, Ref, Reply), ?MODULE:loop(S); @@ -327,6 +327,7 @@ loop(#state{common = C, sys = Sys} = S) -> reltool_utils:reply(ReplyTo, Ref, {ok, App2, Warnings}), ?MODULE:loop(S3); {error, Reason} -> + %% Keep old state reltool_utils:reply(ReplyTo, Ref, {error, Reason}), ?MODULE:loop(S) end; @@ -372,16 +373,20 @@ loop(#state{common = C, sys = Sys} = S) -> (Sys2#sys.lib_dirs =/= Sys#sys.lib_dirs) orelse (Sys2#sys.escripts =/= Sys#sys.escripts), {S3, Status} = refresh(S2, Force, {ok, []}), - {S4, Status2} = analyse(S3#state{old_sys = S#state.sys}, Status), - S6 = - case Status2 of - {ok, _Warnings} -> - S4#state{status = Status2, old_status = S#state.status}; - {error, _} -> - S - end, - reltool_utils:reply(ReplyTo, Ref, Status2), - ?MODULE:loop(S6); + {S4, Status2} = + analyse(S3#state{old_sys = S#state.sys}, Status), + {S5, Status3} = + case Status2 of + {ok, _Warnings} -> % BUGBUG: handle warnings + {S4#state{status = Status2, + old_status = S#state.status}, + Status2}; + {error, _} -> + %% Keep old state + {S, Status2} + end, + reltool_utils:reply(ReplyTo, Ref, Status3), + ?MODULE:loop(S5); {call, ReplyTo, Ref, get_status} -> reltool_utils:reply(ReplyTo, Ref, S#state.status), ?MODULE:loop(S); @@ -427,7 +432,9 @@ do_set_app(#state{sys = Sys} = S, App, Status) -> Sys2 = Sys#sys{apps = Apps2, escripts = Escripts}, {S#state{sys = Sys2}, Status2}. -analyse(#state{common = C, sys = #sys{apps = Apps0} = Sys} = S, Status) -> +analyse(#state{common = C, + sys = #sys{apps = Apps0, rels = Rels} = Sys} = S, + Status) -> Apps = lists:keydelete(?MISSING_APP, #app.name, Apps0), ets:delete_all_objects(C#common.app_tab), ets:delete_all_objects(C#common.mod_tab), @@ -435,7 +442,13 @@ analyse(#state{common = C, sys = #sys{apps = Apps0} = Sys} = S, Status) -> MissingApp = default_app(?MISSING_APP, "missing"), ets:insert(C#common.app_tab, MissingApp), - Apps2 = lists:map(fun(App) -> app_init_is_included(C, Sys, App) end, Apps), + RelApps = apps_in_rels(Rels), + {Apps2, Status2} = + lists:mapfoldl(fun(App, Acc) -> + app_init_is_included(C, Sys, App, RelApps, Acc) + end, + Status, + Apps), Apps3 = case app_propagate_is_included(C, Sys, Apps2, []) of [] -> @@ -454,15 +467,23 @@ analyse(#state{common = C, sys = #sys{apps = Apps0} = Sys} = S, Status) -> %% io:format("Missing app: ~p\n", %% [lists:keysearch(?MISSING_APP, #app.name, Apps4)]), Sys2 = Sys#sys{apps = Apps4}, - try - Status2 = verify_config(Sys2, Status), - {S#state{sys = Sys2}, Status2} - catch - throw:{error, Status3} -> + case verify_config(Sys2, Status2) of + {ok, _Warnings} = Status3 -> + {S#state{sys = Sys2}, Status3}; + {error, _} = Status3 -> {S, Status3} end. -app_init_is_included(C, Sys, #app{mods = Mods} = A) -> +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]]. + +app_init_is_included(C, + Sys, + #app{name = AppName, mods = Mods} = A, + RelApps, + Status) -> AppCond = case A#app.incl_cond of undefined -> Sys#sys.incl_cond; @@ -473,24 +494,37 @@ app_init_is_included(C, Sys, #app{mods = Mods} = A) -> undefined -> Sys#sys.mod_cond; _ -> A#app.mod_cond end, - IsIncl = - case AppCond of - include -> true; - exclude -> false; - derived -> undefined + Rels = [RelName || {RelName, AN} <- RelApps, AN =:= AppName], + {Default, IsPreIncl, IsIncl, Status2} = + case {AppCond, Rels} of + {include, _} -> + {undefined, true, true, Status}; + {exclude, []} -> + {undefined, false, false, Status}; + {exclude, [RelName | _]} -> % App is included in at least one rel + Text = lists:concat(["Application ", AppName, " is used " + "in release ", RelName, " and cannot " + "be excluded"]), + TmpStatus = reltool_utils:return_first_error(Status, Text), + {undefined, false, false, TmpStatus}; + {derived, []} -> + {undefined, undefined, undefined, Status}; + {derived, [_ | _]} -> % App is included in at least one rel + {true, undefined, true, Status} end, - A2 = A#app{is_pre_included = IsIncl, is_included = IsIncl}, + A2 = A#app{is_pre_included = IsPreIncl, + is_included = IsIncl, + rels = Rels}, ets:insert(C#common.app_tab, A2), lists:foreach(fun(Mod) -> mod_init_is_included(C, Mod, ModCond, AppCond, - undefined) + Default) end, Mods), - %%app_mod_init_is_included(C, AppName, Info, ModCond, AppCond), - A2. + {A2, Status2}. mod_init_is_included(C, M, ModCond, AppCond, Default) -> %% print(M#mod.name, hipe, "incl_cond -> ~p\n", [AppCond]), @@ -862,11 +896,15 @@ read_app_info(AppFileOrBin, AppFile, AppName, DefaultVsn, Status) -> parse_app_info(AppFile, Info, AI, Status); {ok, _BadApp} -> Text = lists:concat([AppName, - ": Illegal contents in app file ", AppFile]), + ": Illegal contents in app file ", AppFile, + ", application tuple with arity 3 expected."]), {missing_app_info(DefaultVsn), reltool_utils:add_warning(Status, Text)}; - {error, Text} when Text =:= EnoentText-> - {missing_app_info(DefaultVsn), Status}; + {error, Text} when Text =:= EnoentText -> + Text2 = lists:concat([AppName, + ": Missing app file ", AppFile, "."]), + {missing_app_info(DefaultVsn), + reltool_utils:add_warning(Status, Text2)}; {error, Text} -> Text2 = lists:concat([AppName, ": Cannot parse app file ", @@ -1045,7 +1083,7 @@ do_get_config(S, InclDef, InclDeriv) -> false -> shrink_sys(S); true -> S end, - {ok, reltool_target:gen_config(S2#state.sys, InclDef)}. + reltool_target:gen_config(S2#state.sys, InclDef). do_save_config(S, Filename, InclDef, InclDeriv) -> {ok, Config} = do_get_config(S, InclDef, InclDeriv), @@ -1072,6 +1110,7 @@ do_load_config(S, SysConfig) -> {ok, _Warnings2} -> S3#state{status = Status3, old_status = S#state.status}; {error, _} -> + %% Keep old state S end, {S4, Status3}; @@ -1099,24 +1138,30 @@ read_config(OldSys, Filename, Status) when is_list(Filename) -> end; read_config(OldSys, {sys, KeyVals}, Status) -> {NewSys, Status2} = - try - decode(OldSys#sys{apps = [], rels = []}, KeyVals, Status) - catch - throw:{error, Text} -> - {OldSys, reltool_utils:return_first_error(Status, Text)} - end, - Apps = [A#app{mods = lists:sort(A#app.mods)} || A <- NewSys#sys.apps], - case NewSys#sys.rels of - [] -> Rels = reltool_utils:default_rels(); - Rels -> ok - end, - NewSys2 = NewSys#sys{apps = lists:sort(Apps), rels = lists:sort(Rels)}, - case lists:keysearch(NewSys2#sys.boot_rel, #rel.name, NewSys2#sys.rels) of - {value, _} -> - {NewSys2, Status2}; - false -> - Text2 = "Missing rel: " ++ NewSys2#sys.boot_rel, - {OldSys, reltool_utils:return_first_error(Status2, Text2)} + decode(OldSys#sys{apps = [], rels = []}, KeyVals, Status), + case Status2 of + {ok, _Warnings} -> % BUGBUG: handle warnings + Apps = [A#app{mods = lists:sort(A#app.mods)} || + A <- NewSys#sys.apps], + case NewSys#sys.rels of + [] -> Rels = reltool_utils:default_rels(); + Rels -> ok + end, + NewSys2 = NewSys#sys{apps = lists:sort(Apps), + rels = lists:sort(Rels)}, + case lists:keysearch(NewSys2#sys.boot_rel, + #rel.name, + NewSys2#sys.rels) of + {value, _} -> + {NewSys2, Status2}; + false -> + Text2 = lists:concat(["Release " ++ NewSys2#sys.boot_rel, + " is mandatory (used as boot_rel)"]), + {OldSys, reltool_utils:return_first_error(Status2, Text2)} + end; + {error, _} -> + %% Keep old state + {OldSys, Status2} end; read_config(OldSys, BadConfig, Status) -> Text = lists:flatten(io_lib:format("~p", [BadConfig])), @@ -1175,96 +1220,78 @@ decode(#sys{} = Sys, [{Key, Val} | KeyVals], Status) -> profile when Val =:= development -> Val = ?DEFAULT_PROFILE, % assert, {Sys#sys{profile = Val, - incl_sys_filters = - reltool_utils:decode_regexps(incl_sys_filters, - ?DEFAULT_INCL_SYS_FILTERS, - Sys#sys.incl_sys_filters), - excl_sys_filters = - reltool_utils:decode_regexps(excl_sys_filters, - ?DEFAULT_EXCL_SYS_FILTERS, - Sys#sys.excl_sys_filters), - incl_app_filters = - reltool_utils:decode_regexps(incl_app_filters, - ?DEFAULT_INCL_APP_FILTERS, - Sys#sys.incl_app_filters), - excl_app_filters = - reltool_utils:decode_regexps(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 = - reltool_utils:decode_regexps(incl_sys_filters, - ?EMBEDDED_INCL_SYS_FILTERS, - Sys#sys.incl_sys_filters), - excl_sys_filters = - reltool_utils:decode_regexps(excl_sys_filters, - ?EMBEDDED_EXCL_SYS_FILTERS, - Sys#sys.excl_sys_filters), - incl_app_filters = - reltool_utils:decode_regexps(incl_app_filters, - ?EMBEDDED_INCL_APP_FILTERS, - Sys#sys.incl_app_filters), - excl_app_filters = - reltool_utils:decode_regexps(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 = - reltool_utils:decode_regexps(incl_sys_filters, - ?STANDALONE_INCL_SYS_FILTERS, - Sys#sys.incl_sys_filters), - excl_sys_filters = - reltool_utils:decode_regexps(excl_sys_filters, - ?STANDALONE_EXCL_SYS_FILTERS, - Sys#sys.excl_sys_filters), - incl_app_filters = - reltool_utils:decode_regexps(incl_app_filters, - ?STANDALONE_INCL_APP_FILTERS, - Sys#sys.incl_app_filters), - excl_app_filters = - reltool_utils:decode_regexps(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 = - reltool_utils:decode_regexps(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 = - reltool_utils:decode_regexps(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 = - reltool_utils:decode_regexps(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 = - reltool_utils:decode_regexps(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 = - reltool_utils:decode_regexps(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 = - reltool_utils:decode_regexps(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}; @@ -1304,7 +1331,7 @@ decode(#app{} = App, [{Key, Val} | KeyVals], Status) -> Val =:= strip -> {App#app{debug_info = Val}, Status}; app_file when Val =:= keep; - Val =:= strip, + Val =:= strip; Val =:= all -> {App#app{app_file = Val}, Status}; app_type when Val =:= permanent; @@ -1314,28 +1341,24 @@ decode(#app{} = App, [{Key, Val} | KeyVals], Status) -> Val =:= none -> {App#app{app_type = Val}, Status}; incl_app_filters -> - {App#app{incl_app_filters = - reltool_utils:decode_regexps(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 = - reltool_utils:decode_regexps(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 = - reltool_utils:decode_regexps(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 = - reltool_utils:decode_regexps(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}; @@ -1443,51 +1466,49 @@ merge_config(OldSys, NewSys, Force, Status) -> verify_config(Sys, Status) -> case lists:keymember(Sys#sys.boot_rel, #rel.name, Sys#sys.rels) of true -> - lists:foreach(fun(Rel)-> check_rel(Rel, Sys, Status) end, - Sys#sys.rels), - Status; + lists:foldl(fun(Rel, Acc)-> check_rel(Rel, Sys, Acc) end, + Status, + Sys#sys.rels); false -> - Text = lists:concat([Sys#sys.boot_rel, ": release is mandatory"]), - Status2 = reltool_utils:return_first_error(Status, Text), - throw({error, Status2}) + Text = lists:concat(["Release ", Sys#sys.boot_rel, + " 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) -> EnsureApp = - fun(AppName) -> + fun(AppName, Acc) -> case lists:keymember(AppName, #rel_app.name, RelApps) of true -> - ok; + Acc; false -> - Text = lists:concat([RelName, ": ", AppName, - " is not included."]), - Status2 = - reltool_utils:return_first_error(Status, Text), - throw({error, Status2}) + Text = lists:concat(["Mandatory application ", + AppName, + " is not included in release ", + RelName]), + reltool_utils:return_first_error(Acc, Text) end end, - EnsureApp(kernel), - EnsureApp(stdlib), + Mandatory = [kernel, stdlib], + Status2 = lists:foldl(EnsureApp, Status, Mandatory), CheckRelApp = - fun(#rel_app{name = AppName}) -> + fun(#rel_app{name = AppName}, Acc) -> case lists:keysearch(AppName, #app.name, Apps) of {value, App} when App#app.is_pre_included -> - ok; + Acc; {value, App} when App#app.is_included -> - ok; + Acc; _ -> - Text = - lists:concat([RelName, ": uses application ", - AppName, " that not is included."]), - Status2 = - reltool_utils:return_first_error(Status, Text), - %% throw BUGBUG: add throw - ({error, Status2}) + Text = lists:concat(["Release ", RelName, + " uses non included application ", + AppName]), + + reltool_utils:return_first_error(Acc, Text) end end, - lists:foreach(CheckRelApp, RelApps). + lists:foldl(CheckRelApp, Status2, RelApps). patch_erts_version(RootDir, Apps, Status) -> AppName = erts, @@ -1508,7 +1529,7 @@ patch_erts_version(RootDir, Apps, Status) -> {Apps, Status} end; false -> - Text = "erts cannnot be found in the root directory " ++ RootDir, + Text = "erts cannot be found in the root directory " ++ RootDir, Status2 = reltool_utils:return_first_error(Status, Text), {Apps, Status2} end. @@ -1814,7 +1835,8 @@ default_app(Name) -> status = missing, uses_mods = undefined, is_pre_included = undefined, - is_included = undefined}. + is_included = undefined, + rels = undefined}. %% Assume that the application are sorted refresh_apps([Old | OldApps], [New | NewApps], Acc, Force, Status) diff --git a/lib/reltool/src/reltool_target.erl b/lib/reltool/src/reltool_target.erl index e079a02f3c..a4440f8fb1 100644 --- a/lib/reltool/src/reltool_target.erl +++ b/lib/reltool/src/reltool_target.erl @@ -64,36 +64,39 @@ kernel_processes(KernelApp) -> %% Generate the contents of a config file %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -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}, - InclDefs) -> +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, + incl_archive_filters = InclArchiveDirs, + excl_archive_filters = ExclArchiveDirs, + archive_opts = ArchiveOpts, + relocatable = Relocatable, + app_type = AppType, + app_file = AppFile, + debug_info = DebugInfo}, + InclDefs) -> ErtsItems = case lists:keysearch(erts, #app.name, Apps) of {value, Erts} -> - [{erts, gen_config(Erts, InclDefs)}]; + [{erts, do_gen_config(Erts, InclDefs)}]; false -> [] end, AppsItems = - [{app, A#app.name, gen_config(A, InclDefs)} + [{app, A#app.name, do_gen_config(A, InclDefs)} || A <- Apps, A#app.name =/= ?MISSING_APP, A#app.name =/= erts, @@ -102,16 +105,19 @@ gen_config(#sys{root_dir = RootDir, EscriptItems = [{escript, A#app.active_dir, emit(incl_cond, A#app.incl_cond, undefined, InclDefs)} - || A <- Apps, A#app.is_escript], + || A <- Apps, A#app.is_escript], DefaultRels = reltool_utils:default_rels(), RelsItems = - case {[{rel, R#rel.name, R#rel.vsn, gen_config(R, InclDefs)} || - R <- Rels], - [{rel, R#rel.name, R#rel.vsn, gen_config(R, InclDefs)} || - R <- DefaultRels]} of - {RI, RI} -> []; - {RI, _} -> RI - end, + [{rel, R#rel.name, R#rel.vsn, do_gen_config(R, InclDefs)} || + R <- Rels], + DefaultRelsItems = + [{rel, R#rel.name, R#rel.vsn, do_gen_config(R, InclDefs)} || + R <- DefaultRels], + RelsItems2 = + case InclDefs of + true -> RelsItems; + false -> RelsItems -- DefaultRelsItems + end, X = fun(List) -> [Re || #regexp{source = Re} <- List] end, {sys, emit(root_dir, RootDir, code:root_dir(), InclDefs) ++ @@ -122,7 +128,7 @@ gen_config(#sys{root_dir = RootDir, ErtsItems ++ AppsItems ++ emit(boot_rel, BootRel, ?DEFAULT_REL_NAME, InclDefs) ++ - RelsItems ++ + RelsItems2 ++ emit(emu_name, EmuName, ?DEFAULT_EMU_NAME, InclDefs) ++ emit(relocatable, Relocatable, ?DEFAULT_RELOCATABLE, InclDefs) ++ emit(profile, Profile, ?DEFAULT_PROFILE, InclDefs) ++ @@ -136,60 +142,60 @@ 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)}; -gen_config(#app{name = _Name, - mod_cond = ModCond, - incl_cond = AppCond, - debug_info = DebugInfo, - app_file = AppFile, - incl_app_filters = InclAppFiles, - excl_app_filters = ExclAppFiles, - incl_archive_filters = InclArchiveDirs, - excl_archive_filters = ExclArchiveDirs, - archive_opts = ArchiveOpts, - use_selected_vsn = UseSelected, - vsn = Vsn, - mods = Mods}, - InclDefs) -> +do_gen_config(#app{name = _Name, + mod_cond = ModCond, + incl_cond = AppCond, + debug_info = DebugInfo, + app_file = AppFile, + incl_app_filters = InclAppFiles, + excl_app_filters = ExclAppFiles, + incl_archive_filters = InclArchiveDirs, + excl_archive_filters = ExclArchiveDirs, + archive_opts = ArchiveOpts, + use_selected_vsn = UseSelected, + vsn = Vsn, + mods = Mods}, + 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, gen_config(M, InclDefs)} || - M <- Mods, - M#mod.is_included =:= true]; -gen_config(#mod{name = _Name, - incl_cond = AppCond, - debug_info = DebugInfo}, - 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, + incl_cond = AppCond, + debug_info = DebugInfo}, + InclDefs) -> emit(incl_cond, AppCond, undefined, InclDefs) ++ - emit(debug_info, DebugInfo, undefined, InclDefs); -gen_config(#rel{name = _Name, - vsn = _Vsn, - rel_apps = RelApps}, - InclDefs) -> - [gen_config(RA, InclDefs) || RA <- RelApps]; -gen_config(#rel_app{name = Name, - app_type = Type, - incl_apps = InclApps}, - _InclDefs) -> + emit(debug_info, DebugInfo, undefined, InclDefs); +do_gen_config(#rel{name = _Name, + vsn = _Vsn, + rel_apps = RelApps}, + InclDefs) -> + [do_gen_config(RA, InclDefs) || RA <- RelApps]; +do_gen_config(#rel_app{name = Name, + app_type = Type, + incl_apps = InclApps}, + _InclDefs) -> case {Type, InclApps} of {undefined, []} -> Name; {undefined, _} -> {Name, InclApps}; {_, []} -> {Name, Type}; {_, _} -> {Name, Type, InclApps} end; -gen_config({Tag, Val}, InclDefs) -> +do_gen_config({Tag, Val}, InclDefs) -> emit(Tag, Val, undefined, InclDefs); -gen_config([], _InclDefs) -> +do_gen_config([], _InclDefs) -> []; -gen_config([H | T], InclDefs) -> - lists:flatten([gen_config(H, InclDefs), gen_config(T, InclDefs)]). +do_gen_config([H | T], InclDefs) -> + lists:flatten([do_gen_config(H, InclDefs), do_gen_config(T, InclDefs)]). emit(Tag, Val, Default, InclDefs) -> if @@ -239,13 +245,28 @@ gen_app(#app{name = Name, %% Generate the contents of a rel file %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -gen_rel(#rel{name = RelName, vsn = RelVsn, rel_apps = RelApps}, - #sys{apps = Apps}) -> - {value, Erts} = lists:keysearch(erts, #app.name, Apps), - {release, - {RelName, RelVsn}, - {erts, Erts#app.vsn}, - [app_to_rel(RA, Apps ) || RA <- RelApps]}. +gen_rel(Rel, Sys) -> + try + {ok, do_gen_rel(Rel, Sys)} + catch + throw:{error, Text} -> + {error, Text} + end. + +do_gen_rel(#rel{name = RelName, vsn = RelVsn, rel_apps = RelApps}, + #sys{apps = Apps}) -> + 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]}; + 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) -> @@ -607,7 +628,7 @@ do_spec_rel_files(#rel{name = Name} = Rel, Sys) -> RelFile = Name ++ ".rel", ScriptFile = Name ++ ".script", BootFile = Name ++ ".boot", - GenRel = gen_rel(Rel, Sys), + GenRel = do_gen_rel(Rel, Sys), PathFlag = true, Variables = [], {ok, Script} = do_gen_script(Rel, Sys, PathFlag, Variables), @@ -678,7 +699,8 @@ strip_sys_files(Relocatable, SysFiles, Apps, ExclRegexps) -> true -> ExtraExcl = ["^erts.*/bin/.*src\$"], reltool_utils:decode_regexps(excl_sys_filters, - {add, ExtraExcl}, ExclRegexps); + {add, ExtraExcl}, + ExclRegexps); false -> ExclRegexps end, @@ -759,18 +781,29 @@ spec_bin_files(Sys, AllSysFiles, StrippedSysFiles, RelFiles, InclRegexps) -> GoodNames = [F || {copy_file, F} <- OldBinFiles, not lists:suffix(".boot", F), not lists:suffix(".script", F)], - BinFiles2 = [Map(S) || S <- BinFiles, lists:member(element(2, S), GoodNames)], + BinFiles2 = [Map(S) || S <- BinFiles, + lists:member(element(2, S), GoodNames)], BootFiles = [F || F <- RelFiles, lists:suffix(".boot", element(2, F))], - [{write_file, _, BootRel}] = safe_lookup_spec(Sys#sys.boot_rel ++ ".boot", BootFiles), - BootFiles2 = lists:keystore("start.boot", 2, BootFiles, {write_file, "start.boot", BootRel}), - MakeRegexp = fun(File) -> "^bin/" ++ element(2, File) ++ "(|.escript)\$" end, + [{write_file, _, BootRel}] = + safe_lookup_spec(Sys#sys.boot_rel ++ ".boot", BootFiles), + BootFiles2 = lists:keystore("start.boot", + 2, + BootFiles, + {write_file, "start.boot", BootRel}), + MakeRegexp = + fun(File) -> "^bin/" ++ element(2, File) ++ "(|.escript)\$" end, ExtraIncl = lists:map(MakeRegexp, Escripts), - InclRegexps2 = reltool_utils:decode_regexps(incl_sys_filters, {add, ExtraIncl}, InclRegexps), + InclRegexps2 = reltool_utils:decode_regexps(incl_sys_filters, + {add, ExtraIncl}, + InclRegexps), {InclRegexps2, Escripts ++ BinFiles2 ++ BootFiles2}. spec_escripts(#sys{apps = Apps}, ErtsBin, BinFiles) -> - Filter = fun(#app{is_escript = IsEscript, is_included = IsIncl, - is_pre_included = IsPre, name = Name, active_dir = File}) -> + Filter = fun(#app{is_escript = IsEscript, + is_included = IsIncl, + is_pre_included = IsPre, + name = Name, + active_dir = File}) -> if Name =:= ?MISSING_APP -> false; -- cgit v1.2.3 From 512b1a258c083021f199e6cad2da479e7fdfd6dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5kan=20Mattsson?= Date: Tue, 9 Mar 2010 18:46:31 +0100 Subject: Add function to return status about the configuration It is called reltool:get_status/1. The API functions in reltool that may take PidOrOptions as input and actually gets Options does now print out the warnings. --- lib/reltool/doc/src/reltool.xml | 11 +++++++ lib/reltool/src/reltool.erl | 50 +++++++++++++++++++++++-------- lib/reltool/src/reltool_target.erl | 29 ++++++++++-------- lib/reltool/test/reltool_server_SUITE.erl | 20 ++++++++----- lib/reltool/test/rtt | 2 +- 5 files changed, 78 insertions(+), 34 deletions(-) (limited to 'lib') diff --git a/lib/reltool/doc/src/reltool.xml b/lib/reltool/doc/src/reltool.xml index 15beec52d6..24683b9302 100644 --- a/lib/reltool/doc/src/reltool.xml +++ b/lib/reltool/doc/src/reltool.xml @@ -617,6 +617,17 @@ target_spec() = [target_spec()] more details.

+ + get_status(Server) -> {ok, [Warning]} | {error, Reason} + Get contents of a release file + + Server = server() + Warning = string() + Reason = reason() + +

Get status about the configuration

+
+ get_server(WindowPid) -> {ok, ServerPid} | {error, Reason} Start server process with options diff --git a/lib/reltool/src/reltool.erl b/lib/reltool/src/reltool.erl index ff200d0eb8..351a3d59cf 100644 --- a/lib/reltool/src/reltool.erl +++ b/lib/reltool/src/reltool.erl @@ -21,7 +21,7 @@ %% Public -export([ start/0, start/1, start_link/1, debug/0, % GUI - start_server/1, get_server/1, stop/1, + start_server/1, get_server/1, get_status/1, stop/1, get_config/1, get_config/3, get_rel/2, get_script/2, create_target/2, get_target_spec/1, eval_target_spec/3, install/2 @@ -96,20 +96,45 @@ stop(Pid) when is_pid(Pid) -> end. %% Internal library function --spec eval_server(server(), fun((server_pid()) -> term())) -> +-spec eval_server(server(), boolean(), fun((server_pid()) -> term())) -> {ok, server_pid()} | {error, reason()}. -eval_server(Pid, Fun) when is_pid(Pid) -> +eval_server(Pid, DisplayWarnings, Fun) + when is_pid(Pid), is_boolean(DisplayWarnings) -> Fun(Pid); -eval_server(Options, Fun) when is_list(Options), is_function(Fun, 1) -> +eval_server(Options, DisplayWarnings, Fun) + when is_list(Options), is_boolean(DisplayWarnings), is_function(Fun, 1) -> case start_server(Options) of {ok, Pid} -> - Res = Fun(Pid), - stop(Pid), - Res; + apply_fun(Pid, DisplayWarnings, Fun); {error, Reason} -> {error, Reason} end. +apply_fun(Pid, false, Fun) -> + Res = Fun(Pid), + stop(Pid), + Res; +apply_fun(Pid, true, Fun) -> + case get_status(Pid) of + {ok, Warnings} -> + [io:format("~p: ~s\n", [?APPLICATION, W]) || W <- Warnings], + apply_fun(Pid, false, Fun); + {error, Reason} -> + stop(Pid), + {error, Reason} + end. + +%% Get status about the configuration +-type warning() :: string(). +-spec get_status(server()) -> + {ok, [warning()]} | {error, reason()}. +get_status(PidOrOptions) + when is_pid(PidOrOptions); is_list(PidOrOptions) -> + eval_server(PidOrOptions, false, + fun(Pid) -> + reltool_server:get_status(Pid) + end). + %% Get reltool configuration -spec get_config(server()) -> {ok, config()} | {error, reason()}. get_config(PidOrOption) -> @@ -119,7 +144,7 @@ get_config(PidOrOption) -> {ok, config()} | {error, reason()}. get_config(PidOrOptions, InclDef, InclDeriv) when is_pid(PidOrOptions); is_list(PidOrOptions) -> - eval_server(PidOrOptions, + eval_server(PidOrOptions, true, fun(Pid) -> reltool_server:get_config(Pid, InclDef, InclDeriv) end). @@ -128,7 +153,7 @@ get_config(PidOrOptions, InclDef, InclDeriv) -spec get_rel(server(), rel_name()) -> {ok, rel_file()} | {error, reason()}. get_rel(PidOrOptions, RelName) when is_pid(PidOrOptions); is_list(PidOrOptions) -> - eval_server(PidOrOptions, + eval_server(PidOrOptions, true, fun(Pid) -> reltool_server:get_rel(Pid, RelName) end). %% Get contents of boot script file @@ -136,21 +161,22 @@ get_rel(PidOrOptions, RelName) {ok, script_file()} | {error, reason()}. get_script(PidOrOptions, RelName) when is_pid(PidOrOptions); is_list(PidOrOptions) -> - eval_server(PidOrOptions, + eval_server(PidOrOptions, true, fun(Pid) -> reltool_server:get_script(Pid, RelName) end). %% Generate a target system -spec create_target(server(), target_dir()) -> ok | {error, reason()}. create_target(PidOrOptions, TargetDir) when is_pid(PidOrOptions); is_list(PidOrOptions) -> - eval_server(PidOrOptions, + eval_server(PidOrOptions, true, fun(Pid) -> reltool_server:gen_target(Pid, TargetDir) end). %% Generate a target system -spec get_target_spec(server()) -> {ok, target_spec()} | {error, reason()}. get_target_spec(PidOrOptions) when is_pid(PidOrOptions); is_list(PidOrOptions) -> - eval_server(PidOrOptions, fun(Pid) -> reltool_server:gen_spec(Pid) end). + eval_server(PidOrOptions, true, + fun(Pid) -> reltool_server:gen_spec(Pid) end). %% Generate a target system -spec eval_target_spec(target_spec(), root_dir(), target_dir()) -> diff --git a/lib/reltool/src/reltool_target.erl b/lib/reltool/src/reltool_target.erl index a4440f8fb1..160cbd8e15 100644 --- a/lib/reltool/src/reltool_target.erl +++ b/lib/reltool/src/reltool_target.erl @@ -707,16 +707,17 @@ strip_sys_files(Relocatable, SysFiles, Apps, ExclRegexps) -> {value, Erts} = lists:keysearch(erts, #app.name, Apps), FilterErts = fun(Spec) -> - File = element(2, Spec), - case lists:prefix("erts", File) of - true -> - if - File =:= Erts#app.label -> - replace_dyn_erl(Relocatable, Spec); - true -> - false - end; - false -> + File = element(2, Spec), + case File of + "erts" -> + reltool_utils:throw_error("This system is not installed. " + "The directory ~s is missing.", + [Erts#app.label]); + _ when File =:= Erts#app.label -> + replace_dyn_erl(Relocatable, Spec); + "erts-" ++ _ -> + false; + _ -> true end end, @@ -729,7 +730,8 @@ strip_sys_files(Relocatable, SysFiles, Apps, ExclRegexps) -> replace_dyn_erl(false, _ErtsSpec) -> true; replace_dyn_erl(true, {create_dir, ErtsDir, ErtsFiles}) -> - [{create_dir, _, BinFiles}] = safe_lookup_spec("bin", ErtsFiles), + [{create_dir, _, BinFiles}] = + safe_lookup_spec("bin", ErtsFiles), case lookup_spec("dyn_erl", BinFiles) of [] -> case lookup_spec("erl.ini", BinFiles) of @@ -853,6 +855,7 @@ lookup_spec(Prefix, Specs) -> safe_lookup_spec(Prefix, Specs) -> case lookup_spec(Prefix, Specs) of [] -> + %% io:format("lookup fail ~s:\n\t~p\n", [Prefix, Specs]), reltool_utils:throw_error("Mandatory system file ~s is " "not included", [Prefix]); Match -> @@ -1115,7 +1118,7 @@ do_eval_spec({archive, Archive, Options, Files}, {ok, _} -> ok; {error, Reason} -> - reltool_utils:throw_error("create archive ~s: ~p\n", + reltool_utils:throw_error("create archive ~s failed: ~p\n", [ArchiveFile, Reason]) end; do_eval_spec({copy_file, File}, _OrigSourceDir, SourceDir, TargetDir) -> @@ -1317,7 +1320,7 @@ do_install(RelName, TargetDir) -> ok = release_handler:create_RELEASES(TargetDir2, RelFile), ok; _ -> - reltool_utils:throw_error("~s: Illegal syntax.\n", [DataFile]) + reltool_utils:throw_error("~s: Illegal data file syntax.\n", [DataFile]) end. subst_src_scripts(Scripts, SrcDir, DestDir, Vars, Opts) -> diff --git a/lib/reltool/test/reltool_server_SUITE.erl b/lib/reltool/test/reltool_server_SUITE.erl index cf951191a0..df53d0cc23 100644 --- a/lib/reltool/test/reltool_server_SUITE.erl +++ b/lib/reltool/test/reltool_server_SUITE.erl @@ -26,11 +26,13 @@ -include("reltool_test_lib.hrl"). -define(NODE_NAME, '__RELTOOL__TEMPORARY_TEST__NODE__'). +-define(WORK_DIR, "reltool_work_dir"). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Initialization functions. init_per_suite(Config) -> + ?ignore(file:make_dir(?WORK_DIR)), reltool_test_lib:init_per_suite(Config). end_per_suite(Config) -> @@ -161,13 +163,15 @@ create_script(_Config) -> {erts, ErtsVsn}, [{stdlib, StdlibVsn}, {kernel, KernelVsn}]}, ?m({ok, Rel}, reltool:get_rel(Pid, RelName)), - RelFile = RelName ++ ".rel", - ?m(ok, file:write_file(RelFile, io_lib:format("~p.\n", [Rel]))), + ?m(ok, file:write_file(filename:join([?WORK_DIR, RelName ++ ".rel"]), + io_lib:format("~p.\n", [Rel]))), %% Generate script file + {ok, Cwd} = file:get_cwd(), + ?m(ok, file:set_cwd(?WORK_DIR)), ?m(ok, systools:make_script(RelName, [])), - ScriptFile = RelName ++ ".script", - {ok, [OrigScript]} = ?msym({ok, [_]}, file:consult(ScriptFile)), + {ok, [OrigScript]} = ?msym({ok, [_]}, file:consult(RelName ++ ".script")), + ?m(ok, file:set_cwd(Cwd)), {ok, Script} = ?msym({ok, _}, reltool:get_script(Pid, RelName)), %% OrigScript2 = sort_script(OrigScript), %% Script2 = sort_script(Script), @@ -201,7 +205,7 @@ create_target(_Config) -> ]}, %% Generate target file - TargetDir = "reltool_target_dir_development", + TargetDir = filename:join([?WORK_DIR, "target_development"]), ?m(ok, reltool_utils:recursive_delete(TargetDir)), ?m(ok, file:make_dir(TargetDir)), ?m(ok, reltool:create_target([{config, Config}], TargetDir)), @@ -234,7 +238,7 @@ create_embedded(_Config) -> ]}, %% Generate target file - TargetDir = "reltool_target_dir_embedded", + TargetDir = filename:join([?WORK_DIR, "target_embedded"]), ?m(ok, reltool_utils:recursive_delete(TargetDir)), ?m(ok, file:make_dir(TargetDir)), ?m(ok, reltool:create_target([{config, Config}], TargetDir)), @@ -264,7 +268,7 @@ create_standalone(_Config) -> ]}, %% Generate target file - TargetDir = "reltool_target_dir_standalone", + TargetDir = filename:join([?WORK_DIR, "target_standalone"]), ?m(ok, reltool_utils:recursive_delete(TargetDir)), ?m(ok, file:make_dir(TargetDir)), ?m(ok, reltool:create_target([{config, Config}], TargetDir)), @@ -306,7 +310,7 @@ create_old_target(_Config) -> ]}, %% Generate target file - TargetDir = "reltool_target_dir_old", + TargetDir = filename:join([?WORK_DIR, "target_old_style"]), ?m(ok, reltool_utils:recursive_delete(TargetDir)), ?m(ok, file:make_dir(TargetDir)), ?m(ok, reltool:create_target([{config, Config}], TargetDir)), diff --git a/lib/reltool/test/rtt b/lib/reltool/test/rtt index 2411195338..940bcdf451 100755 --- a/lib/reltool/test/rtt +++ b/lib/reltool/test/rtt @@ -23,7 +23,7 @@ while [ $# -gt 0 ]; do case "$1" in "-cerl") shift - emu=cerl + emu="$ERL_TOP/bin/cerl" ;; *) break -- cgit v1.2.3 From 6512dbbb4c119deda0b1185c5ec9a6e5b32a22fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5kan=20Mattsson?= Date: Mon, 15 Mar 2010 10:53:50 +0100 Subject: Add app and appup files to reltool --- lib/reltool/src/Makefile | 42 ++++++++++++++++++++--------------- lib/reltool/src/files.mk | 32 +++++++++++++++++++++++++++ lib/reltool/src/reltool.app.src | 46 ++++++++++++++++++++------------------- lib/reltool/src/reltool.appup.src | 22 +++++++++++++++++++ 4 files changed, 103 insertions(+), 39 deletions(-) create mode 100644 lib/reltool/src/files.mk create mode 100644 lib/reltool/src/reltool.appup.src (limited to 'lib') diff --git a/lib/reltool/src/Makefile b/lib/reltool/src/Makefile index 7fac7cbf88..4e6a112b7e 100644 --- a/lib/reltool/src/Makefile +++ b/lib/reltool/src/Makefile @@ -28,7 +28,6 @@ include ../vsn.mk VSN = $(RELTOOL_VSN) APP_VSN = "reltool-$(VSN)" - # ---------------------------------------------------- # Release directory specification # ---------------------------------------------------- @@ -39,25 +38,20 @@ RELSYSDIR = $(RELEASE_PATH)/lib/reltool-$(VSN) # Target Specs # ---------------------------------------------------- -MODULES = \ - reltool \ - reltool_app_win \ - reltool_fgraph \ - reltool_fgraph_win \ - reltool_mod_win \ - reltool_sys_win \ - reltool_server \ - reltool_target \ - reltool_utils - -HRL_FILES = - -INTERNAL_HRL_FILES = reltool.hrl reltool_fgraph.hrl +include files.mk ERL_FILES = $(MODULES:%=%.erl) TARGET_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR)) +APP_FILE = reltool.app +APP_SRC = $(APP_FILE).src +APP_TARGET = $(EBIN)/$(APP_FILE) + +APPUP_FILE = reltool.appup +APPUP_SRC = $(APPUP_FILE).src +APPUP_TARGET = $(EBIN)/$(APPUP_FILE) + # ---------------------------------------------------- # FLAGS # ---------------------------------------------------- @@ -69,14 +63,27 @@ ERL_COMPILE_FLAGS += +'{parse_transform,sys_pre_attributes}' \ # Targets # ---------------------------------------------------- -debug opt: $(TARGET_FILES) $(HRL_FILES) +debug: + @${MAKE} TYPE=debug opt + +opt: $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET) clean: - rm -f $(TARGET_FILES) + rm -f $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET) rm -f core docs: +# ---------------------------------------------------- +# Special Build Targets +# ---------------------------------------------------- + +$(APP_TARGET): $(APP_SRC) ../vsn.mk + sed -e 's;%VSN%;$(VSN);' $< > $@ + +$(APPUP_TARGET): $(APPUP_SRC) ../vsn.mk + sed -e 's;%VSN%;$(VSN);' $< > $@ + # ---------------------------------------------------- # Dependencies # ---------------------------------------------------- @@ -94,6 +101,7 @@ release_spec: opt $(INSTALL_DATA) $(INTERNAL_HRL_FILES) $(ERL_FILES) $(RELSYSDIR)/src $(INSTALL_DIR) $(RELSYSDIR)/ebin $(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR)/ebin + $(INSTALL_DATA) $(APP_TARGET) $(APPUP_TARGET) $(RELSYSDIR)/ebin release_docs_spec: diff --git a/lib/reltool/src/files.mk b/lib/reltool/src/files.mk new file mode 100644 index 0000000000..9a798cfb22 --- /dev/null +++ b/lib/reltool/src/files.mk @@ -0,0 +1,32 @@ +#-*-makefile-*- ; force emacs to enter makefile-mode +# %CopyrightBegin% +# +# Copyright Ericsson AB 2001-2010. All Rights Reserved. +# +# The contents of this file are subject to the Erlang Public License, +# Version 1.1, (the "License"); you may not use this file except in +# compliance with the License. You should have received a copy of the +# Erlang Public License along with this software. If not, it can be +# retrieved online at http://www.erlang.org/. +# +# Software distributed under the License is distributed on an "AS IS" +# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +# the License for the specific language governing rights and limitations +# under the License. +# +# %CopyrightEnd% + +MODULES = \ + reltool \ + reltool_app_win \ + reltool_fgraph \ + reltool_fgraph_win \ + reltool_mod_win \ + reltool_sys_win \ + reltool_server \ + reltool_target \ + reltool_utils + +HRL_FILES = + +INTERNAL_HRL_FILES = reltool.hrl reltool_fgraph.hrl diff --git a/lib/reltool/src/reltool.app.src b/lib/reltool/src/reltool.app.src index f83042c157..6d089100f1 100644 --- a/lib/reltool/src/reltool.app.src +++ b/lib/reltool/src/reltool.app.src @@ -1,37 +1,39 @@ %% This is an -*- erlang -*- file. %% %% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2009. All Rights Reserved. -%% +%% +%% Copyright Ericsson AB 2010. All Rights Reserved. +%% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in %% compliance with the License. You should have received a copy of the %% Erlang Public License along with this software. If not, it can be %% retrieved online at http://www.erlang.org/. -%% +%% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and limitations %% under the License. -%% -%% %CopyrightEnd% %% +%% %CopyrightEnd% {application, reltool, - [{description, "Release management tool"}, - {vsn, "%VSN%"}, - {modules, [ - reltool, - reltool_app, - reltool_fgraph, - reltool_fgraph_win, - reltool_gen, - reltool_mod, - reltool_sys, - reltool_server, - reltool_utils - ]}, - {applications, [kernel, stdlib]} - ] -}. + [{description, "Reltool the release management tool"}, + {vsn, "%VSN%"}, + {modules, + [ + reltool_app_win, + reltool, + reltool_fgraph, + reltool_fgraph.hrl + reltool_fgraph_win, + reltool_mod_win, + reltool_server, + reltool_sys_win, + reltool_target, + reltool_utils + ]}, + {registered, []}, + {applications, [stdlib, kernel]}, + {env, []} + ]}. diff --git a/lib/reltool/src/reltool.appup.src b/lib/reltool/src/reltool.appup.src new file mode 100644 index 0000000000..c02edd2afb --- /dev/null +++ b/lib/reltool/src/reltool.appup.src @@ -0,0 +1,22 @@ +%% This is an -*- erlang -*- file. +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2010. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% + +{"%VSN%", + [ ] +}. -- cgit v1.2.3 From 5217fb3d0816aa241d228f7ef14fb54f6a14a8f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5kan=20Mattsson?= Date: Mon, 15 Mar 2010 16:09:04 +0100 Subject: Add app test SUITE --- lib/reltool/src/reltool.app.src | 1 - lib/reltool/src/reltool_target.erl | 2 +- lib/reltool/src/reltool_utils.erl | 24 ++- lib/reltool/test/Makefile | 1 + lib/reltool/test/reltool_app_SUITE.erl | 291 +++++++++++++++++++++++++++++++++ lib/reltool/test/reltool_test_lib.erl | 4 +- 6 files changed, 318 insertions(+), 5 deletions(-) create mode 100644 lib/reltool/test/reltool_app_SUITE.erl (limited to 'lib') diff --git a/lib/reltool/src/reltool.app.src b/lib/reltool/src/reltool.app.src index 6d089100f1..9b1ba46e04 100644 --- a/lib/reltool/src/reltool.app.src +++ b/lib/reltool/src/reltool.app.src @@ -25,7 +25,6 @@ reltool_app_win, reltool, reltool_fgraph, - reltool_fgraph.hrl reltool_fgraph_win, reltool_mod_win, reltool_server, diff --git a/lib/reltool/src/reltool_target.erl b/lib/reltool/src/reltool_target.erl index 160cbd8e15..260c8a15f8 100644 --- a/lib/reltool/src/reltool_target.erl +++ b/lib/reltool/src/reltool_target.erl @@ -31,7 +31,7 @@ gen_target/2, install/2 ]). --compile(export_all). + -include("reltool.hrl"). -include_lib("kernel/include/file.hrl"). diff --git a/lib/reltool/src/reltool_utils.erl b/lib/reltool/src/reltool_utils.erl index 403fa574c5..1768ee0db3 100644 --- a/lib/reltool/src/reltool_utils.erl +++ b/lib/reltool/src/reltool_utils.erl @@ -19,7 +19,29 @@ -module(reltool_utils). %% Public --compile([export_all]). +-export([root_dir/0, erl_libs/0, lib_dirs/1, + split_app_name/1, prim_consult/1, default_rels/0, + + assign_image_list/1, get_latest_resize/1, + mod_conds/0, list_to_mod_cond/1, mod_cond_to_index/1, + incl_conds/0, list_to_incl_cond/1, incl_cond_to_index/1, elem_to_index/2, + app_dir_test/2, split_app_dir/1, + get_item/1, get_items/1, get_selected_items/3, + select_items/3, select_item/2, + + safe_keysearch/5, print/4, return_first_error/2, add_warning/2, + + create_dir/1, list_dir/1, read_file_info/1, + write_file_info/2, read_file/1, write_file/2, + recursive_delete/1, delete/2, recursive_copy_file/2, copy_file/2, + + throw_error/2, + + decode_regexps/3, + default_val/2, + escript_foldl/3, + + call/2, cast/2, reply/3]). -include_lib("kernel/include/file.hrl"). -include_lib("wx/include/wx.hrl"). diff --git a/lib/reltool/test/Makefile b/lib/reltool/test/Makefile index 00d2add3e5..fe23478a37 100644 --- a/lib/reltool/test/Makefile +++ b/lib/reltool/test/Makefile @@ -25,6 +25,7 @@ include $(ERL_TOP)/make/$(TARGET)/otp.mk MODULES= \ rtt \ + reltool_app_SUITE \ reltool_wx_SUITE \ reltool_server_SUITE \ reltool_test_lib diff --git a/lib/reltool/test/reltool_app_SUITE.erl b/lib/reltool/test/reltool_app_SUITE.erl new file mode 100644 index 0000000000..3944190953 --- /dev/null +++ b/lib/reltool/test/reltool_app_SUITE.erl @@ -0,0 +1,291 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2010. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +%%---------------------------------------------------------------------- +%% Purpose: Verify the application specifics of the Reltool application +%%---------------------------------------------------------------------- +-module(reltool_app_SUITE). + +-compile(export_all). + +-include("reltool_test_lib.hrl"). + + +t() -> reltool_test_lib:t(?MODULE). +t(Case) -> reltool_test_lib:t({?MODULE, Case}). + +%% Test server callbacks +init_per_suite(Config) -> + Config2 = reltool_test_lib:init_per_suite(Config), + case is_app(reltool) of + {ok, AppFile} -> + %% io:format("AppFile: ~n~p~n", [AppFile]), + [{app_file, AppFile} | Config2]; + {error, Reason} -> + fail(Reason) + end. + +end_per_suite(Config) -> + reltool_test_lib:end_per_suite(Config). + +init_per_testcase(Case, Config) -> + Config2 = + case Case of + undef_funcs -> + [{tc_timeout, timer:minutes(10)} | Config]; + _ -> + Config + end, + reltool_test_lib:init_per_testcase(Case, Config2). + +end_per_testcase(Func,Config) -> + reltool_test_lib:end_per_testcase(Func,Config). + +fin_per_testcase(Case, Config) -> + reltool_test_lib:end_per_testcase(Case, Config). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +all() -> + all(suite). + +all(suite) -> + [ + fields, + modules, + exportall, + app_depend, + undef_funcs + ]. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +is_app(App) -> + LibDir = code:lib_dir(App), + File = filename:join([LibDir, "ebin", atom_to_list(App) ++ ".app"]), + case file:consult(File) of + {ok, [{application, App, AppFile}]} -> + {ok, AppFile}; + {error, {LineNo, Mod, Code}} -> + IoList = lists:concat([File, ":", LineNo, ": ", + Mod:format_error(Code)]), + {error, list_to_atom(lists:flatten(IoList))} + end. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +fields(suite) -> + []; +fields(doc) -> + []; +fields(Config) when is_list(Config) -> + AppFile = key1search(app_file, Config), + Fields = [vsn, description, modules, registered, applications], + case check_fields(Fields, AppFile, []) of + [] -> + ok; + Missing -> + fail({missing_fields, Missing}) + end. + +check_fields([], _AppFile, Missing) -> + Missing; +check_fields([Field|Fields], AppFile, Missing) -> + check_fields(Fields, AppFile, check_field(Field, AppFile, Missing)). + +check_field(Name, AppFile, Missing) -> + io:format("checking field: ~p~n", [Name]), + case lists:keymember(Name, 1, AppFile) of + true -> + Missing; + false -> + [Name|Missing] + end. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +modules(suite) -> + []; +modules(doc) -> + []; +modules(Config) when is_list(Config) -> + AppFile = key1search(app_file, Config), + Mods = key1search(modules, AppFile), + EbinList = get_ebin_mods(reltool), + case missing_modules(Mods, EbinList, []) of + [] -> + ok; + Missing -> + throw({error, {missing_modules, Missing}}) + end, + case extra_modules(Mods, EbinList, []) of + [] -> + ok; + Extra -> + throw({error, {extra_modules, Extra}}) + end, + {ok, Mods}. + +get_ebin_mods(App) -> + LibDir = code:lib_dir(App), + EbinDir = filename:join([LibDir,"ebin"]), + {ok, Files0} = file:list_dir(EbinDir), + Files1 = [lists:reverse(File) || File <- Files0], + [list_to_atom(lists:reverse(Name)) || [$m,$a,$e,$b,$.|Name] <- Files1]. + +missing_modules([], _Ebins, Missing) -> + Missing; +missing_modules([Mod|Mods], Ebins, Missing) -> + case lists:member(Mod, Ebins) of + true -> + missing_modules(Mods, Ebins, Missing); + false -> + io:format("missing module: ~p~n", [Mod]), + missing_modules(Mods, Ebins, [Mod|Missing]) + end. + + +extra_modules(_Mods, [], Extra) -> + Extra; +extra_modules(Mods, [Mod|Ebins], Extra) -> + case lists:member(Mod, Mods) of + true -> + extra_modules(Mods, Ebins, Extra); + false -> + io:format("supefluous module: ~p~n", [Mod]), + extra_modules(Mods, Ebins, [Mod|Extra]) + end. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +exportall(suite) -> + []; +exportall(doc) -> + []; +exportall(Config) when is_list(Config) -> + AppFile = key1search(app_file, Config), + Mods = key1search(modules, AppFile), + check_export_all(Mods). + + +check_export_all([]) -> + ok; +check_export_all([Mod|Mods]) -> + case (catch apply(Mod, module_info, [compile])) of + {'EXIT', {undef, _}} -> + check_export_all(Mods); + O -> + case lists:keysearch(options, 1, O) of + false -> + check_export_all(Mods); + {value, {options, List}} -> + case lists:member(export_all, List) of + true -> + throw({error, {export_all, Mod}}); + false -> + check_export_all(Mods) + end + end + end. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +app_depend(suite) -> + []; +app_depend(doc) -> + []; +app_depend(Config) when is_list(Config) -> + AppFile = key1search(app_file, Config), + Apps = key1search(applications, AppFile), + check_apps(Apps). + +check_apps([]) -> + ok; +check_apps([App|Apps]) -> + case is_app(App) of + {ok, _} -> + check_apps(Apps); + Error -> + throw({error, {missing_app, {App, Error}}}) + end. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +undef_funcs(suite) -> + []; +undef_funcs(doc) -> + []; +undef_funcs(Config) when is_list(Config) -> + App = reltool, + AppFile = key1search(app_file, Config), + Mods = key1search(modules, AppFile), + Root = code:root_dir(), + LibDir = code:lib_dir(App), + EbinDir = filename:join([LibDir,"ebin"]), + XRefTestName = undef_funcs_make_name(App, xref_test_name), + {ok, XRef} = xref:start(XRefTestName), + ok = xref:set_default(XRef, + [{verbose,false},{warnings,false}]), + XRefName = undef_funcs_make_name(App, xref_name), + {ok, XRefName} = xref:add_release(XRef, Root, {name,XRefName}), + {ok, App} = xref:replace_application(XRef, App, EbinDir), + {ok, Undefs} = xref:analyze(XRef, undefined_function_calls), + xref:stop(XRef), + analyze_undefined_function_calls(Undefs, Mods, []). + +analyze_undefined_function_calls([], _, []) -> + ok; +analyze_undefined_function_calls([], _, AppUndefs) -> + exit({suite_failed, {undefined_function_calls, AppUndefs}}); +analyze_undefined_function_calls([{{Mod, _F, _A}, _C} = AppUndef|Undefs], + AppModules, AppUndefs) -> + %% Check that this module is our's + case lists:member(Mod,AppModules) of + true -> + {Calling,Called} = AppUndef, + {Mod1,Func1,Ar1} = Calling, + {Mod2,Func2,Ar2} = Called, + io:format("undefined function call: " + "~n ~w:~w/~w calls ~w:~w/~w~n", + [Mod1,Func1,Ar1,Mod2,Func2,Ar2]), + analyze_undefined_function_calls(Undefs, AppModules, + [AppUndef|AppUndefs]); + false -> + io:format("dropping ~p~n", [Mod]), + analyze_undefined_function_calls(Undefs, AppModules, AppUndefs) + end. + +%% This function is used simply to avoid cut-and-paste errors later... +undef_funcs_make_name(App, PostFix) -> + list_to_atom(atom_to_list(App) ++ "_" ++ atom_to_list(PostFix)). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +fail(Reason) -> + exit({suite_failed, Reason}). + +key1search(Key, L) -> + case lists:keysearch(Key, 1, L) of + false -> + fail({not_found, Key, L}); + {value, {Key, Value}} -> + Value + end. diff --git a/lib/reltool/test/reltool_test_lib.erl b/lib/reltool/test/reltool_test_lib.erl index 25978294ee..4023b37e8c 100644 --- a/lib/reltool/test/reltool_test_lib.erl +++ b/lib/reltool/test/reltool_test_lib.erl @@ -24,9 +24,11 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% init_per_suite(Config) when is_list(Config)-> + global:register_name(reltool_global_logger, group_leader()), incr_timetrap(Config, 5). end_per_suite(Config) when is_list(Config)-> + global:unregister_name(reltool_global_logger), ok. incr_timetrap(Config, Times) -> @@ -130,11 +132,9 @@ wx_end_per_suite(Config) -> init_per_testcase(_Func, Config) when is_list(Config) -> set_kill_timer(Config), - global:register_name(reltool_global_logger, group_leader()), Config. end_per_testcase(_Func, Config) when is_list(Config) -> - global:unregister_name(reltool_global_logger), reset_kill_timer(Config), Config. -- cgit v1.2.3 From 534f334247163035b477293e74b78823f2d9b7f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5kan=20Mattsson?= Date: Tue, 23 Mar 2010 16:50:50 +0100 Subject: 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. --- lib/reltool/bin/reltool.escript | 10 +- lib/reltool/doc/src/reltool_examples.xml | 4 +- lib/reltool/src/reltool_server.erl | 304 ++++++++++++++++++------------- lib/reltool/src/reltool_target.erl | 271 +++++++++++++++++---------- lib/reltool/src/reltool_utils.erl | 24 +-- lib/reltool/test/reltool_app_SUITE.erl | 8 +- 6 files changed, 378 insertions(+), 243 deletions(-) (limited to 'lib') 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)
 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).
-- 
cgit v1.2.3


From bc5807db3a4bb72395da7d32f4bee4a4678e8bfe Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?H=C3=A5kan=20Mattsson?= 
Date: Fri, 26 Mar 2010 16:57:42 +0100
Subject: Removed spurious CDATA in documentation

---
 lib/reltool/doc/src/reltool.xml | 70 ++++++++++++++++++++---------------------
 1 file changed, 35 insertions(+), 35 deletions(-)

(limited to 'lib')

diff --git a/lib/reltool/doc/src/reltool.xml b/lib/reltool/doc/src/reltool.xml
index 24683b9302..a46323b1f2 100644
--- a/lib/reltool/doc/src/reltool.xml
+++ b/lib/reltool/doc/src/reltool.xml
@@ -67,14 +67,14 @@
 
     
 
-      
+      config
       
         

This is the main option and it controls the configuration of reltool. It can either be a sys tuple or a name of a file containing a sys tuple.

- + trap_exit>

This option controls the error handling behavior of reltool. By default the window processes traps @@ -82,7 +82,7 @@ trap_exit to false.

- + wx_debug

This option controls the debug level of wx. As its name indicates it is only useful for debugging. See @@ -97,27 +97,27 @@ - + erts

Erts specific configuration. See application level options below.

- + escript

Escript specific configuration. An escript has a mandatory file name and escript level options that are described below.

- + app

Application specific configuration. An application has a mandatory name and application level options that are described below.

- + mod_cond

This parameter controls the module inclusion policy. It defaults to all which means that if an application is @@ -134,7 +134,7 @@ system level is used as default for all applications.

- + incl_cond

This parameter controls the application and escript inclusion policy. It defaults to derived which means @@ -148,14 +148,14 @@ incl_cond setting will be excluded.

- + boot_rel

A target system may have several releases but the one given as boot_rel will be used as default when the system is booting up.

- + rel

Release specific configuration. Each release maps to a rel, script and boot file. See the @@ -165,7 +165,7 @@ applications.

- + relocatable

This parameter controls whether the erl executable in the target system automatically should determine where it @@ -177,7 +177,7 @@ re-installation. The default is true.

- + profile

The creation of the specification for a target system is performed in two steps. In the first step a complete @@ -196,7 +196,7 @@ incl_app_filters and excl_app_filters.

- + app_file

This parameter controls the default handling of the app files when a target system is generated. It @@ -213,7 +213,7 @@ and strip.

- + debug_info

The debug_info parameter controls whether the debug information in the beam file should be kept (keep) or @@ -221,7 +221,7 @@ system.

- + incl_sys_filters

This parameter normally contains a list of regular expressions that controls which files in the system that @@ -235,7 +235,7 @@ [".*"].

- + excl_sys_filters

This parameter normally contains a list of regular expressions that controls which files in the system that not @@ -245,7 +245,7 @@ excl_sys_filters. This parameter defaults to [].

- + incl_app_filters

This parameter normally contains a list of regular expressions that controls which application specific files @@ -256,7 +256,7 @@ parameter defaults to [".*"].

- + excl_app_filters

This parameter normally contains a list of regular expressions that controls which application specific files @@ -267,7 +267,7 @@ [].

- + incl_archive_filters

This parameter normally contains a list of regular expressions that controls which top level directories in an @@ -280,7 +280,7 @@ parameter defaults to [".*"].

- + excl_archive_filters

This parameter normally contains a list of regular expressions that controls which top level directories in an @@ -291,7 +291,7 @@ parameter defaults to ["^include$","^priv$"].

- + archive_opts

This parameter contains a list of options that are given to zip:create/3 when application specific files are @@ -307,7 +307,7 @@ supported:

- + incl_cond

The value of this parameter overrides the parameter with the same name on system level.

@@ -318,62 +318,62 @@ supported:

- + vsn

The version of the application. In an installed system there may exist several versions of an application. The vsn parameter controls which version of the application that will be choosen. If it is omitted, the latest version will be choosen.

- + mod

Module specific configuration. A module has a mandatory name and module level options that are described below.

- + mod_cond

The value of this parameter overrides the parameter with the same name on system level.

- + incl_cond

The value of this parameter overrides the parameter with the same name on system level.

- + app_file

The value of this parameter overrides the parameter with the same name on system level.

- + debug_info

The value of this parameter overrides the parameter with the same name on system level.

- + incl_app_filters

The value of this parameter overrides the parameter with the same name on system level.

- + excl_app_filters

The value of this parameter overrides the parameter with the same name on system level.

- + incl_archive_filters

The value of this parameter overrides the parameter with the same name on system level.

- + excl_archive_filters

The value of this parameter overrides the parameter with the same name on system level.

- + archive_opts

The value of this parameter overrides the parameter with the same name on system level.

@@ -384,7 +384,7 @@ supported:

- + incl_cond

This parameter controls whether the module is included or not. By default the mod_incl parameter on application and system level @@ -395,7 +395,7 @@ derived implies that the is included if any included uses the module.

- + debug_info

The value of this parameter overrides the parameter with the same name on application level.

-- cgit v1.2.3 From 21db0d0e7e7112d7c257ed19fc8e3c0a90d4698b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5kan=20Mattsson?= Date: Thu, 1 Apr 2010 10:37:29 +0200 Subject: Introduced a new embedded_app_type option It is for embedded systems where all included applications must be loaded from the boot script. If embedded_app_type is set to something else than undefined all included applications will be included in both the "rel" as well as in the "script". --- lib/reltool/src/reltool.hrl | 11 ++++-- lib/reltool/src/reltool_mod_win.erl | 4 +- lib/reltool/src/reltool_server.erl | 44 +++++++++++++--------- lib/reltool/src/reltool_sys_win.erl | 2 +- lib/reltool/src/reltool_target.erl | 73 ++++++++++++++++++++++--------------- 5 files changed, 81 insertions(+), 53 deletions(-) (limited to 'lib') diff --git a/lib/reltool/src/reltool.hrl b/lib/reltool/src/reltool.hrl index b3f06e8753..7c9f519878 100644 --- a/lib/reltool/src/reltool.hrl +++ b/lib/reltool/src/reltool.hrl @@ -17,7 +17,7 @@ %% %CopyrightEnd% -define(APPLICATION, reltool). --define(MISSING_APP, '*MISSING*'). +-define(MISSING_APP_NAME, '*MISSING*'). -define(MISSING_APP_TEXT, "*MISSING*"). -type file() :: string(). @@ -187,7 +187,7 @@ %% Static target cond debug_info :: debug_info() | undefined, app_file :: app_file() | undefined, - app_type :: app_type(), + app_type :: app_type() | undefined, incl_app_filters :: incl_app_filters(), excl_app_filters :: excl_app_filters(), incl_archive_filters :: incl_archive_filters(), @@ -242,7 +242,8 @@ excl_archive_filters :: excl_archive_filters(), archive_opts :: [archive_opt()], relocatable :: boolean(), - app_type :: app_type(), + rel_app_type :: app_type(), + embedded_app_type :: app_type() | undefined, app_file :: app_file(), debug_info :: debug_info() }). @@ -267,7 +268,8 @@ -define(DEFAULT_EMU_NAME, "beam"). -define(DEFAULT_PROFILE, development). -define(DEFAULT_RELOCATABLE, true). --define(DEFAULT_APP_TYPE, permanent). +-define(DEFAULT_REL_APP_TYPE, permanent). +-define(DEFAULT_EMBEDDED_APP_TYPE, undefined). -define(DEFAULT_APP_FILE, keep). -define(DEFAULT_DEBUG_INFO, keep). @@ -292,6 +294,7 @@ "^priv", "^include"]). -define(EMBEDDED_EXCL_APP_FILTERS, []). +-define(EMBEDDED_APP_TYPE, load). -define(STANDALONE_INCL_SYS_FILTERS, ["^bin/(erl|epmd)(|\\.exe|\\.ini)\$", "^bin/start(|_clean).boot\$", diff --git a/lib/reltool/src/reltool_mod_win.erl b/lib/reltool/src/reltool_mod_win.erl index c2544cc2d8..f68c61fd6f 100644 --- a/lib/reltool/src/reltool_mod_win.erl +++ b/lib/reltool/src/reltool_mod_win.erl @@ -514,7 +514,7 @@ select_image(Xref, ModName) -> {ok, M} = reltool_server:get_mod(Xref, ModName), Image = case M#mod.is_included of - _ when M#mod.app_name =:= ?MISSING_APP -> ?ERR_IMAGE; + _ when M#mod.app_name =:= ?MISSING_APP_NAME -> ?ERR_IMAGE; true -> ?TICK_IMAGE; false -> ?WARN_IMAGE; undefined -> ?ERR_IMAGE @@ -674,7 +674,7 @@ do_goto_function(#state{active_page = P} = S, [FunName]) -> find_regexp_forward(S, "^" ++ FunName ++ "("); do_goto_function(S, [ModStr, FunStr]) -> case reltool_server:get_mod(S#state.xref_pid, list_to_atom(ModStr)) of - {ok, Mod} when Mod#mod.app_name =/= ?MISSING_APP -> + {ok, Mod} when Mod#mod.app_name =/= ?MISSING_APP_NAME -> S2 = create_code_page(S#state{mod = Mod}, ModStr), find_regexp_forward(S2, "^" ++ FunStr ++ "("); {ok, _} -> diff --git a/lib/reltool/src/reltool_server.erl b/lib/reltool/src/reltool_server.erl index a1e9c0193b..01a7d93823 100644 --- a/lib/reltool/src/reltool_server.erl +++ b/lib/reltool/src/reltool_server.erl @@ -175,7 +175,8 @@ parse_options(Opts) -> ?DEFAULT_EXCL_APP_FILTERS, []), relocatable = ?DEFAULT_RELOCATABLE, - app_type = ?DEFAULT_APP_TYPE, + rel_app_type = ?DEFAULT_REL_APP_TYPE, + embedded_app_type = ?DEFAULT_EMBEDDED_APP_TYPE, app_file = ?DEFAULT_APP_FILE, incl_archive_filters = dec_re(incl_archive_filters, ?DEFAULT_INCL_ARCHIVE_FILTERS, @@ -301,7 +302,7 @@ loop(#state{common = C, sys = Sys} = S) -> [M] -> {ok, M}; [] -> - {ok, missing_mod(ModName, ?MISSING_APP)} + {ok, missing_mod(ModName, ?MISSING_APP_NAME)} end, reltool_utils:reply(ReplyTo, Ref, Reply), ?MODULE:loop(S); @@ -435,11 +436,11 @@ do_set_app(#state{sys = Sys} = S, App, Status) -> analyse(#state{common = C, sys = #sys{apps = Apps0, rels = Rels} = Sys} = S, Status) -> - Apps = lists:keydelete(?MISSING_APP, #app.name, Apps0), + Apps = lists:keydelete(?MISSING_APP_NAME, #app.name, Apps0), ets:delete_all_objects(C#common.app_tab), ets:delete_all_objects(C#common.mod_tab), ets:delete_all_objects(C#common.mod_used_by_tab), - MissingApp = default_app(?MISSING_APP, "missing"), + MissingApp = default_app(?MISSING_APP_NAME, "missing"), ets:insert(C#common.app_tab, MissingApp), {RevRelApps, Status2} = apps_in_rels(Rels, Apps, Status), @@ -466,7 +467,7 @@ analyse(#state{common = C, app_propagate_is_used_by(C, Apps3), Apps4 = read_apps(C, Sys, Apps3, []), %% io:format("Missing app: ~p\n", - %% [lists:keysearch(?MISSING_APP, #app.name, Apps4)]), + %% [lists:keysearch(?MISSING_APP_NAME, #app.name, Apps4)]), Sys2 = Sys#sys{apps = Apps4}, case verify_config(RelApps2, Sys2, Status3) of @@ -704,7 +705,7 @@ mod_mark_is_included(C, Sys, UsedByName, [ModName | ModNames], Acc) -> Acc2) end; [] -> - M = missing_mod(ModName, ?MISSING_APP), + M = missing_mod(ModName, ?MISSING_APP_NAME), M2 = M#mod{is_included = true}, ets:insert(C#common.mod_tab, M2), ets:insert(C#common.mod_used_by_tab, {UsedByName, ModName}), @@ -715,7 +716,7 @@ mod_mark_is_included(_C, _Sys, _UsedByName, [], Acc) -> Acc. app_propagate_is_used_by(C, [#app{mods = Mods, name = Name} | Apps]) -> - case Name =:= ?MISSING_APP of + case Name =:= ?MISSING_APP_NAME of true -> ok; false -> ok end, @@ -1286,7 +1287,8 @@ decode(#sys{} = Sys, [{Key, Val} | KeyVals], Status) -> excl_app_filters = dec_re(excl_app_filters, ?EMBEDDED_EXCL_APP_FILTERS, - Sys#sys.excl_app_filters)}, + Sys#sys.excl_app_filters), + embedded_app_type = ?EMBEDDED_APP_TYPE}, Status}; profile when Val =:= standalone -> {Sys#sys{profile = Val, @@ -1347,12 +1349,19 @@ decode(#sys{} = Sys, [{Key, Val} | KeyVals], Status) -> {Sys#sys{archive_opts = Val}, Status}; relocatable when Val =:= true; Val =:= false -> {Sys#sys{relocatable = Val}, Status}; - app_type when Val =:= permanent; - Val =:= transient; - Val =:= temporary; - Val =:= load; - Val =:= none -> - {Sys#sys{app_type = Val}, Status}; + rel_app_type when Val =:= permanent; + Val =:= transient; + Val =:= temporary; + Val =:= load; + Val =:= none -> + {Sys#sys{rel_app_type = Val}, Status}; + embedded_app_type when Val =:= permanent; + Val =:= transient; + Val =:= temporary; + Val =:= load; + Val =:= none; + Val =:= undefined -> + {Sys#sys{embedded_app_type = Val}, Status}; app_file when Val =:= keep; Val =:= strip, Val =:= all -> {Sys#sys{app_file = Val}, Status}; debug_info when Val =:= keep; Val =:= strip -> @@ -1389,7 +1398,8 @@ decode(#app{} = App, [{Key, Val} | KeyVals], Status) -> Val =:= transient; Val =:= temporary; Val =:= load; - Val =:= none -> + Val =:= none; + Val =:= undefined -> {App#app{app_type = Val}, Status}; incl_app_filters -> {App#app{incl_app_filters = @@ -1921,7 +1931,7 @@ refresh_apps([Old | OldApps], [New | NewApps], Acc, Force, Status) when New#app.name > Old#app.name -> %% No new version. Remove the old. Status2 = - case Old#app.name =:= ?MISSING_APP of + case Old#app.name =:= ?MISSING_APP_NAME of true -> Status; false -> @@ -1939,7 +1949,7 @@ refresh_apps([], [New | NewApps], Acc, Force, Status) -> refresh_apps([Old | OldApps], [], Acc, Force, Status) -> %% No new version. Remove the old. Status2 = - case Old#app.name =:= ?MISSING_APP of + case Old#app.name =:= ?MISSING_APP_NAME of true -> Status; false -> diff --git a/lib/reltool/src/reltool_sys_win.erl b/lib/reltool/src/reltool_sys_win.erl index 2e226d9147..dbb8e32aa2 100644 --- a/lib/reltool/src/reltool_sys_win.erl +++ b/lib/reltool/src/reltool_sys_win.erl @@ -1227,7 +1227,7 @@ create_fgraph_window(S, Title, Nodes, Links) -> Panel = wxPanel:new(Frame, []), Options = [{size, {lists:max([100, ?WIN_WIDTH - 100]), ?WIN_HEIGHT}}], {Server, Fgraph} = reltool_fgraph_win:new(Panel, Options), - Choose = fun(?MISSING_APP) -> alternate; + Choose = fun(?MISSING_APP_NAME) -> alternate; (_) -> default end, [reltool_fgraph_win:add_node(Server, N, Choose(N)) || N <- Nodes], diff --git a/lib/reltool/src/reltool_target.erl b/lib/reltool/src/reltool_target.erl index aaf9d99d2f..bd06cda773 100644 --- a/lib/reltool/src/reltool_target.erl +++ b/lib/reltool/src/reltool_target.erl @@ -84,7 +84,8 @@ do_gen_config(#sys{root_dir = RootDir, excl_archive_filters = ExclArchiveDirs, archive_opts = ArchiveOpts, relocatable = Relocatable, - app_type = AppType, + rel_app_type = RelAppType, + embedded_app_type = InclAppType, app_file = AppFile, debug_info = DebugInfo}, InclDefs) -> @@ -98,7 +99,7 @@ do_gen_config(#sys{root_dir = RootDir, AppsItems = [do_gen_config(A, InclDefs) || A <- Apps, - A#app.name =/= ?MISSING_APP, + A#app.name =/= ?MISSING_APP_NAME, A#app.name =/= erts, not A#app.is_escript], EscriptItems = [{escript, @@ -138,7 +139,8 @@ do_gen_config(#sys{root_dir = RootDir, emit(incl_archive_filters, X(InclArchiveDirs), ?DEFAULT_INCL_ARCHIVE_FILTERS, InclDefs) ++ emit(excl_archive_filters, X(ExclArchiveDirs), ?DEFAULT_EXCL_ARCHIVE_FILTERS, InclDefs) ++ emit(archive_opts, ArchiveOpts, ?DEFAULT_ARCHIVE_OPTS, InclDefs) ++ - emit(app_type, AppType, ?DEFAULT_APP_TYPE, InclDefs) ++ + emit(rel_app_type, RelAppType, ?DEFAULT_REL_APP_TYPE, InclDefs) ++ + emit(embedded_app_type, InclAppType, ?DEFAULT_EMBEDDED_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, @@ -294,41 +296,54 @@ 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}}) -> + info = #app_info{incl_apps = InclApps}}) + when Type =/= undefined -> case {Type, InclApps} of - {undefined, []} -> {Name, Vsn}; - {undefined, _} -> {Name, Vsn, InclApps}; + {permanent, []} -> {Name, Vsn}; + {permanent, _} -> {Name, Vsn, InclApps}; {_, []} -> {Name, Vsn, Type}; {_, _} -> {Name, Vsn, Type, InclApps} end. -merge_apps(#rel{name = RelName, rel_apps = RelApps}, - #sys{apps = Apps, app_type = DefType}) -> +merge_apps(#rel{name = RelName, + rel_apps = RelApps}, + #sys{apps = Apps, + rel_app_type = RelAppType, + embedded_app_type = EmbAppType}) -> 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) -> + MergedApps2 = do_merge_apps(RelName, RelApps, Apps, RelAppType, MergedApps), + Embedded = + [A#app.name || A <- Apps, + EmbAppType =/= undefined, + A#app.is_included, + A#app.name =/= erts, + A#app.name =/= ?MISSING_APP_NAME, + not lists:keymember(A#app.name, #app.name, MergedApps2)], + io:format("Embedded: ~p\n", [Embedded]), + MergedApps3 = do_merge_apps(RelName, Embedded, Apps, EmbAppType, MergedApps2), + sort_apps(MergedApps3). + +do_merge_apps(RelName, [#rel_app{name = Name} = RA | RelApps], Apps, RelAppType, Acc) -> case is_already_merged(Name, RelApps, Acc) of true -> - do_merge_apps(RelName, RelApps, Apps, DefType, Acc); + do_merge_apps(RelName, RelApps, Apps, RelAppType, Acc); false -> {value, App} = lists:keysearch(Name, #app.name, Apps), - MergedApp = merge_app(RelName, RA, DefType, App), + MergedApp = merge_app(RelName, RA, RelAppType, App), MoreNames = (MergedApp#app.info)#app_info.applications, Acc2 = [MergedApp | Acc], - do_merge_apps(RelName, MoreNames ++ RelApps, Apps, DefType, Acc2) + do_merge_apps(RelName, MoreNames ++ RelApps, Apps, RelAppType, Acc2) end; -do_merge_apps(RelName, [Name | RelApps], Apps, DefType, Acc) -> +do_merge_apps(RelName, [Name | RelApps], Apps, RelAppType, Acc) -> case is_already_merged(Name, RelApps, Acc) of true -> - do_merge_apps(RelName, RelApps, Apps, DefType, Acc); + do_merge_apps(RelName, RelApps, Apps, RelAppType, Acc); false -> RelApp = init_rel_app(Name, Apps), - do_merge_apps(RelName, [RelApp | RelApps], Apps, DefType, Acc) + do_merge_apps(RelName, [RelApp | RelApps], Apps, RelAppType, Acc) end; -do_merge_apps(_RelName, [], _Apps, _DefType, Acc) -> +do_merge_apps(_RelName, [], _Apps, _RelAppType, Acc) -> lists:reverse(Acc). init_rel_app(Name, Apps) -> @@ -340,20 +355,20 @@ init_rel_app(Name, Apps) -> merge_app(RelName, #rel_app{name = Name, - app_type = RelAppType, + app_type = Type, incl_apps = InclApps}, - DefType, + RelAppType, App) -> - Type = - case {RelAppType, App#app.app_type} of - {undefined, undefined} -> DefType; - {undefined, AppType} -> AppType; - {_, _} -> RelAppType + Type2 = + case {Type, App#app.app_type} of + {undefined, undefined} -> RelAppType; + {undefined, AppAppType} -> AppAppType; + {_, _} -> Type 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}}; + App#app{app_type = Type2, info = Info#app_info{incl_apps = InclApps}}; BadIncl -> reltool_utils:throw_error("~p: These applications are " "used by release ~s but are " @@ -880,7 +895,7 @@ spec_escripts(#sys{apps = Apps}, ErtsBin, BinFiles) -> name = Name, active_dir = File}) -> if - Name =:= ?MISSING_APP -> + Name =:= ?MISSING_APP_NAME -> false; not IsEscript -> false; @@ -943,7 +958,7 @@ spec_lib_files(#sys{apps = Apps} = Sys) -> Filter = fun(#app{is_escript = IsEscript, is_included = IsIncl, is_pre_included = IsPre, name = Name}) -> if - Name =:= ?MISSING_APP -> + Name =:= ?MISSING_APP_NAME -> false; IsEscript -> false; -- cgit v1.2.3 From 2f304e221f790af9b0bf15d9ea8f8f447159351e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5kan=20Mattsson?= Date: Thu, 1 Apr 2010 13:09:35 +0200 Subject: Ensure that {error, Reason} is returned even when server dies --- lib/reltool/src/reltool.erl | 19 ++++--- lib/reltool/src/reltool.hrl | 16 +++--- lib/reltool/src/reltool_server.erl | 112 +++++++++++++------------------------ lib/reltool/src/reltool_target.erl | 12 ++-- lib/reltool/src/reltool_utils.erl | 36 +++++++++++- 5 files changed, 98 insertions(+), 97 deletions(-) (limited to 'lib') diff --git a/lib/reltool/src/reltool.erl b/lib/reltool/src/reltool.erl index 351a3d59cf..9dd0a24f46 100644 --- a/lib/reltool/src/reltool.erl +++ b/lib/reltool/src/reltool.erl @@ -99,16 +99,19 @@ stop(Pid) when is_pid(Pid) -> -spec eval_server(server(), boolean(), fun((server_pid()) -> term())) -> {ok, server_pid()} | {error, reason()}. eval_server(Pid, DisplayWarnings, Fun) - when is_pid(Pid), is_boolean(DisplayWarnings) -> + when is_pid(Pid) -> Fun(Pid); eval_server(Options, DisplayWarnings, Fun) - when is_list(Options), is_boolean(DisplayWarnings), is_function(Fun, 1) -> - case start_server(Options) of - {ok, Pid} -> - apply_fun(Pid, DisplayWarnings, Fun); - {error, Reason} -> - {error, Reason} - end. + when is_list(Options) -> + TrapExit = process_flag(trap_exit, true), + Res = case start_server(Options) of + {ok, Pid} -> + apply_fun(Pid, DisplayWarnings, Fun); + {error, Reason} -> + {error, Reason} + end, + process_flag(trap_exit, TrapExit), + Res. apply_fun(Pid, false, Fun) -> Res = Fun(Pid), diff --git a/lib/reltool/src/reltool.hrl b/lib/reltool/src/reltool.hrl index 7c9f519878..1a34ced89d 100644 --- a/lib/reltool/src/reltool.hrl +++ b/lib/reltool/src/reltool.hrl @@ -283,23 +283,23 @@ -define(DEFAULT_EXCL_APP_FILTERS, []). -define(EMBEDDED_INCL_SYS_FILTERS, ["^bin", - "^erts", - "^lib", - "^releases"]). + "^erts", + "^lib", + "^releases"]). -define(EMBEDDED_EXCL_SYS_FILTERS, ["^bin/(erlc|dialyzer|typer)(|\\.exe)\$", "^erts.*/bin/(erlc|dialyzer|typer)(|\\.exe)\$", "^erts.*/bin/.*(debug|pdb)"]). -define(EMBEDDED_INCL_APP_FILTERS, ["^ebin", - "^priv", - "^include"]). + "^include", + "^priv"]). -define(EMBEDDED_EXCL_APP_FILTERS, []). -define(EMBEDDED_APP_TYPE, load). -define(STANDALONE_INCL_SYS_FILTERS, ["^bin/(erl|epmd)(|\\.exe|\\.ini)\$", - "^bin/start(|_clean).boot\$", - "^erts.*/bin", - "^lib\$"]). + "^bin/start(|_clean).boot\$", + "^erts.*/bin", + "^lib\$"]). -define(STANDALONE_EXCL_SYS_FILTERS, ["^erts.*/bin/(erlc|dialyzer|typer)(|\\.exe)\$", "^erts.*/bin/(start|escript|to_erl|run_erl)(|\\.exe)\$", diff --git a/lib/reltool/src/reltool_server.erl b/lib/reltool/src/reltool_server.erl index 01a7d93823..039ad56aa8 100644 --- a/lib/reltool/src/reltool_server.erl +++ b/lib/reltool/src/reltool_server.erl @@ -132,20 +132,20 @@ init(Options) -> end. do_init(Options) -> - case parse_options(Options) of - {#state{parent_pid = ParentPid, common = C, sys = Sys} = S, Status} -> - %% process_flag(trap_exit, (S#state.common)#common.trap_exit), - proc_lib:init_ack(ParentPid, - {ok, self(), C, Sys#sys{apps = undefined}}), - {S2, Status2} = refresh(S, true, Status), - {S3, Status3} = - analyse(S2#state{old_sys = S2#state.sys}, Status2), - case Status3 of - {ok, _Warnings} -> % BUGBUG: handle warnings - loop(S3#state{status = Status3, old_status = {ok, []}}); - {error, Reason} -> - exit(Reason) - end + {S, Status} = parse_options(Options), + #state{parent_pid = ParentPid, common = C, sys = Sys} = S, + + %% process_flag(trap_exit, (S#state.common)#common.trap_exit), + proc_lib:init_ack(ParentPid, + {ok, self(), C, Sys#sys{apps = undefined}}), + {S2, Status2} = refresh(S, true, Status), + {S3, Status3} = + analyse(S2#state{old_sys = S2#state.sys}, Status2), + case Status3 of + {ok, _Warnings} -> % BUGBUG: handle warnings + loop(S3#state{status = Status3, old_status = {ok, []}}); + {error, Reason} -> + exit(Reason) end. parse_options(Opts) -> @@ -195,8 +195,8 @@ parse_options(Opts) -> S = #state{options = Opts}, parse_options(Opts, S, C2, Sys, {ok, []}). -dec_re(Key, Regexps, _Old) -> - reltool_utils:decode_regexps(Key, Regexps, _Old). +dec_re(Key, Regexps, Old) -> + reltool_utils:decode_regexps(Key, Regexps, Old). parse_options([{Key, Val} | KeyVals], S, C, Sys, Status) -> case Key of @@ -1250,64 +1250,28 @@ decode(#sys{} = Sys, [{Key, Val} | KeyVals], Status) -> {Sys#sys{boot_rel = Val}, Status}; emu_name when is_list(Val) -> {Sys#sys{emu_name = Val}, 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)}, - 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), - embedded_app_type = ?EMBEDDED_APP_TYPE}, - 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)}, + profile when Val =:= development; + Val =:= embedded; + Val =:= standalone -> + InclSys = reltool_utils:choose_default(incl_sys_filters, Val, false), + ExclSys = reltool_utils:choose_default(excl_sys_filters, Val, false), + InclApp = reltool_utils:choose_default(incl_app_filters, Val, false), + ExclApp = reltool_utils:choose_default(excl_app_filters, Val, false), + AppType = reltool_utils:choose_default(embedded_app_type, Val, false), + {Sys#sys{profile = Val, + incl_sys_filters = dec_re(incl_sys_filters, + InclSys, + Sys#sys.incl_sys_filters), + excl_sys_filters = dec_re(excl_sys_filters, + ExclSys, + Sys#sys.excl_sys_filters), + incl_app_filters = dec_re(incl_app_filters, + InclApp, + Sys#sys.incl_app_filters), + excl_app_filters = dec_re(excl_app_filters, + ExclApp, + Sys#sys.excl_app_filters), + embedded_app_type = AppType}, Status}; incl_sys_filters -> {Sys#sys{incl_sys_filters = diff --git a/lib/reltool/src/reltool_target.erl b/lib/reltool/src/reltool_target.erl index bd06cda773..6149279112 100644 --- a/lib/reltool/src/reltool_target.erl +++ b/lib/reltool/src/reltool_target.erl @@ -132,15 +132,15 @@ do_gen_config(#sys{root_dir = RootDir, emit(emu_name, EmuName, ?DEFAULT_EMU_NAME, InclDefs) ++ emit(relocatable, Relocatable, ?DEFAULT_RELOCATABLE, InclDefs) ++ emit(profile, Profile, ?DEFAULT_PROFILE, InclDefs) ++ - emit(incl_sys_filters, X(InclSysFiles), ?DEFAULT_INCL_SYS_FILTERS, InclDefs) ++ - emit(excl_sys_filters, X(ExclSysFiles), ?DEFAULT_EXCL_SYS_FILTERS, InclDefs) ++ - emit(incl_app_filters, X(InclAppFiles), ?DEFAULT_INCL_APP_FILTERS, InclDefs) ++ - emit(excl_app_filters, X(ExclAppFiles), ?DEFAULT_EXCL_APP_FILTERS, InclDefs) ++ + emit(incl_sys_filters, X(InclSysFiles), reltool_utils:choose_default(incl_sys_filters, Profile, InclDefs), InclDefs) ++ + emit(excl_sys_filters, X(ExclSysFiles), reltool_utils:choose_default(excl_sys_filters, Profile, InclDefs), InclDefs) ++ + emit(incl_app_filters, X(InclAppFiles), reltool_utils:choose_default(incl_app_filters, Profile, InclDefs), InclDefs) ++ + emit(excl_app_filters, X(ExclAppFiles), reltool_utils:choose_default(excl_app_filters, Profile, InclDefs), InclDefs) ++ emit(incl_archive_filters, X(InclArchiveDirs), ?DEFAULT_INCL_ARCHIVE_FILTERS, InclDefs) ++ emit(excl_archive_filters, X(ExclArchiveDirs), ?DEFAULT_EXCL_ARCHIVE_FILTERS, InclDefs) ++ emit(archive_opts, ArchiveOpts, ?DEFAULT_ARCHIVE_OPTS, InclDefs) ++ emit(rel_app_type, RelAppType, ?DEFAULT_REL_APP_TYPE, InclDefs) ++ - emit(embedded_app_type, InclAppType, ?DEFAULT_EMBEDDED_APP_TYPE, InclDefs) ++ + emit(embedded_app_type, InclAppType, reltool_utils:choose_default(embedded_app_type, Profile, InclDefs), InclDefs) ++ emit(app_file, AppFile, ?DEFAULT_APP_FILE, InclDefs) ++ emit(debug_info, DebugInfo, ?DEFAULT_DEBUG_INFO, InclDefs)}; do_gen_config(#app{name = Name, @@ -221,6 +221,8 @@ do_gen_config([H | T], InclDefs) -> lists:flatten([do_gen_config(H, InclDefs), do_gen_config(T, InclDefs)]). emit(Tag, Val, Default, InclDefs) -> + %% io:format("~p(~p):\n\t~p\n\t~p\n", + %% [Tag, Val =/= Default, Val, Default]), if Val == undefined -> []; InclDefs -> [{Tag, Val}]; diff --git a/lib/reltool/src/reltool_utils.erl b/lib/reltool/src/reltool_utils.erl index b33820c568..39d057d994 100644 --- a/lib/reltool/src/reltool_utils.erl +++ b/lib/reltool/src/reltool_utils.erl @@ -20,7 +20,8 @@ %% Public -export([root_dir/0, erl_libs/0, lib_dirs/1, - split_app_name/1, prim_consult/1, default_rels/0, + split_app_name/1, prim_consult/1, + default_rels/0, choose_default/3, assign_image_list/1, get_latest_resize/1, mod_conds/0, list_to_mod_cond/1, mod_cond_to_index/1, @@ -139,6 +140,32 @@ default_rels() -> %%rel_apps = [Kernel, Sasl, Stdlib]} ]. +choose_default(Tag, Profile, InclDefs) + when Profile =:= ?DEFAULT_PROFILE; InclDefs -> + case Tag of + incl_sys_filters -> ?DEFAULT_INCL_SYS_FILTERS; + excl_sys_filters -> ?DEFAULT_EXCL_SYS_FILTERS; + incl_app_filters -> ?DEFAULT_INCL_APP_FILTERS; + excl_app_filters -> ?DEFAULT_EXCL_APP_FILTERS; + embedded_app_type -> ?DEFAULT_EMBEDDED_APP_TYPE + end; +choose_default(Tag, standalone, _InclDefs) -> + case Tag of + incl_sys_filters -> ?STANDALONE_INCL_SYS_FILTERS; + excl_sys_filters -> ?STANDALONE_EXCL_SYS_FILTERS; + incl_app_filters -> ?STANDALONE_INCL_APP_FILTERS; + excl_app_filters -> ?STANDALONE_EXCL_APP_FILTERS; + embedded_app_type -> ?DEFAULT_EMBEDDED_APP_TYPE + end; +choose_default(Tag, embedded, _InclDefs) -> + case Tag of + incl_sys_filters -> ?EMBEDDED_INCL_SYS_FILTERS; + excl_sys_filters -> ?EMBEDDED_EXCL_SYS_FILTERS; + incl_app_filters -> ?EMBEDDED_INCL_APP_FILTERS; + excl_app_filters -> ?EMBEDDED_EXCL_APP_FILTERS; + embedded_app_type -> ?EMBEDDED_APP_TYPE + end. + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% assign_image_list(ListCtrl) -> @@ -584,7 +611,12 @@ escript_foldl(Fun, Acc, File) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% call(Name, Msg) when is_atom(Name) -> - call(whereis(Name), Msg); + case whereis(Name) of + undefined -> + {error, {noproc, Name}}; + Pid -> + call(Pid, Msg) + end; call(Pid, Msg) when is_pid(Pid) -> Ref = erlang:monitor(process, Pid), Pid ! {call, self(), Ref, Msg}, -- cgit v1.2.3 From e57e7f332fcf9ea26a7f7536b18a24181b680463 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5kan=20Mattsson?= Date: Thu, 22 Apr 2010 09:30:12 +0200 Subject: Make some cleanups --- lib/reltool/doc/src/reltool.xml | 88 +++++++++++++++---------------- lib/reltool/src/reltool_target.erl | 25 ++------- lib/reltool/test/reltool_server_SUITE.erl | 8 +-- lib/reltool/test/reltool_test_lib.hrl | 1 + 4 files changed, 55 insertions(+), 67 deletions(-) (limited to 'lib') diff --git a/lib/reltool/doc/src/reltool.xml b/lib/reltool/doc/src/reltool.xml index a46323b1f2..0c2b7d2a2b 100644 --- a/lib/reltool/doc/src/reltool.xml +++ b/lib/reltool/doc/src/reltool.xml @@ -136,16 +136,16 @@ incl_cond -

This parameter controls the application and escript - inclusion policy. It defaults to derived which means - that the applications that not have any explicit - incl_cond setting, will only be included if any other - (explicitly or implicitly included) application uses it. The - value include implies that all applications and - escripts that that not have any explicit incl_cond - setting will be included. exclude implies that all - applications and escripts) that that not have any explicit - incl_cond setting will be excluded.

+

This parameter controls the application and escript + inclusion policy. It defaults to derived which means + that the applications that not have any explicit + incl_cond setting, will only be included if any other + (explicitly or implicitly included) application uses it. The + value include implies that all applications and + escripts that that not have any explicit incl_cond + setting will be included. exclude implies that all + applications and escripts) that that not have any explicit + incl_cond setting will be excluded.

boot_rel @@ -167,33 +167,33 @@ relocatable -

This parameter controls whether the erl executable - in the target system automatically should determine where it - is installed or if it should use a hardcoded path to the - installation. In the latter case the target system must be - installed with reltool:install/2 before it can be - used. If the system is relocatable, the file tree containing - the target system can be moved to another location without - re-installation. The default is true.

+

This parameter controls whether the erl executable + in the target system automatically should determine where it + is installed or if it should use a hardcoded path to the + installation. In the latter case the target system must be + installed with reltool:install/2 before it can be + used. If the system is relocatable, the file tree containing + the target system can be moved to another location without + re-installation. The default is true.

profile -

The creation of the specification for a target system is - performed in two steps. In the first step a complete - specification is generated. It will likely contain much more - files than you are interested in your customized target - system. In the second step the specification will be filtered - according to your filters. There you have the ability to - specify filters per application as well as system wide - filters. You can also select a profile for your - system. Depending on the profile, different default - filters will be used. There are three different profiles to - choose from: development, embedded and - standalone. development is default. The - parameters that are affected by the profile are: - incl_sys_filters, excl_sys_filters, - incl_app_filters and excl_app_filters.

+

The creation of the specification for a target system is + performed in two steps. In the first step a complete + specification is generated. It will likely contain much more + files than you are interested in your customized target + system. In the second step the specification will be filtered + according to your filters. There you have the ability to + specify filters per application as well as system wide + filters. You can also select a profile for your + system. Depending on the profile, different default + filters will be used. There are three different profiles to + choose from: development, embedded and + standalone. development is default. The + parameters that are affected by the profile are: + incl_sys_filters, excl_sys_filters, + incl_app_filters and excl_app_filters.

app_file @@ -386,14 +386,14 @@ incl_cond -

This parameter controls whether the module is included or not. By - default the mod_incl parameter on application and system level - will be used to control whether the module is included or not. The - value of incl_cond overrides the module inclusion policy. - include implies that the module is included, while - exclude implies that the module not is included. - derived implies that the is included if any included uses the - module.

+

This parameter controls whether the module is included or not. By + default the mod_incl parameter on application and system level + will be used to control whether the module is included or not. The + value of incl_cond overrides the module inclusion policy. + include implies that the module is included, while + exclude implies that the module not is included. + derived implies that the is included if any included uses the + module.

debug_info @@ -479,7 +479,7 @@ re_regexp() = string() reason() = string() regexps() = [re_regexp()] | {add, [re_regexp()]} - | {del, [re_regexp()]} + | {del, [re_regexp()]} rel_file() = term() rel_name() = string() rel_vsn() = string() @@ -511,9 +511,9 @@ target_spec() = [target_spec()] create_target(Server, TargetDir) -> ok | {error, Reason} Create a target system - Server = server() + Server = server() TargetDir = target_dir() - Reason = reason() + Reason = reason()

Create a target system. Gives the same result as {ok,TargetSpec}=reltool:get_target_spec(Server) and diff --git a/lib/reltool/src/reltool_target.erl b/lib/reltool/src/reltool_target.erl index 6149279112..dd6f75b9fc 100644 --- a/lib/reltool/src/reltool_target.erl +++ b/lib/reltool/src/reltool_target.erl @@ -322,7 +322,6 @@ merge_apps(#rel{name = RelName, A#app.name =/= erts, A#app.name =/= ?MISSING_APP_NAME, not lists:keymember(A#app.name, #app.name, MergedApps2)], - io:format("Embedded: ~p\n", [Embedded]), MergedApps3 = do_merge_apps(RelName, Embedded, Apps, EmbAppType, MergedApps2), sort_apps(MergedApps3). @@ -776,8 +775,6 @@ do_gen_spec(#sys{root_dir = RootDir, {create_dir,BootVsn, RelFiles}]}, {create_dir, "bin", BinFiles} ] ++ SysFiles2, - %% io:format("InclRegexps2: ~p\n", [InclRegexps2]), - %% io:format("ExclRegexps2: ~p\n", [ExclRegexps2]), SysFiles4 = filter_spec(SysFiles3, InclRegexps2, ExclRegexps2), SysFiles5 = SysFiles4 ++ [{create_dir, "lib", LibFiles}], check_sys(["bin", "erts", "lib"], SysFiles5), @@ -921,7 +918,6 @@ check_sys(Mandatory, SysFiles) -> lists:foreach(fun(M) -> do_check_sys(M, SysFiles) end, Mandatory). do_check_sys(Prefix, Specs) -> - %%io:format("Prefix: ~p\n", [Prefix]), case lookup_spec(Prefix, Specs) of [] -> reltool_utils:throw_error("Mandatory system directory ~s " @@ -989,10 +985,10 @@ check_apps([], _) -> spec_app(#app{name = Name, mods = Mods, active_dir = SourceDir, - incl_app_filters = AppInclRegexps, - excl_app_filters = AppExclRegexps} = App, - #sys{incl_app_filters = SysInclRegexps, - excl_app_filters = SysExclRegexps, + incl_app_filters = AppInclRegexps, + excl_app_filters = AppExclRegexps} = App, + #sys{incl_app_filters = SysInclRegexps, + excl_app_filters = SysExclRegexps, debug_info = SysDebugInfo} = Sys) -> %% List files recursively {create_dir, _, AppFiles} = spec_dir(SourceDir), @@ -1342,18 +1338,7 @@ opt_join(Path, File) -> filename:join([Path, File]). match(String, InclRegexps, ExclRegexps) -> - %%case - match(String, InclRegexps) andalso not match(String, ExclRegexps). -%% of -%% true -> -%% true; -%% false -> -%% io:format("no match: ~p\n" -%% " incl: ~p\n" -%% " excl: ~p\n", -%% [String, InclRegexps, ExclRegexps]), -%% false -%% end. + match(String, InclRegexps) andalso not match(String, ExclRegexps). %% Match at least one regexp match(_String, []) -> diff --git a/lib/reltool/test/reltool_server_SUITE.erl b/lib/reltool/test/reltool_server_SUITE.erl index df53d0cc23..d9c6a1350c 100644 --- a/lib/reltool/test/reltool_server_SUITE.erl +++ b/lib/reltool/test/reltool_server_SUITE.erl @@ -130,8 +130,7 @@ create_release(_Config) -> {value, {_, _, StdlibVsn}} = lists:keysearch(stdlib, 1, Apps), Rel = {release, {RelName, RelVsn}, {erts, ErtsVsn}, - [{kernel, KernelVsn}, - {stdlib, StdlibVsn}]}, + [{kernel, KernelVsn}, {stdlib, StdlibVsn}]}, ?m({ok, Rel}, reltool:get_rel([{config, Config}], RelName)), ok. @@ -161,7 +160,7 @@ create_script(_Config) -> Rel = {release, {RelName, RelVsn}, {erts, ErtsVsn}, - [{stdlib, StdlibVsn}, {kernel, KernelVsn}]}, + [{kernel, KernelVsn}, {stdlib, StdlibVsn}]}, ?m({ok, Rel}, reltool:get_rel(Pid, RelName)), ?m(ok, file:write_file(filename:join([?WORK_DIR, RelName ++ ".rel"]), io_lib:format("~p.\n", [Rel]))), @@ -208,6 +207,7 @@ create_target(_Config) -> TargetDir = filename:join([?WORK_DIR, "target_development"]), ?m(ok, reltool_utils:recursive_delete(TargetDir)), ?m(ok, file:make_dir(TargetDir)), + ?log("SPEC: ~p\n", [reltool:get_target_spec([{config, Config}])]), ?m(ok, reltool:create_target([{config, Config}], TargetDir)), Erl = filename:join([TargetDir, "bin", "erl"]), @@ -294,6 +294,8 @@ create_standalone(_Config) -> create_old_target(TestInfo) when is_atom(TestInfo) -> reltool_test_lib:tc_info(TestInfo); create_old_target(_Config) -> + ?skip("Old style of target", []), + %% Configure the server RelName1 = "Just testing", RelName2 = "Just testing with SASL", diff --git a/lib/reltool/test/reltool_test_lib.hrl b/lib/reltool/test/reltool_test_lib.hrl index 93134144ea..60032030ad 100644 --- a/lib/reltool/test/reltool_test_lib.hrl +++ b/lib/reltool/test/reltool_test_lib.hrl @@ -18,6 +18,7 @@ -include_lib("wx/include/wx.hrl"). +-define(flat_format(Format,Args), lists:flatten(io_lib:format(Format,Args))). -define(log(Format,Args), reltool_test_lib:log(Format,Args,?FILE,?LINE)). -define(warning(Format,Args), ?log("\n " ++ Format,Args)). -define(error(Format,Args), reltool_test_lib:error(Format,Args,?FILE,?LINE)). -- cgit v1.2.3