summaryrefslogtreecommitdiff
path: root/src/rebar_erlc_compiler.erl
diff options
context:
space:
mode:
authorDave Smith <dizzyd@dizzyd.com>2010-01-03 22:53:04 -0700
committerDave Smith <dizzyd@dizzyd.com>2010-01-03 22:53:04 -0700
commitfa2a58261ada42798a393a9283fe79a8ca25f365 (patch)
treeba74515174b3114736c0ea3c153fc9bb318e36b1 /src/rebar_erlc_compiler.erl
parent9c15d63191695a8121cb5566817ed2123c59567b (diff)
Another round of refactoring to yield better flexiblity in the base_compiler system
Diffstat (limited to 'src/rebar_erlc_compiler.erl')
-rw-r--r--src/rebar_erlc_compiler.erl134
1 files changed, 79 insertions, 55 deletions
diff --git a/src/rebar_erlc_compiler.erl b/src/rebar_erlc_compiler.erl
index 4e083ab..ee51cd0 100644
--- a/src/rebar_erlc_compiler.erl
+++ b/src/rebar_erlc_compiler.erl
@@ -29,8 +29,7 @@
-export([compile/2,
clean/2]).
- %% make available for rebar_eunit until there is a better option
--export([hrls_check/3]).
+-export([doterl_compile/2]).
-include("rebar.hrl").
@@ -39,16 +38,10 @@
%% ===================================================================
compile(Config, _AppFile) ->
- 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,
- []).
+ doterl_compile(Config, "ebin"),
+ rebar_base_compiler:run(Config, rebar_config:get_list(Config, mib_first_files, []),
+ "mibs", ".mib", "priv/mibs", ".bin",
+ fun compile_mib/3).
clean(_Config, _AppFile) ->
%% TODO: This would be more portable if it used Erlang to traverse
@@ -68,66 +61,97 @@ clean(_Config, _AppFile) ->
%% ===================================================================
-%% Internal functions
+%% .erl Compilation API (externally used by only eunit)
%% ===================================================================
-hrls_check(Source, Target, Config) ->
- TargetLastMod = filelib:last_modified(Target),
- lists:any(fun(I) -> TargetLastMod < filelib:last_modified(I) end,
- list_hrls(Source, Config)).
+doterl_compile(Config, Outdir) ->
+ FirstErls = rebar_config:get_list(Config, erl_first_files, []),
+ RestErls = [Source || Source <- rebar_utils:find_files("src", ".*.erl"),
+ lists:member(Source, FirstErls) == false],
+ rebar_base_compiler:run(Config, FirstErls, RestErls,
+ fun(S, C) -> internal_erl_compile(S, C, Outdir) end).
-list_hrls(Src, Config) ->
- case epp:open(Src, include_path(Src, Config)) of
+%% ===================================================================
+%% Internal functions
+%% ===================================================================
+
+include_path(Source, Config) ->
+ ErlOpts = rebar_config:get(Config, erl_opts, []),
+ [filename:dirname(Source)] ++ proplists:get_all_values(i, ErlOpts).
+
+inspect(Source, IncludePath) ->
+ ModuleDefault = filename:basename(Source, ".erl"),
+ case epp:open(Source, IncludePath) of
{ok, Epp} ->
- %% check include for erlang files
- extract_includes(Epp, Src);
- _ ->
- false
+ inspect_epp(Epp, ModuleDefault, []);
+ {error, Reason} ->
+ ?DEBUG("Failed to inspect ~s: ~p\n", [Source, Reason]),
+ {ModuleDefault, []}
end.
-
-extract_includes(Epp, Src) ->
+inspect_epp(Epp, Module, Includes) ->
case epp:parse_erl_form(Epp) of
- {ok, {attribute, 1, file, {Src, 1}}} ->
- extract_includes(Epp, Src);
+ {ok, {attribute, _, module, ActualModule}} when is_list(ActualModule) ->
+ %% If the module name includes package info, we get a list of atoms...
+ case is_list(ActualModule) of
+ true ->
+ ActualModuleStr = string:join([atom_to_list(P) || P <- ActualModule], ".");
+ false ->
+ ActualModuleStr = atom_to_list(ActualModule)
+ end,
+ inspect_epp(Epp, ActualModuleStr, Includes);
+ {ok, {attribute, 1, file, {Module, 1}}} ->
+ inspect_epp(Epp, Module, Includes);
{ok, {attribute, 1, file, {IncFile, 1}}} ->
- [IncFile|extract_includes(Epp, Src)];
- {ok, _} ->
- extract_includes(Epp, Src);
+ inspect_epp(Epp, Module, [IncFile | Includes]);
{eof, _} ->
epp:close(Epp),
- [];
- {error, _Error} ->
- extract_includes(Epp, Src)
+ {Module, Includes};
+ _ ->
+ inspect_epp(Epp, Module, Includes)
end.
-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;
- {ok, _, _Warnings} ->
- %% We got at least one warning -- if fail_on_warning is in options, fail
- case lists:member(fail_on_warning, Opts) of
- true ->
- ?FAIL;
- false ->
- ok
+needs_compile(Source, Target, Hrls) ->
+ TargetLastMod = filelib:last_modified(Target),
+ lists:any(fun(I) -> TargetLastMod < filelib:last_modified(I) end,
+ [Source] ++ Hrls).
+
+
+internal_erl_compile(Source, Config, Outdir) ->
+ %% Determine the target name and includes list by inspecting the source file
+ {Module, Hrls} = inspect(Source, include_path(Source, Config)),
+
+ %% Construct the target filename
+ Target = filename:join([Outdir | string:tokens(Module, ".")]) ++ ".beam",
+
+ %% If the file needs compilation, based on last mod date of includes or
+ %% the target,
+ case needs_compile(Source, Target, Hrls) of
+ true ->
+ Opts = [{i, "include"}, {outdir, filename:dirname(Target)}, report, return] ++
+ rebar_config:get(Config, erl_opts, []),
+ case compile:file(Source, Opts) of
+ {ok, _, []} ->
+ ok;
+ {ok, _, _Warnings} ->
+ %% We got at least one warning -- if fail_on_warning is in options, fail
+ case lists:member(fail_on_warning, Opts) of
+ true ->
+ ?FAIL;
+ false ->
+ ok
+ end;
+ _ ->
+ ?FAIL
end;
- _ ->
- ?FAIL
+ false ->
+ skipped
end.
compile_mib(Source, _Target, Config) ->
- Opts = [{outdir, "priv/mibs"}, {i, ["priv/mibs"]}] ++ compile_opts(Config, mib_opts),
+ Opts = [{outdir, "priv/mibs"}, {i, ["priv/mibs"]}] ++
+ rebar_config:get(Config, mib_opts, []),
case snmpc:compile(Source, Opts) of
{ok, _} ->
ok;