⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 systools_make.erl

📁 OTP是开放电信平台的简称
💻 ERL
📖 第 1 页 / 共 5 页
字号:
	      end,    ok = xref:set_library_path(?XREF_SERVER, LibPath),    check_xref(sofs:to_external(AppDirs)).check_xref([{App,AppDir} | Appls]) ->    case xref:add_application(?XREF_SERVER, AppDir, {name,App}) of	{ok, _App} ->	    check_xref(Appls);	Error ->	    xref:stop(?XREF_SERVER),	    [{error, Error}]    end;check_xref([]) ->    R = case xref:analyze(?XREF_SERVER, undefined_functions) of	    {ok, []} ->		[];	    {ok, Undefined} -> 		%% This clause is a (temporary?) fix for hipe.		adjust_for_hipe(Undefined);	    Error ->		[{error, Error}]	end,    xref:stop(?XREF_SERVER),    R.adjust_for_hipe(Undef) ->    case erlang:system_info(hipe_architecture) of	undefined ->	    U = lists:filter(fun ({hipe_bifs,_,_}) -> false;				 ({hipe,_,_}) -> false;				 (_) -> true			     end, Undef),	    if 		[] == U ->		    [];		true ->		    [{warning, {exref_undef, U}}]	    end;	_Arch -> 	    %% Some BIFs are not always available on all versions of HiPE.	    U = lists:filter(fun ({hipe_bifs,write_u64,2}) -> false;				 (_) -> true			     end, Undef),	    [{warning, {exref_undef, U}}]    end.%% Perform cross reference checks between all modules specified%% in .app files.%%xref_p(Flags) ->    case member(exref, Flags) of	true ->	    exists_xref(true);	_ ->	    case get_flag(exref, Flags) of		{exref, Appls} when is_list(Appls) ->		    case a_list_p(Appls) of			true -> exists_xref({true, Appls});			_    -> false		    end;		_ ->		    false	    end    end.exists_xref(Flag) ->    case code:ensure_loaded(xref) of	{error, _} -> false;	_          -> Flag    end.objfile_extension(false) ->    code:objfile_extension();objfile_extension(Machine) ->    "." ++ atom_to_list(Machine).check_mod(Mod,App,Dir,Ext,IncPath) ->    ObjFile = mod_to_filename(Dir, Mod, Ext),    case file:read_file_info(ObjFile) of	{ok,FileInfo} ->	    LastModTime = FileInfo#file_info.mtime,	    check_module(Mod, Dir, LastModTime, IncPath);	_ ->	    {error, {module_not_found, App, Mod}}    end.mod_to_filename(Dir, Mod, Ext) ->    Parts = packages:split(Mod),    filename:join([Dir | Parts]) ++ Ext.check_module(Mod, Dir, ObjModTime, IncPath) ->    {SrcDirs,_IncDirs}= smart_guess(Mod, Dir,IncPath),    case locate_src(Mod,SrcDirs) of	{ok,_FDir,_File,LastModTime} ->	    if		LastModTime > ObjModTime ->		    {warning, obj_out_of_date};		true ->		    ok	    end;	_ ->	    {warning, source_not_found}    end.locate_src(Mod,[Dir|Dirs]) ->    File = filename:join(Dir, mod_to_fname(Mod) ++ ".erl"),    case file:read_file_info(File) of	{ok,FileInfo} ->	    LastModTime = FileInfo#file_info.mtime,	    {ok,Dir,File,LastModTime};	_ ->	    locate_src(Mod,Dirs)    end;locate_src(_,[]) ->    false.mod_to_fname(Mod) ->    hd(lists:reverse(packages:split(Mod))).%%______________________________________________________________________%% smart_guess(Mod, Dir,IncludePath) -> {[Dirs],[IncDirs]}%% Guess the src code and include directory. If dir contains .../ebin%% src-dir should be one of .../src or .../src/e_src%% If dir does not contain .../ebin set dir to the same directory.smart_guess(Mod, Dir,IncPath) ->    case reverse(filename:split(Dir)) of	["ebin"|D] ->	    Subdirs = case packages:split(Mod) of			  [_] -> [];			  [_|_] = Parts ->			      lists:reverse(tl(lists:reverse(Parts)))		      end,	    D1 = reverse(D),	    Dirs = [filename:join(D1 ++ ["src" | Subdirs]),		    filename:join(D1 ++ ["src", "e_src" | Subdirs])],	    {Dirs,Dirs ++ IncPath};	_ ->	    {[Dir],[Dir] ++ IncPath}    end.%%______________________________________________________________________%% generate_script(#release, %%                 [{{Name,Vsn},#application}], Flags) ->%%                         ok | {error, Error}%%    Writes a script (a la magnus) to the file File.script%%    and a bootfile to File.boot.generate_script(Output, Release, Appls, Flags) ->    PathFlag = path_flag(Flags),    Variables = get_variables(Flags),    Script = {script, {Release#release.name,Release#release.vsn},	      [{preLoaded, preloaded()},	       {progress, preloaded},	       {path, create_mandatory_path(Appls, PathFlag, Variables)},	       {primLoad, mandatory_modules()},	       {kernel_load_completed},	       {progress, kernel_load_completed}] ++	      load_appl_mods(Appls, mandatory_modules() ++ preloaded(),			     PathFlag, Variables) ++	      [{path, create_path(Appls, PathFlag, Variables)}] ++	      create_kernel_procs(Appls) ++	      create_load_appls(Appls) ++	      create_start_appls(Appls) ++	      script_end()	     },    ScriptFile = Output ++ ".script",    case file:open(ScriptFile, write) of	{ok, Fd} ->	    io:format(Fd, "%% script generated at ~w ~w\n~p.\n",		      [date(), time(), Script]),	    file:close(Fd),	    BootFile = Output ++ ".boot",	    case file:write_file(BootFile, term_to_binary(Script)) of		ok ->		    ok;		{error, Reason} ->		    {error, ?MODULE, {open,BootFile,Reason}}	    end;	{error, Reason} ->	    {error, ?MODULE, {open,ScriptFile,Reason}}    end.path_flag(Flags) ->    case {member(local,Flags), member(otp_build, Flags)} of	{true, _} -> local;	{_, true} -> otp_build;	{_, _}    -> true    end.get_variables(Flags) ->    case get_flag(variables, Flags) of	{variables, Variables} when is_list(Variables) ->	    valid_variables(Variables);	_ ->	    []    end.valid_variables([{Var,Path}|Variables]) when is_list(Var), is_list(Path) ->    [{Var,rm_tlsl(Path)}|valid_variables(Variables)];valid_variables([{Var,Path}|Variables]) when is_atom(Var), is_list(Path) ->    [{to_list(Var),rm_tlsl(Path)}|valid_variables(Variables)];valid_variables([_|Variables]) ->    valid_variables(Variables);valid_variables(_) ->    [].rm_tlsl(P) -> rm_tlsl1(reverse(P)).rm_tlsl1([$/|P]) -> rm_tlsl1(P);rm_tlsl1(P) -> reverse(P).  %%______________________________________________________________________%% Start all applications.%% Do not start applications that are included applications !create_start_appls(Appls) ->    Included = append(map(fun({_,A}) ->				  A#application.includes		      end, Appls)),    create_start_appls(Appls, Included).create_start_appls([{_,A}|T], Incl) ->    App = A#application.name,    case lists:member(App, Incl) of	false when A#application.type == none ->	    create_start_appls(T, Incl);	false when A#application.type == load ->	    create_start_appls(T, Incl);	false ->	    [{apply, {application, start_boot, [App,A#application.type]}} |	     create_start_appls(T, Incl)];	_ ->	    create_start_appls(T, Incl)    end;create_start_appls([], _) ->    [].%%______________________________________________________________________%% Load all applications.create_load_appls([{{kernel,_},_}|T]) -> %Already added !!    create_load_appls(T);create_load_appls([{_,A}|T]) when A#application.type == none ->    create_load_appls(T);create_load_appls([{_,A}|T]) ->    [{apply, {application, load, [pack_app(A)]}} |     create_load_appls(T)];create_load_appls([]) ->    [{progress, applications_loaded}].%%______________________________________________________________________%% The final part of the script.script_end() ->    [{apply, {c, erlangrc, []}},     {progress, started}].%%-----------------------------------------------------------------%% Function: sort_appls(Appls) -> {ok, Appls'} | throw({error, Error})%% Types: Appls = {{Name, Vsn}, #application}]%% Purpose: Sort applications according to dependencies among%%          applications.  If order doesn't matter, use the same%%          order as in the original list.%% Alg. written by Ulf Wiger 970917 (etxuwig@etxb.ericsson.se)%% Mod. by mbj%%-----------------------------------------------------------------sort_appls(Appls) -> {ok, sort_appls(Appls, [], [], [])}.sort_appls([{N, A}|T], Missing, Circular, Visited) ->    {Name,_Vsn} = N,    {Uses, T1, NotFnd1} = find_all(Name, A#application.uses, T, Visited, [], []),    {Incs, T2, NotFnd2} = find_all(Name, lists:reverse(A#application.includes),				   T1, Visited, [], []),    Missing1 = NotFnd1 ++ NotFnd2 ++ Missing,    case Uses ++ Incs of	[] -> 	    %% No more app that must be started before this one is	    %% found; they are all already taken care of (and present	    %% in Visited list)	    [{N, A}|sort_appls(T, Missing1, Circular, [N|Visited])];	L ->	    %% The apps in L must be started before the app.	    %% Check if we have already taken care of some app in L,	    %% in that case we have a circular dependency.	    NewCircular = [N1 || {N1, _} <- L, N2 <- Visited, N1 == N2],	    Circular1 = case NewCircular of 			    [] -> Circular; 			    _ -> [N | NewCircular] ++ Circular			end,	    %% L must be started before N, try again, with all apps	    %% in L added before N.	    Apps = del_apps(NewCircular, L ++ [{N, A}|T2]),	    sort_appls(Apps, Missing1, Circular1, [N|Visited])    end;sort_appls([], [], [], _) ->    [];sort_appls([], Missing, [], _) ->    %% this has already been checked before, but as we have the info...    throw({error, {undefined_applications, make_set(Missing)}});sort_appls([], [], Circular, _) ->    throw({error, {circular_dependencies, make_set(Circular)}});sort_appls([], Missing, Circular, _) ->    throw({error, {apps, [{circular_dependencies, make_set(Circular)}, 			  {undefined_applications, make_set(Missing)}]}}).find_all(CheckingApp, [Name|T], L, Visited, Found, NotFound) ->    case find_app(Name, L) of	{value, App} ->	    {_A,R} = App,	    %% It is OK to have a dependecy like	    %% X includes Y, Y uses X.	    case lists:member(CheckingApp, R#application.includes) of		true ->		    case lists:keymember(Name, 1, Visited) of			true ->			    find_all(CheckingApp, T, L, Visited, Found, NotFound);			false ->			    find_all(CheckingApp, T, L, Visited, Found, [Name|NotFound])		    end;		false ->		    find_all(CheckingApp, T, L -- [App], Visited, [App|Found], NotFound)	    end;	false ->	    case lists:keymember(Name, 1, Visited) of		true ->		    find_all(CheckingApp, T, L, Visited, Found, NotFound);		false ->		    find_all(CheckingApp, T, L, Visited, Found, [Name|NotFound])	    end    end;find_all(_CheckingApp, [], L, _Visited, Found, NotFound) ->    {Found, L, NotFound}.	    find_app(Name, [{{Name,Vsn}, Application}|_]) ->    {value, {{Name,Vsn},Application}};find_app(Name, [_|T]) ->    find_app(Name, T);find_app(_Name, []) ->    false.del_apps([Name|T], L) ->    del_apps(T, lists:keydelete(Name, 1, L));del_apps([], L) ->    L.%%______________________________________________________________________%% Create the load path used in the generated script.%% If PathFlag is true a script intended to be used as a complete%% system (e.g. in an embbeded system), i.e. all applications are%% located under $ROOT/lib.%% Otherwise all paths are set according to dir per application.%% Create the complete path.create_path(Appls, PathFlag, Variables) ->    make_set(map(fun({{Name,Vsn},App}) ->			 cr_path(Name, Vsn, App, PathFlag, Variables)		 end,		 Appls)).%% Create the path to a specific application.%% (The otp_build flag is only used for OTP internal system make)cr_path(Name, Vsn, _, true, []) ->    filename:join(["$ROOT", "lib", to_list(Name) ++ "-" ++ Vsn, "ebin"]);cr_path(Name, Vsn, App, true, Variables) ->    Dir = App#application.dir,    N = to_list(Name),    Tail = [N ++ "-" ++ Vsn, "ebin"],    case variable_dir(Dir, N, Vsn, Variables) of	{ok, VarDir} ->	    filename:join([VarDir] ++ Tail);	_ ->	    filename:join(["$ROOT", "lib"] ++ Tail)    end;cr_path(Name, _, _, otp_build, _) ->    filename:join(["$ROOT", "lib", to_list(Name), "ebin"]);cr_path(_, _, App, _, _) ->    filename:absname(App#application.dir).variable_dir(Dir, Name, Vsn, [{Var,Path}|Variables]) ->    case lists:prefix(Path,Dir) of	true ->	    D0 = strip_prefix(Path, Dir),	    case strip_name_ebin(D0, Name, Vsn) of		{ok, D} ->		    {ok, filename:join(["\$" ++ Var] ++ D)};		_ ->		    %% We know at least that we are located		    %% under the variable dir.		    {ok, filename:join(["\$" ++ Var] ++ D0)}	    end;	_ ->	    variable_dir(Dir, Name, Vsn, Variables)    end;variable_dir(_Dir, _, _, []) ->    false.strip_prefix(Path, Dir) ->    L = length(filename:split(Path)),    lists:nthtail(L, filename:split(Dir)).strip_name_ebin(Dir, Name, Vsn) ->    FullName = Name ++ "-" ++ Vsn,    case reverse(Dir) of	["ebin",Name|D]     -> {ok, reverse(D)};	["ebin",FullName|D] -> {ok, reverse(D)};	_                   -> false    end.%% Create the path to the kernel and stdlib applications.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -