소스 검색

ft: 优化小于批量编译数量时 拆分一个进程一个文件的编译 将编译目录添加到代码目录 全编译的时候 会删除清理输出目录

master
SisMaker 6 달 전
부모
커밋
0d68799d6e
1개의 변경된 파일343개의 추가작업 그리고 328개의 파일을 삭제
  1. +343
    -328
      src/eMake.erl

+ 343
- 328
src/eMake.erl 파일 보기

@ -2,13 +2,13 @@
-include_lib("kernel/include/file.hrl").
-export([
main/1
main/1
]).
-export([
compileWorker/7
, readEMake/0
, saveEMake/1
compileWorker/7
, readEMake/0
, saveEMake/1
]).
-define(MakeOpts, [noexec, load, netload, noload]).
@ -16,403 +16,418 @@
-define(OnceCnt, 16).
main(Args) ->
process_flag(trap_exit, true),
case Args of
["fo"] ->
os:cmd("redis-cli FLUSHDB"),
ok;
["fo", DBNumStr | _] ->
os:cmd("redis-cli -n " ++ DBNumStr ++ " FLUSHDB"),
ok;
["fa" | _] ->
os:cmd("redis-cli FLUSHALL"),
ok;
_ ->
IsAll = lists:member("all", Args),
IsNoHrl = lists:member("nohrl", Args),
case lists:delete("all", lists:delete("nohrl", Args)) of
[] ->
make(max(1, erlang:system_info(schedulers) - 1), ?EMakefile, [], IsAll, IsNoHrl);
[EMakeFileOrWorkCnt] ->
try list_to_integer(EMakeFileOrWorkCnt) of
Cnt ->
make(max(1, Cnt), ?EMakefile, [], IsAll, IsNoHrl)
catch _:_ ->
make(max(1, erlang:system_info(schedulers) - 1), EMakeFileOrWorkCnt, [], IsAll, IsNoHrl)
end;
[EMakeFile, WorkCntStr] ->
make(max(1, list_to_integer(WorkCntStr)), EMakeFile, [], IsAll, IsNoHrl);
[EMakeFile, WorkCntStr, OptsStr] ->
{ok, Opts} = strToTerm(OptsStr),
make(max(1, list_to_integer(WorkCntStr)), EMakeFile, Opts, IsAll, IsNoHrl)
end
end.
process_flag(trap_exit, true),
case Args of
["fo"] ->
os:cmd("redis-cli FLUSHDB"),
ok;
["fo", DBNumStr | _] ->
os:cmd("redis-cli -n " ++ DBNumStr ++ " FLUSHDB"),
ok;
["fa" | _] ->
os:cmd("redis-cli FLUSHALL"),
ok;
_ ->
IsAll = lists:member("all", Args),
IsNoHrl = lists:member("nohrl", Args),
case lists:delete("all", lists:delete("nohrl", Args)) of
[] ->
make(max(1, erlang:system_info(schedulers) - 1), ?EMakefile, [], IsAll, IsNoHrl);
[EMakeFileOrWorkCnt] ->
try list_to_integer(EMakeFileOrWorkCnt) of
Cnt ->
make(max(1, Cnt), ?EMakefile, [], IsAll, IsNoHrl)
catch _:_ ->
make(max(1, erlang:system_info(schedulers) - 1), EMakeFileOrWorkCnt, [], IsAll, IsNoHrl)
end;
[EMakeFile, WorkCntStr] ->
make(max(1, list_to_integer(WorkCntStr)), EMakeFile, [], IsAll, IsNoHrl);
[EMakeFile, WorkCntStr, OptsStr] ->
{ok, Opts} = strToTerm(OptsStr),
make(max(1, list_to_integer(WorkCntStr)), EMakeFile, Opts, IsAll, IsNoHrl)
end
end.
eMakeFile() ->
{ok, CurDir} = file:get_cwd(),
Md5 = erlang:md5(CurDir),
{ok, [[HomeDir]]} = init:get_argument(home),
filename:join(HomeDir, <<".eMake/", (base64:encode(Md5))/binary>>).
{ok, CurDir} = file:get_cwd(),
Md5 = erlang:md5(CurDir),
{ok, [[HomeDir]]} = init:get_argument(home),
filename:join(HomeDir, <<".eMake/", (base64:encode(Md5))/binary>>).
readEMake() ->
try {ok, [LastTime]} = file:consult(eMakeFile()), LastTime of
Value ->
Value
catch _:_ ->
0
end.
try {ok, [LastTime]} = file:consult(eMakeFile()), LastTime of
Value ->
Value
catch _:_ ->
0
end.
saveEMake(NowTime) ->
try
FileName = eMakeFile(),
filelib:ensure_dir(FileName),
file:write_file(FileName, <<(integer_to_binary(NowTime))/binary, ".">>)
catch _:_ ->
ok
end.
try
FileName = eMakeFile(),
filelib:ensure_dir(FileName),
file:write_file(FileName, <<(integer_to_binary(NowTime))/binary, ".">>)
catch _:_ ->
ok
end.
make(WorkerCnt, EMakeFile, Opts, IsAll, IsNoHrl) ->
io:format("compile start use EMakefile: ~ts~n", [EMakeFile]),
StartTime = erlang:system_time(second),
{MakeOpts, CompileOpts} = splitOpts(Opts, [], []),
case readEMakefile(EMakeFile, CompileOpts) of
{ok, Files} ->
LastTime = readEMake(),
LIsAll = IsAll orelse (LastTime /= 0 andalso StartTime =< LastTime),
Ret = forMake(Files, WorkerCnt, lists:member(noexec, MakeOpts), load_opt(MakeOpts), LIsAll, IsNoHrl, []),
EndTime = erlang:system_time(second),
saveEMake(EndTime),
case Ret of
ok ->
io:format("compile over all is ok use time: ~ps IsAll:~p ~n", [EndTime - StartTime, LIsAll]);
{error, _Err} ->
io:format("compile abort why: ~p~n", [_Err])
end;
_Err ->
_Err
end.
io:format("compile start use EMakefile: ~ts~n", [EMakeFile]),
StartTime = erlang:system_time(second),
{MakeOpts, CompileOpts} = splitOpts(Opts, [], []),
LastTime = readEMake(),
LIsAll = IsAll orelse (LastTime /= 0 andalso StartTime =< LastTime),
case readEMakefile(EMakeFile, CompileOpts, LIsAll) of
{ok, Files} ->
Ret = forMake(Files, WorkerCnt, lists:member(noexec, MakeOpts), load_opt(MakeOpts), LIsAll, IsNoHrl, []),
EndTime = erlang:system_time(second),
saveEMake(EndTime),
case Ret of
ok ->
io:format("compile over all is ok use time: ~ps IsAll:~p ~n", [EndTime - StartTime, LIsAll]);
{error, _Err} ->
io:format("compile abort why: ~p~n", [_Err])
end;
_Err ->
_Err
end.
splitOpts([], Make, Compile) ->
{Make, lists:reverse(Compile)};
{Make, lists:reverse(Compile)};
splitOpts([H | T], Make, Compile) ->
case lists:member(H, ?MakeOpts) of
true ->
splitOpts(T, [H | Make], Compile);
false ->
splitOpts(T, Make, [H | Compile])
end.
case lists:member(H, ?MakeOpts) of
true ->
splitOpts(T, [H | Make], Compile);
false ->
splitOpts(T, Make, [H | Compile])
end.
%% term反序列化, string转换为term
strToTerm(String) ->
case erl_scan:string(String ++ ".") of
{ok, Tokens, _} ->
erl_parse:parse_term(Tokens);
_Err ->
{error, _Err}
end.
case erl_scan:string(String ++ ".") of
{ok, Tokens, _} ->
erl_parse:parse_term(Tokens);
_Err ->
{error, _Err}
end.
%% Any flags that are not recognixed as make flags are passed directly
%% to the compiler.
%% So for example make:all([load,debug_info]) will make everything
%% with the debug_info flag and load it.
load_opt(Opts) ->
case lists:member(netload, Opts) of
true ->
netload;
false ->
case lists:member(load, Opts) of
true ->
load;
_ ->
noload
end
end.
case lists:member(netload, Opts) of
true ->
netload;
false ->
case lists:member(load, Opts) of
true ->
load;
_ ->
noload
end
end.
%%% Emakefile [{Mods,Opts}]
%%% %%% Mods
%%% %%% Opts Mods 使
readEMakefile(EMakefile, Opts) ->
case file:consult(EMakefile) of
{ok, EMake} ->
Ret = transform(EMake, Opts, []),
erase(),
{ok, Ret};
{error, enoent} ->
%% EMakefile 使 filelib:wildcard("./**/*.erl")
Mods = [filename:rootname(F) || F <- filelib:wildcard("*.erl")],
{ok, [{Mods, Opts}]};
{error, Other} = _Err ->
io:format("the Emakefile:~s is error:~p~n", [EMakefile, Other]),
_Err
end.
transform([], _Opts, Files) ->
lists:reverse(Files);
transform([{Mod, ModOpts} | EMake], Opts, Files) ->
case expand(Mod) of
[] ->
transform(EMake, Opts, Files);
Mods ->
NewOpts = Opts ++ ModOpts,
ensureOutDir(NewOpts),
transform(EMake, Opts, [{Mods, NewOpts} | Files])
end;
transform([Mod | EMake], Opts, Files) ->
case expand(Mod) of
[] ->
transform(EMake, Opts, Files);
Mods ->
ensureOutDir(Opts),
transform(EMake, Opts, [{Mods, Opts} | Files])
end.
ensureOutDir(Opts) ->
case lists:keysearch(outdir, 1, Opts) of
{value, {outdir, OutDir}} ->
BeamDir = filename:join(OutDir, "xxx.beam"),
filelib:ensure_dir(BeamDir);
_ ->
ignore
end.
readEMakefile(EMakefile, Opts, IsAll) ->
case file:consult(EMakefile) of
{ok, EMake} ->
Ret = transform(EMake, Opts, IsAll, []),
erase(),
{ok, Ret};
{error, enoent} ->
%% EMakefile 使 filelib:wildcard("./**/*.erl")
Mods = [filename:rootname(F) || F <- filelib:wildcard("*.erl")],
{ok, [{Mods, Opts}]};
{error, Other} = _Err ->
io:format("the Emakefile:~s is error:~p~n", [EMakefile, Other]),
_Err
end.
transform([], _Opts, _IsAll, Files) ->
lists:reverse(Files);
transform([{Mod, ModOpts} | EMake], Opts, IsAll, Files) ->
case expand(Mod) of
[] ->
transform(EMake, Opts, IsAll, Files);
Mods ->
NewOpts = Opts ++ ModOpts,
ensureOutDir(NewOpts, IsAll),
transform(EMake, Opts, IsAll, [{Mods, NewOpts} | Files])
end;
transform([Mod | EMake], Opts, IsAll, Files) ->
case expand(Mod) of
[] ->
transform(EMake, Opts, IsAll, Files);
Mods ->
ensureOutDir(Opts, IsAll),
transform(EMake, Opts, IsAll, [{Mods, Opts} | Files])
end.
ensureOutDir(Opts, IsAll) ->
case lists:keysearch(outdir, 1, Opts) of
{value, {outdir, OutDir}} ->
IsAll andalso file:del_dir_r(OutDir),
code:add_path(OutDir),
filelib:ensure_dir(filename:join(OutDir, "xxx.beam"));
_ ->
ignore
end.
expand(Mod) when is_atom(Mod) ->
expand(atom_to_list(Mod));
expand(atom_to_list(Mod));
expand(Mods) when is_list(Mods), not is_integer(hd(Mods)) ->
lists:append([expand(Mod) || Mod <- Mods]);
lists:append([expand(Mod) || Mod <- Mods]);
expand(Mod) ->
case lists:member($*, Mod) of
true ->
foldErl(filelib:wildcard(Mod ++ ".erl"), []);
_ ->
M = filename:rootname(Mod, ".erl"),
case get(M) of
undefined ->
put(M, 1),
[M];
_ ->
[]
end
end.
case lists:member($*, Mod) of
true ->
foldErl(filelib:wildcard(Mod ++ ".erl"), []);
_ ->
M = filename:rootname(Mod, ".erl"),
case get(M) of
undefined ->
put(M, 1),
[M];
_ ->
[]
end
end.
foldErl([], Acc) ->
Acc;
Acc;
foldErl([OneFile | Left], Acc) ->
M = filename:rootname(OneFile),
case get(M) of
undefined ->
put(M, 1),
foldErl(Left, [M | Acc]);
_ ->
foldErl(Left, Acc)
end.
M = filename:rootname(OneFile),
case get(M) of
undefined ->
put(M, 1),
foldErl(Left, [M | Acc]);
_ ->
foldErl(Left, Acc)
end.
forMake([], _Worker, _NoExec, _Load, IsAll, IsNoHrl, AllWorkPids) ->
case AllWorkPids of
[] ->
ok;
_ ->
receive
{mOverCompile, WPid} ->
NewAllWorkPids = lists:delete(WPid, AllWorkPids),
case NewAllWorkPids of
[] ->
ok;
_ ->
forMake([], _Worker, _NoExec, _Load, IsAll, IsNoHrl, NewAllWorkPids)
end;
{mCompileError, Err} ->
errorStop(Err, AllWorkPids);
_Other ->
io:format("forMake [] receive unexpect msg:~p ~n", [_Other]),
{error, _Other}
end
end;
case AllWorkPids of
[] ->
ok;
_ ->
receive
{mOverCompile, WPid} ->
NewAllWorkPids = lists:delete(WPid, AllWorkPids),
case NewAllWorkPids of
[] ->
ok;
_ ->
forMake([], _Worker, _NoExec, _Load, IsAll, IsNoHrl, NewAllWorkPids)
end;
{mCompileError, Err} ->
errorStop(Err, AllWorkPids);
_Other ->
io:format("forMake [] receive unexpect msg:~p ~n", [_Other]),
{error, _Other}
end
end;
forMake([{Mods, Opts} | Rest], Worker, NoExec, Load, IsAll, IsNoHrl, AllWorkPids) ->
case Mods of
[] ->
forMake(Rest, Worker, NoExec, Load, IsAll, IsNoHrl, AllWorkPids);
_ ->
case Worker > 0 of
true ->
{Files, More} = splitMods(Mods),
WPid = spawn_link(?MODULE, compileWorker, [Files, Opts, self(), NoExec, Load, IsAll, IsNoHrl]),
case More of
over ->
forMake(Rest, Worker - 1, NoExec, Load, IsAll, IsNoHrl, [WPid | AllWorkPids]);
_ ->
forMake([{More, Opts} | Rest], Worker - 1, NoExec, Load, IsAll, IsNoHrl, [WPid | AllWorkPids])
end;
_ ->
receive
{mOverCompile, WPid} ->
{Files, More} = splitMods(Mods),
erlang:send(WPid, {mNewFile, Files, Opts}),
case More of
over ->
forMake(Rest, Worker, NoExec, Load, IsAll, IsNoHrl, AllWorkPids);
_ ->
forMake([{More, Opts} | Rest], Worker, NoExec, Load, IsAll, IsNoHrl, AllWorkPids)
end;
{mCompileError, Err} ->
errorStop(Err, AllWorkPids);
_Other ->
io:format("forMake xx receive unexpect msg:~p ~n", [_Other]),
{error, _Other}
end
end
end.
case Mods of
[] ->
forMake(Rest, Worker, NoExec, Load, IsAll, IsNoHrl, AllWorkPids);
_ ->
case Worker > 0 of
true ->
{Files, More} = splitMods(Mods),
WPid = spawn_link(?MODULE, compileWorker, [Files, Opts, self(), NoExec, Load, IsAll, IsNoHrl]),
case More of
over ->
forMake(Rest, Worker - 1, NoExec, Load, IsAll, IsNoHrl, [WPid | AllWorkPids]);
_ ->
forMake([{More, Opts} | Rest], Worker - 1, NoExec, Load, IsAll, IsNoHrl, [WPid | AllWorkPids])
end;
_ ->
receive
{mOverCompile, WPid} ->
{Files, More} = splitMods(Mods),
erlang:send(WPid, {mNewFile, Files, Opts}),
case More of
over ->
forMake(Rest, Worker, NoExec, Load, IsAll, IsNoHrl, AllWorkPids);
_ ->
forMake([{More, Opts} | Rest], Worker, NoExec, Load, IsAll, IsNoHrl, AllWorkPids)
end;
{mCompileError, Err} ->
errorStop(Err, AllWorkPids);
_Other ->
io:format("forMake xx receive unexpect msg:~p ~n", [_Other]),
{error, _Other}
end
end
end.
splitMods(Mods) ->
case length(Mods) =< ?OnceCnt of
true ->
{Mods, over};
_ ->
lists:split(?OnceCnt, Mods)
end.
{CurList, Index, LeftList} = splitFiles(?OnceCnt, Mods, 0, []),
case Index < ?OnceCnt of
true ->
{TCurList, _TIndex, TLeftList} = splitFiles(1, Mods, 0, []),
case TLeftList of
[] ->
{TCurList, over};
_ ->
{TCurList, TLeftList}
end;
_ ->
{CurList, LeftList}
end.
splitFiles(0, List, Index, Acc) ->
{lists:reverse(Acc), Index, List};
splitFiles(_Cnt, [], Index, Acc) ->
{lists:reverse(Acc), Index, []};
splitFiles(Cnt, [H | T], Index, R) ->
splitFiles(Cnt - 1, T, Index + 1, [H | R]).
errorStop(Err, AllWorkPids) ->
[exit(OnePid, kill) || OnePid <- AllWorkPids],
case Err of
{File, Errors, Warnings} ->
io:format("the file:~ts compile error:~p wrar:~p ~n", [File, Errors, Warnings]);
File ->
io:format("the file:~ts compile error please check ~n", [File])
end,
{error, compile_error}.
[exit(OnePid, kill) || OnePid <- AllWorkPids],
case Err of
{File, Errors, Warnings} ->
io:format("the file:~ts compile error:~p wrar:~p ~n", [File, Errors, Warnings]);
File ->
io:format("the file:~ts compile error please check ~n", [File])
end,
{error, compile_error}.
compileWorker(Files, Opts, Parent, NoExec, Load, IsAll, IsNoHrl) ->
compileWork(Files, Opts, Parent, NoExec, Load, IsAll, IsNoHrl).
compileWork(Files, Opts, Parent, NoExec, Load, IsAll, IsNoHrl).
compileWork([], _Opts, Parent, NoExec, Load, IsAll, IsNoHrl) ->
erlang:send(Parent, {mOverCompile, self()}),
receive
{mNewFile, Files, Opts} ->
compileWork(Files, Opts, Parent, NoExec, Load, IsAll, IsNoHrl);
_Other ->
io:format("compileWorker [] receive unexpect msg:~p ~n", [_Other])
end;
erlang:send(Parent, {mOverCompile, self()}),
receive
{mNewFile, Files, Opts} ->
compileWork(Files, Opts, Parent, NoExec, Load, IsAll, IsNoHrl);
_Other ->
io:format("compileWorker [] receive unexpect msg:~p ~n", [_Other])
end;
compileWork([OneFile | Files], Opts, Parent, NoExec, Load, IsAll, IsNoHrl) ->
case tryCompile(coerce_2_list(OneFile), NoExec, Load, IsAll, IsNoHrl, Opts) of
error ->
Parent ! {mCompileError, OneFile},
exit(error);
{error, Errors, Warnings} ->
Parent ! {mCompileError, {OneFile, Errors, Warnings}},
exit(error);
_ ->
compileWork(Files, Opts, Parent, NoExec, Load, IsAll, IsNoHrl)
end.
case tryCompile(coerce_2_list(OneFile), NoExec, Load, IsAll, IsNoHrl, Opts) of
error ->
Parent ! {mCompileError, OneFile},
exit(error);
{error, Errors, Warnings} ->
Parent ! {mCompileError, {OneFile, Errors, Warnings}},
exit(error);
_ ->
compileWork(Files, Opts, Parent, NoExec, Load, IsAll, IsNoHrl)
end.
tryCompile(File, NoExec, Load, IsAll, IsNoHrl, Opts) ->
case IsAll of
false ->
ObjName = lists:append(filename:basename(File), code:objfile_extension()),
ObjFile =
case lists:keysearch(outdir, 1, Opts) of
{value, {outdir, OutDir}} ->
filename:join(coerce_2_list(OutDir), ObjName);
false ->
ObjName
end,
case exists(ObjFile) of
true ->
reCompile(File, NoExec, Load, Opts, ObjFile, IsNoHrl);
false ->
doCompile(File, NoExec, Load, Opts)
end;
_ ->
doCompile(File, NoExec, Load, Opts)
end.
case IsAll of
false ->
ObjName = lists:append(filename:basename(File), code:objfile_extension()),
ObjFile =
case lists:keysearch(outdir, 1, Opts) of
{value, {outdir, OutDir}} ->
filename:join(coerce_2_list(OutDir), ObjName);
false ->
ObjName
end,
case exists(ObjFile) of
true ->
reCompile(File, NoExec, Load, Opts, ObjFile, IsNoHrl);
false ->
doCompile(File, NoExec, Load, Opts)
end;
_ ->
doCompile(File, NoExec, Load, Opts)
end.
reCompile(File, NoExec, Load, Opts, ObjFile, IsNoHrl) ->
{ok, #file_info{mtime = SrcTime}} = file:read_file_info(lists:append(File, ".erl")),
{ok, #file_info{mtime = ObjTime}} = file:read_file_info(ObjFile),
case SrcTime > ObjTime of
true ->
doCompile(File, NoExec, Load, Opts);
_ ->
IsNoHrl /= true andalso ckIncludeRecompile(ObjTime, File, NoExec, Load, Opts)
end.
{ok, #file_info{mtime = SrcTime}} = file:read_file_info(lists:append(File, ".erl")),
{ok, #file_info{mtime = ObjTime}} = file:read_file_info(ObjFile),
case SrcTime > ObjTime of
true ->
doCompile(File, NoExec, Load, Opts);
_ ->
IsNoHrl /= true andalso ckIncludeRecompile(ObjTime, File, NoExec, Load, Opts)
end.
%% recompile2(ObjMTime, File, NoExec, Load, Opts)
%% Check if file is of a later date than include files.
ckIncludeRecompile(ObjMTime, File, NoExec, Load, Opts) ->
IncludePath = include_opt(Opts),
case check_includes(lists:append(File, ".erl"), IncludePath, ObjMTime) of
true ->
doCompile(File, NoExec, Load, Opts);
false ->
false
end.
IncludePath = include_opt(Opts),
case check_includes(lists:append(File, ".erl"), IncludePath, ObjMTime) of
true ->
doCompile(File, NoExec, Load, Opts);
false ->
false
end.
include_opt([{i, Path} | Rest]) ->
[Path | include_opt(Rest)];
[Path | include_opt(Rest)];
include_opt([_First | Rest]) ->
include_opt(Rest);
include_opt(Rest);
include_opt([]) ->
[].
[].
%% recompile(File, NoExec, Load, Opts)
%% Actually recompile and load the file, depending on the flags.
%% Where load can be netload | load | noload
doCompile(File, true, _Load, _Opts) ->
io:format("Out of date: ~ts\n", [File]);
io:format("Out of date: ~ts\n", [File]);
doCompile(File, false, noload, Opts) ->
% io:format("Recompile: ~ts\n", [File]),
compile:file(File, [report_errors, report_warnings, error_summary | Opts]);
% io:format("Recompile: ~ts\n", [File]),
compile:file(File, [report_errors, report_warnings, error_summary | Opts]);
doCompile(File, false, load, Opts) ->
% io:format("Recompile: ~ts\n", [File]),
c:c(File, Opts);
% io:format("Recompile: ~ts\n", [File]),
c:c(File, Opts);
doCompile(File, false, netload, Opts) ->
% io:format("Recompile: ~ts\n", [File]),
c:nc(File, Opts).
% io:format("Recompile: ~ts\n", [File]),
c:nc(File, Opts).
exists(File) ->
case file:read_file_info(File) of
{ok, _} ->
true;
_ ->
false
end.
case file:read_file_info(File) of
{ok, _} ->
true;
_ ->
false
end.
coerce_2_list(X) when is_atom(X) ->
atom_to_list(X);
atom_to_list(X);
coerce_2_list(X) ->
X.
X.
%%% If you an include file is found with a modification
%%% time larger than the modification time of the object
%%% file, return true. Otherwise return false.
check_includes(File, IncludePath, ObjMTime) ->
Path = [filename:dirname(File) | IncludePath],
case epp:open(File, Path, []) of
{ok, Epp} ->
check_includes2(Epp, File, ObjMTime);
_Error ->
false
end.
Path = [filename:dirname(File) | IncludePath],
case epp:open(File, Path, []) of
{ok, Epp} ->
check_includes2(Epp, File, ObjMTime);
_Error ->
false
end.
check_includes2(Epp, File, ObjMTime) ->
case epp:parse_erl_form(Epp) of
{ok, {attribute, 1, file, {File, 1}}} ->
check_includes2(Epp, File, ObjMTime);
{ok, {attribute, 1, file, {IncFile, 1}}} ->
case file:read_file_info(IncFile) of
{ok, #file_info{mtime = MTime}} when MTime > ObjMTime ->
epp:close(Epp),
true;
_ ->
check_includes2(Epp, File, ObjMTime)
end;
{ok, _} ->
check_includes2(Epp, File, ObjMTime);
{eof, _} ->
epp:close(Epp),
false;
{error, _Error} ->
check_includes2(Epp, File, ObjMTime);
{warning, _Warning} ->
check_includes2(Epp, File, ObjMTime)
end.
case epp:parse_erl_form(Epp) of
{ok, {attribute, 1, file, {File, 1}}} ->
check_includes2(Epp, File, ObjMTime);
{ok, {attribute, 1, file, {IncFile, 1}}} ->
case file:read_file_info(IncFile) of
{ok, #file_info{mtime = MTime}} when MTime > ObjMTime ->
epp:close(Epp),
true;
_ ->
check_includes2(Epp, File, ObjMTime)
end;
{ok, _} ->
check_includes2(Epp, File, ObjMTime);
{eof, _} ->
epp:close(Epp),
false;
{error, _Error} ->
check_includes2(Epp, File, ObjMTime);
{warning, _Warning} ->
check_includes2(Epp, File, ObjMTime)
end.

불러오는 중...
취소
저장