📄 systools_make.erl
字号:
%% ``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 via the world wide web 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.%% %% The Initial Developer of the Original Code is Ericsson Utvecklings AB.%% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings%% AB. All Rights Reserved.''%% %% $Id$%%-module(systools_make).%% Purpose : Create start script. RelName.rel --> RelName.{script,boot}.%% and create a tar file of a release (RelName.tar.gz)-export([make_script/1, make_script/2, make_script/3, make_tar/1, make_tar/2]).-export([format_error/1, format_warning/1]).-export([read_release/2, get_release/2, get_release/3, get_release/4, pack_app/1]).-export([read_application/4]).-import(lists, [filter/2, keysort/2, keysearch/3, map/2, reverse/1, append/1, foldl/3, member/2, foreach/2]).-include("systools.hrl").-include_lib("kernel/include/file.hrl").-define(XREF_SERVER, systools_make).-compile({inline,[{badarg,2}]}).%%-----------------------------------------------------------------%% Create a boot script from a release file.%% Options is a list of {path, Path} | silent | local where path sets%% the search path, silent supresses error message printing on console,%% local generates a script with references to the directories there%% the applications are found.%%%% New options: {path,Path} can contain wildcards%% no_module_tests%% {variables,[{Name,AbsString}]}%% {machine, jam | beam | vee}%% exref | {exref, [AppName]}%%-----------------------------------------------------------------make_script(RelName) when is_list(RelName) -> make_script(RelName, []);make_script(RelName) -> badarg(RelName,[RelName]).make_script(RelName, Flags) when is_list(RelName), is_list(Flags) -> case get_outdir(Flags) of "" -> make_script(RelName, RelName, Flags); OutDir -> %% To maintain backwards compatibility for make_script/3, %% the boot script file name is constructed here, before %% checking the validity of OutDir %% (is done in check_args_script/1) Output = filename:join(OutDir, filename:basename(RelName)), make_script(RelName, Output, Flags) end. make_script(RelName, Output, Flags) when is_list(RelName), is_list(Output), is_list(Flags) -> case check_args_script(Flags) of [] -> Path0 = get_path(Flags), Path1 = mk_path(Path0), % expand wildcards etc. Path = make_set(Path1 ++ code:get_path()), ModTestP = {not member(no_module_tests, Flags), xref_p(Flags)}, case get_release(RelName, Path, ModTestP, machine(Flags)) of {ok, Release, Appls, Warnings} -> case generate_script(Output,Release,Appls,Flags) of ok -> return(ok,Warnings,Flags); Error -> return(Error,Warnings,Flags) end; Error -> return(Error,[],Flags) end; ErrorVars -> badarg(ErrorVars, [RelName, Flags]) end;make_script(RelName, _Output, Flags) when is_list(Flags) -> badarg(RelName,[RelName, Flags]);make_script(RelName, _Output, Flags) -> badarg(Flags,[RelName, Flags]).%% Inlined.badarg(BadArg, Args) -> erlang:error({badarg,BadArg}, Args).machine(Flags) -> case get_flag(machine,Flags) of {machine, Machine} when is_atom(Machine) -> Machine; _ -> false end.get_path(Flags) -> case get_flag(path,Flags) of {path,Path} when is_list(Path) -> Path; _ -> [] end.get_outdir(Flags) -> case get_flag(outdir,Flags) of {outdir,OutDir} when is_list(OutDir) -> OutDir; _ -> % false | {outdir, Badarg} "" end.return(ok,Warnings,Flags) -> case member(silent,Flags) of true -> {ok,?MODULE,Warnings}; _ -> io:format("~s",[format_warning(Warnings)]), ok end;return({error,Mod,Error},_,Flags) -> case member(silent,Flags) of true -> {error,Mod,Error}; _ -> io:format("~s",[Mod:format_error(Error)]), error end.%%-----------------------------------------------------------------%% Create a release package from a release file.%% Options is a list of {path, Path} | silent |%% {dirs, [src,include,examples,..]} | {erts, ErtsDir} where path%% sets the search path, silent supresses error message printing,%% dirs includes the specified directories (per application) in the%% release package and erts specifies that the erts-Vsn/bin directory%% should be included in the release package and there it can be found.%%%% New options: {path,Path} can contain wildcards%% no_module_tests%% exref | {exref, [AppName]}%% {variables,[{Name,AbsString}]}%% {machine, jam | beam | vee}%% {var_tar, include | ownfile | omit}%%%% The tar file contains:%% lib/App-Vsn/ebin%% /priv%% [/src]%% [/include]%% [/doc]%% [/examples]%% [/...]%% Variable1.tar.gz%% ...%% VariableN.tar.gz%% releases/RelName.rel%% RelVsn/start.boot%% relup%% sys.config%% erts-EVsn[/bin]%%-----------------------------------------------------------------make_tar(RelName) when is_list(RelName) -> make_tar(RelName, []);make_tar(RelName) -> badarg(RelName,[RelName]).make_tar(RelName, Flags) when is_list(RelName), is_list(Flags) -> case check_args_tar(Flags) of [] -> Path0 = get_path(Flags), Path1 = mk_path(Path0), Path = make_set(Path1 ++ code:get_path()), ModTestP = {not member(no_module_tests, Flags), xref_p(Flags)}, case get_release(RelName, Path, ModTestP, machine(Flags)) of {ok, Release, Appls, Warnings} -> case catch mk_tar(RelName, Release, Appls, Flags, Path1) of ok -> return(ok,Warnings,Flags); Error -> return(Error,Warnings,Flags) end; Error -> return(Error,[],Flags) end; ErrorVars -> badarg(ErrorVars, [RelName, Flags]) end;make_tar(RelName, Flags) when is_list(Flags) -> badarg(RelName,[RelName, Flags]);make_tar(RelName, Flags) -> badarg(Flags,[RelName, Flags]). %%______________________________________________________________________%% get_release(File, Path) ->%% get_release(File, Path, ModTestP) ->%% get_release(File, Path, ModTestP, Machine) ->%% {ok, #release, [{{Name,Vsn},#application}], Warnings} | {error, What}get_release(File, Path) -> get_release(File, Path, true, false).get_release(File, Path, ModTestP) -> get_release(File, Path, ModTestP, false).get_release(File, Path, ModTestP, Machine) -> case catch get_release1(File, Path, ModTestP, Machine) of {error, Error} -> {error, ?MODULE, Error}; {'EXIT', Why} -> {error, ?MODULE, {'EXIT',Why}}; Answer -> Answer end. get_release1(File, Path, ModTestP, Machine) -> {ok, Release} = read_release(File, Path), {ok, Appls0} = collect_applications(Release, Path), {ok, Appls1} = check_applications(Appls0), {ok, Appls2} = sort_included_applications(Appls1, Release), % OTP-4121 {ok, Warnings} = check_modules(Appls2, Path, ModTestP, Machine), {ok, Appls} = sort_appls(Appls2), {ok, Release, Appls, Warnings}.%%______________________________________________________________________%% read_release(File, Path) -> {ok, #release} | throw({error, What})read_release(File, Path) -> case read_file(File ++ ".rel", ["."|Path]) of {ok, Release, _FullName} -> check_rel(Release); {error,Error} -> throw({error,?MODULE,Error}) end.check_rel(Release) -> case catch check_rel1(Release) of {ok, {Name,Vsn,Evsn,Appl,Incl}} -> {ok, #release{name=Name, vsn=Vsn, erts_vsn=Evsn, applications=Appl, incl_apps=Incl}}; {error, Error} -> throw({error,?MODULE,Error}); Error -> throw({error,?MODULE,Error}) end.check_rel1({release,{Name,Vsn},{erts,EVsn},Appl}) when is_list(Appl) -> check_name(Name), check_vsn(Vsn), check_evsn(EVsn), {Appls,Incls} = check_appl(Appl), {ok, {Name,Vsn,EVsn,Appls,Incls}};check_rel1(_) -> {error, badly_formatted_release}.check_name(Name) -> case string_p(Name) of true -> Name; _ -> throw({error,{illegal_name, Name}}) end.check_vsn(Vsn) -> case string_p(Vsn) of true -> Vsn; _ -> throw({error,{illegal_form, Vsn}}) end.check_evsn(Vsn) -> case string_p(Vsn) of true -> Vsn; _ -> throw({error,{illegal_form, {erts,Vsn}}}) end.check_appl(Appl) -> case filter(fun({App,Vsn}) when is_atom(App) -> not string_p(Vsn); ({App,Vsn,Incl}) when is_atom(App), is_list(Incl) -> case {string_p(Vsn), a_list_p(Incl)} of {true, true} -> false; _ -> true end; ({App,Vsn,Type}) when is_atom(App), is_atom(Type) -> case {string_p(Vsn), is_app_type(Type)} of {true, true} -> false; _ -> true end; ({App,Vsn,Type,Incl}) when is_atom(App), is_atom(Type), is_list(Incl) -> case {string_p(Vsn),is_app_type(Type),a_list_p(Incl)} of {true, true, true} -> false; _ -> true end; (_) -> true end, Appl) of [] -> mandatory_applications(Appl), split_app_incl(Appl); Illegal -> throw({error, {illegal_applications,Illegal}}) end.mandatory_applications(Appl) -> AppNames = map(fun(AppT) -> element(1, AppT) end, Appl), Mand = mandatory_applications(), case filter(fun(X) -> member(X, AppNames) end, Mand) of Mand -> ok; _ -> throw({error, {missing_mandatory_app, Mand}}) end.mandatory_applications() -> [kernel, stdlib].split_app_incl(Appl) -> split_app_incl(Appl, [], []).split_app_incl([{App,Vsn}|Appls], Apps, Incls) -> split_app_incl(Appls, [{App,Vsn,permanent}|Apps], Incls);split_app_incl([{App,Vsn,Incl}|Appls], Apps,Incls) when is_list(Incl) -> split_app_incl(Appls, [{App,Vsn,permanent}|Apps], [{App,Incl}|Incls]);split_app_incl([{App,Vsn,Type}|Appls], Apps, Incls) -> split_app_incl(Appls, [{App,Vsn,Type}|Apps], Incls);split_app_incl([{App,Vsn,Type,Incl}|Appls], Apps, Incls) when is_list(Incl) -> split_app_incl(Appls, [{App,Vsn,Type}|Apps], [{App,Incl}|Incls]);split_app_incl([], Apps, Incls) -> {reverse(Apps),reverse(Incls)}.%%______________________________________________________________________%% collect_applications(#release, Path) -> %% {ok,[{{Name,Vsn},#application}]} |%% throw({error, What})%% Read all the application files specified in the release descriptorcollect_applications(Release, Path) -> Appls = Release#release.applications, Incls = Release#release.incl_apps, X = foldl(fun({Name,Vsn,Type}, {Ok, Errs}) -> case read_application(to_list(Name), Vsn, Path, Incls) of {ok, A} -> case {A#application.name,A#application.vsn} of {Name,Vsn} -> {[{{Name,Vsn}, A#application{type=Type}} | Ok], Errs}; E -> {Ok, [{bad_application_name, {Name, E}} | Errs]} end; {error, What} -> {Ok, [{error_reading, {Name, What}} | Errs]} end end, {[],[]}, Appls), case X of {A, []} -> {ok, reverse(A)}; {_, Errs} -> throw({error, Errs}) end.%%______________________________________________________________________%% read_application(Name, Vsn, Path, Incls) -> {ok, #release} | {error, What}read_application(Name, Vsn, Path, Incls) -> read_application(Name, Vsn, Path, Incls, false, no_fault).read_application(Name, Vsn, [Dir|Path], Incls, Found, FirstError) -> case read_file(Name ++ ".app", [Dir]) of {ok, Term, FullName} -> case parse_application(Term, FullName, Vsn, Incls) of {error, {no_valid_version, {Vsn, OtherVsn}}} when FirstError == no_fault -> NFE = {no_valid_version, {{"should be", Vsn}, {"found file", filename:join(Dir, Name++".app"), OtherVsn}}}, read_application(Name, Vsn, Path, Incls, true, NFE); {error, {no_valid_version, {Vsn, _OtherVsn}}} -> read_application(Name, Vsn, Path, Incls, true, FirstError); Res -> Res end; {error, {parse, _File, {Line, _Mod, Err}}} when FirstError == no_fault -> read_application(Name, Vsn, Path, Incls, Found, {parse_error, {filename:join(Dir, Name++".app"), Line, Err}}); {error, {parse, _File, _Err}} ->
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -