[2013-04-19] erl -make 编译

简单的看了一下erl -make 编译的过程,简单记录一下

rl -make
 
实际上相当于 调用make:all() 方法 通过解析Emakefile 文件 进行编译的过程,
 
%% 编译模式 noexec 不使用任何模式,单纯打印需要编译的模块名称
%% load 编译并加载
%% netload 编译并在所有节点上加载
%% noload 编译但不加载
-define(MakeOpts,[noexec,load,netload,noload]).
 
从宏定义的几个字段可以简单看出,erl -make 的编译存在4种编译模式
 
all(Options) ->
 
    {MakeOpts,CompileOpts} = sort_options(Options,[],[]),
 
    case read_emakefile('Emakefile',CompileOpts) of
Files when is_list(Files) ->
            %%取得所有编译文件
    do_make_files(Files,MakeOpts);
error ->
    error
    end.
 
 
all 函数很简单,首先通过sort_options(Options,[],[]),编译的参数进行区分,其实就是从 Opts 中分离 MakeOpts 编译方式 和 编译的参数,  {MakeOpts,CompileOpts},
接着 通过 read_emakefile 方法读取和解析 emakefile 文件,取得所有需要编译的文件列表, 最后直接调用 do_make_files 函数对取得的编译文件列表进行编译
 
简单看一下解析分析read_emakefile 函数执行的过程
read_emakefile(Emakefile,Opts) ->
    case file:consult(Emakefile) of
{ok,Emake} ->
    transform(Emake,Opts,[],[]);
{error,enoent} ->
    %% No Emakefile found - return all modules in current 
    %% directory and the options given at command line
    Mods = [filename:rootname(F) ||  F <- filelib:wildcard("*.erl")],
    [{Mods, Opts}];
{error,Other} ->
    io:format("make: Trouble reading 'Emakefile':~n~p~n",[Other]),
    error
    end.
transform 函数的作用便是直接从emakefile文件配置的目录中取得所有的.erl 结尾的文件列表 , 如果不存在 emakefile文件,则直接取得当前目录下的所有.erl 文件
Emakefile 的文件格式
{
    %% 编译路劲
    [  "src/*" ,
        "src/*/*"
    ],
    %% 编译参数
    []
}
 
在看一下do_make_files 编译的过程,
从编译参数中取得编译的目标文件目录然后检查是否已经存在一个目标文件,如果不存在,
直接编译,如果采用noeec模式编译,则打印编译文件后直接进行下一个,如果是noload 模式则采用  compile:file 对文件进行编译
如果是load模式,则采用c:c进行编译 ,netload  则 c:nc
 
如果目标文件存在,则使用file:read_file_info 分别读取 编译文件 以及已存在的目标文件,对比两者的时间,
如果编译文件修改时间新与目标文件,则编译 替换
如果修改时间一致,则读取文件的 include头文件,如果问头见的修改时间大于目标文件的编译时间,则编译,否则跳过
 
do_make_files(Fs, Opts) ->
    process(Fs, lists:member(noexec, Opts), load_opt(Opts)).
process([{[],_Opts}|Rest], NoExec, Load) ->
    process(Rest, NoExec, Load);
process([{[H|T],Opts}|Rest], NoExec, Load) ->
    case recompilep(coerce_2_list(H), NoExec, Load, Opts) of
error ->
    error;
_ ->
    process([{T,Opts}|Rest], NoExec, Load)
    end;
process([], _NoExec, _Load) ->
    up_to_date.
posted @ 2013-04-19 18:40  哈雷路亚  阅读(309)  评论(0)    收藏  举报