recompile files if their "includes" have changed

added parameter to do_compile for passing a function that can extra the list of includes from a file
This commit is contained in:
Bryan Fink 2009-12-21 12:15:21 -05:00
parent a0b665360a
commit 1fa659b5b3
3 changed files with 64 additions and 24 deletions

View file

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

View file

@ -51,7 +51,7 @@ eunit(Config, _File) ->
%% Compile all erlang from src/ into ?EUNIT_DIR %% Compile all erlang from src/ into ?EUNIT_DIR
rebar_erlc_compiler:do_compile(Config, "src/*.erl", ?EUNIT_DIR, ".erl", ".beam", rebar_erlc_compiler:do_compile(Config, "src/*.erl", ?EUNIT_DIR, ".erl", ".beam",
fun compile_erl/2, undefined, fun compile_erl/2,
rebar_config:get_list(Config, erl_first_files, [])), rebar_config:get_list(Config, erl_first_files, [])),
%% Build a list of all the .beams in ?EUNIT_DIR -- use this for cover %% Build a list of all the .beams in ?EUNIT_DIR -- use this for cover

View file

@ -37,7 +37,7 @@
compile(Config, _AppFile) -> compile(Config, _AppFile) ->
FirstFiles = rebar_config:get_list(Config, lfe_first_files, []), FirstFiles = rebar_config:get_list(Config, lfe_first_files, []),
rebar_erlc_compiler:do_compile(Config, "src/*.lfe", "ebin", ".lfe", ".beam", rebar_erlc_compiler:do_compile(Config, "src/*.lfe", "ebin", ".lfe", ".beam",
fun compile_lfe/2, FirstFiles). undefined, fun compile_lfe/2, FirstFiles).
%% =================================================================== %% ===================================================================