|
|
@ -28,7 +28,7 @@ |
|
|
|
clean/2]). |
|
|
|
|
|
|
|
%% make available for rebar_eunit until there is a better option |
|
|
|
-export([do_compile/7, compile_opts/2]). |
|
|
|
-export([do_compile/8, compile_opts/2]). |
|
|
|
|
|
|
|
-include("rebar.hrl"). |
|
|
|
|
|
|
@ -38,10 +38,10 @@ |
|
|
|
|
|
|
|
compile(Config, _AppFile) -> |
|
|
|
do_compile(Config, "src/*.erl", "ebin", ".erl", ".beam", |
|
|
|
fun compile_erl/2, |
|
|
|
fun list_hrls/2, fun compile_erl/2, |
|
|
|
rebar_config:get_list(Config, erl_first_files, [])), |
|
|
|
do_compile(Config, "mibs/*.mib", "priv/mibs", ".mib", ".bin", |
|
|
|
fun compile_mib/2, |
|
|
|
undefined, fun compile_mib/2, |
|
|
|
rebar_config:get_list(Config, mib_first_files, [])). |
|
|
|
|
|
|
|
clean(_Config, _AppFile) -> |
|
|
@ -57,7 +57,8 @@ clean(_Config, _AppFile) -> |
|
|
|
%% Internal functions |
|
|
|
%% =================================================================== |
|
|
|
|
|
|
|
do_compile(Config, SrcWildcard, OutDir, InExt, OutExt, CompileFn, FirstFiles) -> |
|
|
|
do_compile(Config, SrcWildcard, OutDir, InExt, OutExt, |
|
|
|
IncludeFn, CompileFn, FirstFiles) -> |
|
|
|
case filelib:wildcard(SrcWildcard) of |
|
|
|
[] -> |
|
|
|
ok; |
|
|
@ -72,14 +73,14 @@ do_compile(Config, SrcWildcard, OutDir, InExt, OutExt, CompileFn, FirstFiles) -> |
|
|
|
ok = filelib:ensure_dir(target_file(hd(FoundFiles), OutDir, InExt, OutExt)), |
|
|
|
|
|
|
|
%% Compile first targets in sequence |
|
|
|
compile_each(FirstTargets, Config, CompileFn), |
|
|
|
compile_each(FirstTargets, Config, IncludeFn, CompileFn), |
|
|
|
|
|
|
|
%% Spin up workers |
|
|
|
Self = self(), |
|
|
|
Pids = [spawn_monitor(fun() -> compile_worker(Self) end) || _I <- lists:seq(1,3)], |
|
|
|
|
|
|
|
%% Process rest of targets |
|
|
|
compile_queue(Pids, RestTargets, Config, CompileFn) |
|
|
|
compile_queue(Pids, RestTargets, Config, IncludeFn, CompileFn) |
|
|
|
end. |
|
|
|
|
|
|
|
drop_each([], List) -> |
|
|
@ -87,10 +88,10 @@ drop_each([], List) -> |
|
|
|
drop_each([Member | Rest], List) -> |
|
|
|
drop_each(Rest, lists:delete(Member, List)). |
|
|
|
|
|
|
|
compile_each([], _Config, _CompileFn) -> |
|
|
|
compile_each([], _Config, _IncludeFn, _CompileFn) -> |
|
|
|
ok; |
|
|
|
compile_each([{Src, Target} | Rest], Config, CompileFn) -> |
|
|
|
case needs_compile(Src, Target) of |
|
|
|
compile_each([{Src, Target} | Rest], Config, IncludeFn, CompileFn) -> |
|
|
|
case needs_compile(Src, Target, IncludeFn, Config) of |
|
|
|
true -> |
|
|
|
?CONSOLE("Compiling ~s\n", [Src]), |
|
|
|
CompileFn(Src, Config); |
|
|
@ -98,11 +99,23 @@ compile_each([{Src, Target} | Rest], Config, CompileFn) -> |
|
|
|
?INFO("Skipping ~s\n", [Src]), |
|
|
|
ok |
|
|
|
end, |
|
|
|
compile_each(Rest, Config, CompileFn). |
|
|
|
compile_each(Rest, Config, IncludeFn, CompileFn). |
|
|
|
|
|
|
|
needs_compile(Src, Target) -> |
|
|
|
filelib:last_modified(Target) < filelib:last_modified(Src). |
|
|
|
|
|
|
|
needs_compile(Src, Target, IncludeFn, Config) -> |
|
|
|
TargetLM = filelib:last_modified(Target), |
|
|
|
case TargetLM < filelib:last_modified(Src) of |
|
|
|
true -> |
|
|
|
true; |
|
|
|
false -> |
|
|
|
if is_function(IncludeFn) -> |
|
|
|
lists:any(fun(I) -> |
|
|
|
TargetLM < filelib:last_modified(I) |
|
|
|
end, |
|
|
|
IncludeFn(Src, Config)); |
|
|
|
true -> |
|
|
|
false |
|
|
|
end |
|
|
|
end. |
|
|
|
|
|
|
|
target_file(F, TargetDir, InExt, OutExt) -> |
|
|
|
filename:join([TargetDir, filename:basename(F, InExt) ++ OutExt]). |
|
|
@ -110,6 +123,33 @@ target_file(F, TargetDir, InExt, OutExt) -> |
|
|
|
compile_opts(Config, Key) -> |
|
|
|
rebar_config:get_list(Config, Key, []). |
|
|
|
|
|
|
|
list_hrls(Src, Config) -> |
|
|
|
case epp:open(Src, include_path(Src, Config)) of |
|
|
|
{ok, Epp} -> |
|
|
|
%% check include for erlang files |
|
|
|
extract_includes(Epp, Src); |
|
|
|
_ -> |
|
|
|
false |
|
|
|
end. |
|
|
|
|
|
|
|
include_path(Src, Config) -> |
|
|
|
[filename:dirname(Src)|compile_opts(Config, i)]. |
|
|
|
|
|
|
|
extract_includes(Epp, Src) -> |
|
|
|
case epp:parse_erl_form(Epp) of |
|
|
|
{ok, {attribute, 1, file, {Src, 1}}} -> |
|
|
|
extract_includes(Epp, Src); |
|
|
|
{ok, {attribute, 1, file, {IncFile, 1}}} -> |
|
|
|
[IncFile|extract_includes(Epp, Src)]; |
|
|
|
{ok, _} -> |
|
|
|
extract_includes(Epp, Src); |
|
|
|
{eof, _} -> |
|
|
|
epp:close(Epp), |
|
|
|
[]; |
|
|
|
{error, _Error} -> |
|
|
|
extract_includes(Epp, Src) |
|
|
|
end. |
|
|
|
|
|
|
|
compile_erl(Source, Config) -> |
|
|
|
Opts = [{i, "include"}, {outdir, "ebin"}, report, return] ++ compile_opts(Config, erl_opts), |
|
|
|
case compile:file(Source, Opts) of |
|
|
@ -136,18 +176,18 @@ compile_mib(Source, Config) -> |
|
|
|
?FAIL |
|
|
|
end. |
|
|
|
|
|
|
|
compile_queue([], [], _Config, _CompileFn) -> |
|
|
|
compile_queue([], [], _Config, _IncludeFn, _CompileFn) -> |
|
|
|
ok; |
|
|
|
compile_queue(Pids, Targets, Config, CompileFn) -> |
|
|
|
compile_queue(Pids, Targets, Config, IncludeFn, CompileFn) -> |
|
|
|
receive |
|
|
|
{next, Worker} -> |
|
|
|
case Targets of |
|
|
|
[] -> |
|
|
|
Worker ! empty, |
|
|
|
compile_queue(Pids, Targets, Config, CompileFn); |
|
|
|
compile_queue(Pids, Targets, Config, IncludeFn, CompileFn); |
|
|
|
[{Src, Target} | Rest] -> |
|
|
|
Worker ! {compile, Src, Target, Config, CompileFn}, |
|
|
|
compile_queue(Pids, Rest, Config, CompileFn) |
|
|
|
Worker ! {compile, Src, Target, Config, IncludeFn, CompileFn}, |
|
|
|
compile_queue(Pids, Rest, Config, IncludeFn, CompileFn) |
|
|
|
end; |
|
|
|
|
|
|
|
{fail, Error} -> |
|
|
@ -156,12 +196,12 @@ compile_queue(Pids, Targets, Config, CompileFn) -> |
|
|
|
|
|
|
|
{compiled, Source} -> |
|
|
|
?CONSOLE("Compiled ~s\n", [Source]), |
|
|
|
compile_queue(Pids, Targets, Config, CompileFn); |
|
|
|
compile_queue(Pids, Targets, Config, IncludeFn, CompileFn); |
|
|
|
|
|
|
|
{'DOWN', Mref, _, Pid, normal} -> |
|
|
|
?DEBUG("Worker exited cleanly\n", []), |
|
|
|
Pids2 = lists:delete({Pid, Mref}, Pids), |
|
|
|
compile_queue(Pids2, Targets, Config, CompileFn); |
|
|
|
compile_queue(Pids2, Targets, Config, IncludeFn, CompileFn); |
|
|
|
|
|
|
|
{'DOWN', _Mref, _, _Pid, Info} -> |
|
|
|
?DEBUG("Worker failed: ~p\n", [Info]), |
|
|
@ -171,8 +211,8 @@ compile_queue(Pids, Targets, Config, CompileFn) -> |
|
|
|
compile_worker(QueuePid) -> |
|
|
|
QueuePid ! {next, self()}, |
|
|
|
receive |
|
|
|
{compile, Src, Target, Config, CompileFn} -> |
|
|
|
case needs_compile(Src, Target) of |
|
|
|
{compile, Src, Target, Config, IncludeFn, CompileFn} -> |
|
|
|
case needs_compile(Src, Target, IncludeFn, Config) of |
|
|
|
true -> |
|
|
|
case catch(CompileFn(Src, Config)) of |
|
|
|
ok -> |
|
|
|