diff options
author | Dave Smith <dizzyd@dizzyd.com> | 2010-01-02 14:17:59 -0700 |
---|---|---|
committer | Dave Smith <dizzyd@dizzyd.com> | 2010-01-02 14:17:59 -0700 |
commit | 9c15d63191695a8121cb5566817ed2123c59567b (patch) | |
tree | daaae1391c29f7b50d214b203ba183d684b16d88 /src/rebar_erlc_compiler.erl | |
parent | 18e1b37e6f1e81325e8ce8167a639b521a8f4726 (diff) |
Refactor of compilation logic to enable support for package modules and provide better modularity/reusability for other systems
Diffstat (limited to 'src/rebar_erlc_compiler.erl')
-rw-r--r-- | src/rebar_erlc_compiler.erl | 186 |
1 files changed, 44 insertions, 142 deletions
diff --git a/src/rebar_erlc_compiler.erl b/src/rebar_erlc_compiler.erl index 68b1d75..4e083ab 100644 --- a/src/rebar_erlc_compiler.erl +++ b/src/rebar_erlc_compiler.erl @@ -30,7 +30,7 @@ clean/2]). %% make available for rebar_eunit until there is a better option --export([do_compile/8, compile_opts/2, list_hrls/2]). +-export([hrls_check/3]). -include("rebar.hrl"). @@ -39,18 +39,30 @@ %% =================================================================== compile(Config, _AppFile) -> - do_compile(Config, "src/*.erl", "ebin", ".erl", ".beam", - 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", - undefined, fun compile_mib/2, - rebar_config:get_list(Config, mib_first_files, [])). + rebar_base_compiler:run(Config, "src", ".erl", "ebin", ".beam", + rebar_config:get_list(Config, erl_first_files, []), + fun compile_erl/3, + [recurse_source_dir, + {needs_compile_checks, [fun hrls_check/3]}]), + + rebar_base_compiler:run(Config, "mibs", ".mib", "priv/mibs", ".bin", + rebar_config:get_list(Config, mib_first_files, []), + fun compile_mib/3, + []). clean(_Config, _AppFile) -> %% TODO: This would be more portable if it used Erlang to traverse %% the dir structure and delete each file; however it would also %% much slower. - [] = os:cmd("rm -f ebin/*.beam priv/mibs/*.bin"), + ok = rebar_file_utils:rm_rf("ebin/*.beam priv/mibs/*.bin"), + + %% Erlang compilation is recursive, so it's possible that we have a nested + %% directory structure in ebin with .beam files within. As such, we want + %% to scan whatever is left in the ebin/ directory for sub-dirs which + %% satisfy our criteria. TODO: Is there a better way to do this? + BeamFiles = filelib:fold_files("ebin", "^.*\\.beam\$", true, + fun(F, BeamFiles) -> BeamFiles ++ [F] end, []), + rebar_file_utils:delete_each(BeamFiles), ok. @@ -59,71 +71,11 @@ clean(_Config, _AppFile) -> %% Internal functions %% =================================================================== -do_compile(Config, SrcWildcard, OutDir, InExt, OutExt, - IncludeFn, CompileFn, FirstFiles) -> - case filelib:wildcard(SrcWildcard) of - [] -> - ok; - FoundFiles when is_list(FoundFiles) -> - %% Ensure that the FirstFiles are compiled first; drop them from the - %% FoundFiles and compile them in sequence - FirstTargets = [{Fs, target_file(Fs, OutDir, InExt, OutExt)} || Fs <- FirstFiles], - RestTargets = [{Fs, target_file(Fs, OutDir, InExt, OutExt)} || - Fs <- drop_each(FirstFiles, FoundFiles)], - - %% Make sure target directory exists - ok = filelib:ensure_dir(target_file(hd(FoundFiles), OutDir, InExt, OutExt)), - - %% Compile first targets in sequence - 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, IncludeFn, CompileFn) - end. - -drop_each([], List) -> - List; -drop_each([Member | Rest], List) -> - drop_each(Rest, lists:delete(Member, List)). - -compile_each([], _Config, _IncludeFn, _CompileFn) -> - ok; -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); - false -> - ?INFO("Skipping ~s\n", [Src]), - ok - end, - compile_each(Rest, Config, IncludeFn, CompileFn). - -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. +hrls_check(Source, Target, Config) -> + TargetLastMod = filelib:last_modified(Target), + lists:any(fun(I) -> TargetLastMod < filelib:last_modified(I) end, + list_hrls(Source, Config)). -target_file(F, TargetDir, InExt, OutExt) -> - filename:join([TargetDir, filename:basename(F, 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 @@ -134,26 +86,31 @@ list_hrls(Src, Config) -> 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}}} -> + {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) + {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), +include_path(Source, Config) -> + [filename:dirname(Source) | compile_opts(Config, i)]. + +compile_opts(Config, Key) -> + rebar_config:get_list(Config, Key, []). + +compile_erl(Source, Target, Config) -> + Opts = [{i, "include"}, {outdir, filename:dirname(Target)}, report, return] ++ + compile_opts(Config, erl_opts), case compile:file(Source, Opts) of {ok, _, []} -> ok; @@ -169,7 +126,7 @@ compile_erl(Source, Config) -> ?FAIL end. -compile_mib(Source, Config) -> +compile_mib(Source, _Target, Config) -> Opts = [{outdir, "priv/mibs"}, {i, ["priv/mibs"]}] ++ compile_opts(Config, mib_opts), case snmpc:compile(Source, Opts) of {ok, _} -> @@ -177,58 +134,3 @@ compile_mib(Source, Config) -> {error, compilation_failed} -> ?FAIL end. - -compile_queue([], [], _Config, _IncludeFn, _CompileFn) -> - ok; -compile_queue(Pids, Targets, Config, IncludeFn, CompileFn) -> - receive - {next, Worker} -> - case Targets of - [] -> - Worker ! empty, - compile_queue(Pids, Targets, Config, IncludeFn, CompileFn); - [{Src, Target} | Rest] -> - Worker ! {compile, Src, Target, Config, IncludeFn, CompileFn}, - compile_queue(Pids, Rest, Config, IncludeFn, CompileFn) - end; - - {fail, Error} -> - ?DEBUG("Worker compilation failed: ~p\n", [Error]), - ?FAIL; - - {compiled, Source} -> - ?CONSOLE("Compiled ~s\n", [Source]), - 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, IncludeFn, CompileFn); - - {'DOWN', _Mref, _, _Pid, Info} -> - ?DEBUG("Worker failed: ~p\n", [Info]), - ?FAIL - end. - -compile_worker(QueuePid) -> - QueuePid ! {next, self()}, - receive - {compile, Src, Target, Config, IncludeFn, CompileFn} -> - case needs_compile(Src, Target, IncludeFn, Config) of - true -> - case catch(CompileFn(Src, Config)) of - ok -> - QueuePid ! {compiled, Src}, - compile_worker(QueuePid); - Error -> - QueuePid ! {fail, Error}, - ok - end; - false -> - ?INFO("Skipping ~s\n", [Src]), - compile_worker(QueuePid) - end; - - empty -> - ok - end. |