erl_compile.erl
来自「OTP是开放电信平台的简称」· ERL 代码 · 共 222 行
ERL
222 行
%% ``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.''%% %% Purpose: Consistent interface to various compilers. Invoked from erlc.%%%% $Id$%%-module(erl_compile).-include("erl_compile.hrl").-include("file.hrl").-export([compile_cmdline/1]).%% Mapping from extension to {M,F} to run the correct compiler.compiler(".erl") -> {compile, compile};compiler(".S") -> {compile, compile_asm};compiler(".beam") -> {compile, compile_beam};compiler(".core") -> {compile, compile_core};compiler(".mib") -> {snmpc, compile};compiler(".bin") -> {snmpc, mib_to_hrl};compiler(".yrl") -> {yecc, compile};compiler(".script") -> {systools, script2boot};compiler(".rel") -> {systools, compile_rel};compiler(".idl") -> {ic, compile};compiler(".asn1") -> {asn1ct, compile_asn1};compiler(".asn") -> {asn1ct, compile_asn};compiler(".py") -> {asn1ct, compile_py};compiler(".xml") -> {xmerl_scan, process};compiler(_) -> no.%% Entry from command line.compile_cmdline(List) -> case compile(List) of ok -> my_halt(0); error -> my_halt(1); _ -> my_halt(2) end.my_halt(Reason) -> case process_info(group_leader(), status) of {_,waiting} -> %% Now all output data is down in the driver. %% Give the driver some extra time before halting. receive after 1 -> ok end, halt(Reason); _ -> %% Probably still processing I/O requests. erlang:yield(), my_halt(Reason) end.%% Run the the compiler in a separate process, trapping EXITs.compile(List) -> process_flag(trap_exit, true), Pid = spawn_link(fun() -> compiler_runner(List) end), receive {'EXIT', Pid, {compiler_result, Result}} -> Result; {'EXIT', Pid, Reason} -> io:format("Runtime error: ~p~n", [Reason]), error end.compiler_runner(List) -> exit({compiler_result, compile1(List)}).%% Parses the first part of the option list.compile1(['@cwd', Cwd|Rest]) -> CwdL = atom_to_list(Cwd), compile1(Rest, Cwd, #options{outdir=CwdL, cwd=CwdL});compile1(Other) -> throw({error, {bad_input, Other}}).%% Parses all options.compile1(['@i', Dir|Rest], Cwd, Opts) -> AbsDir = filename:absname(Dir, Cwd), compile1(Rest, Cwd, Opts#options{includes=[AbsDir|Opts#options.includes]});compile1(['@outdir', Dir|Rest], Cwd, Opts) -> AbsName = filename:absname(Dir, Cwd), case file_or_directory(AbsName) of file -> compile1(Rest, Cwd, Opts#options{outfile=AbsName}); directory -> compile1(Rest, Cwd, Opts#options{outdir=AbsName}) end;compile1(['@d', Name|Rest], Cwd, Opts) -> Defines = Opts#options.defines, compile1(Rest, Cwd, Opts#options{defines=[Name|Defines]});compile1(['@dv', Name, Term|Rest], Cwd, Opts) -> Defines = Opts#options.defines, Value = make_term(atom_to_list(Term)), compile1(Rest, Cwd, Opts#options{defines=[{Name, Value}|Defines]});compile1(['@warn', Level0|Rest], Cwd, Opts) -> case catch list_to_integer(atom_to_list(Level0)) of Level when is_integer(Level) -> compile1(Rest, Cwd, Opts#options{warning=Level}); _ -> compile1(Rest, Cwd, Opts) end;compile1(['@verbose', false|Rest], Cwd, Opts) -> compile1(Rest, Cwd, Opts#options{verbose=false});compile1(['@verbose', true|Rest], Cwd, Opts) -> compile1(Rest, Cwd, Opts#options{verbose=true});compile1(['@optimize', Atom|Rest], Cwd, Opts) -> Term = make_term(atom_to_list(Atom)), compile1(Rest, Cwd, Opts#options{optimize=Term});compile1(['@option', Atom|Rest], Cwd, Opts) -> Term = make_term(atom_to_list(Atom)), Specific = Opts#options.specific, compile1(Rest, Cwd, Opts#options{specific=[Term|Specific]});compile1(['@output_type', OutputType|Rest], Cwd, Opts) -> compile1(Rest, Cwd, Opts#options{output_type=OutputType});compile1(['@files'|Rest], Cwd, Opts) -> Includes = lists:reverse(Opts#options.includes), compile2(Rest, Cwd, Opts#options{includes=Includes}).compile2(Files, Cwd, Opts) -> case {Opts#options.outfile, length(Files)} of {"", _} -> compile3(Files, Cwd, Opts); {[_|_], 1} -> compile3(Files, Cwd, Opts); {[_|_], _N} -> io:format("Output file name given, but more than one input file.~n"), error end.%% Compiles the list of files, until done or compilation fails.compile3([File|Rest], Cwd, Options) -> Ext = filename:extension(File), Root = filename:rootname(File), InFile = filename:absname(Root, Cwd), OutFile = case Options#options.outfile of "" -> filename:join(Options#options.outdir, filename:basename(Root)); Outfile -> filename:rootname(Outfile) end, case compile_file(Ext, InFile, OutFile, Options) of ok -> compile3(Rest, Cwd, Options); Other -> Other end;compile3([], _Cwd, _Options) -> ok.%% Invokes the appropriate compiler, depending on the file extension.compile_file("", Input, _Output, _Options) -> io:format("File has no extension: ~s~n", [Input]), error;compile_file(Ext, Input, Output, Options) -> case compiler(Ext) of no -> io:format("Unknown extension: '~s'\n", [Ext]), error; {M, F} -> case catch M:F(Input, Output, Options) of ok -> ok; error -> error; {'EXIT',Reason} -> io:format("Compiler function ~w:~w/3 failed:\n~p~n", [M,F,Reason]), error; Other -> io:format("Compiler function ~w:~w/3 returned:\n~p~n", [M,F,Other]), error end end.%% Guesses if a give name refers to a file or a directory.file_or_directory(Name) -> case file:read_file_info(Name) of {ok, #file_info{type=regular}} -> file; {ok, _} -> directory; {error, _} -> case filename:extension(Name) of [] -> directory; _Other -> file end end.%% Makes an Erlang term given a string.make_term(Str) -> case erl_scan:string(Str) of {ok, Tokens, _} -> case erl_parse:parse_term(Tokens ++ [{dot, 1}]) of {ok, Term} -> Term; {error, {_,_,Reason}} -> io:format("~s: ~s~n", [Reason, Str]), throw(error) end; {error, {_,_,Reason}, _} -> io:format("~s: ~s~n", [Reason, Str]), throw(error) end.
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?