From 1fa659b5b340fdc7926e657c608b4454efa16ee5 Mon Sep 17 00:00:00 2001 From: Bryan Fink Date: Mon, 21 Dec 2009 12:15:21 -0500 Subject: [PATCH] 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 --- src/rebar_erlc_compiler.erl | 84 +++++++++++++++++++++++++++---------- src/rebar_eunit.erl | 2 +- src/rebar_lfe_compiler.erl | 2 +- 3 files changed, 64 insertions(+), 24 deletions(-) diff --git a/src/rebar_erlc_compiler.erl b/src/rebar_erlc_compiler.erl index 80371ad..661b8db 100644 --- a/src/rebar_erlc_compiler.erl +++ b/src/rebar_erlc_compiler.erl @@ -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 -> diff --git a/src/rebar_eunit.erl b/src/rebar_eunit.erl index 162a692..574054b 100644 --- a/src/rebar_eunit.erl +++ b/src/rebar_eunit.erl @@ -51,7 +51,7 @@ eunit(Config, _File) -> %% Compile all erlang from src/ into ?EUNIT_DIR 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, [])), %% Build a list of all the .beams in ?EUNIT_DIR -- use this for cover diff --git a/src/rebar_lfe_compiler.erl b/src/rebar_lfe_compiler.erl index cc2cde5..3776164 100644 --- a/src/rebar_lfe_compiler.erl +++ b/src/rebar_lfe_compiler.erl @@ -37,7 +37,7 @@ compile(Config, _AppFile) -> FirstFiles = rebar_config:get_list(Config, lfe_first_files, []), rebar_erlc_compiler:do_compile(Config, "src/*.lfe", "ebin", ".lfe", ".beam", - fun compile_lfe/2, FirstFiles). + undefined, fun compile_lfe/2, FirstFiles). %% ===================================================================