Make the base compiler accept target file names

The rebar_base_compiler:run/5 is an alternative to run/8, where
instead of source/target dirs and file name extensions, it takes
a list of tuples: [{SourceFileName, TargetFileName}], after the
idea by Tuncer Ayaz in discussion with Luis Rascão and me.

This is useful for situations where the target file name cannot be
expressed as only a new suffix or extension.  For example the gpb
protocol buffer compiler can take an option to add a file name prefix
as well as a suffix.

As a result, the values passed around inside the internal functions in
rebar_base_compiler are either source file names (eg. when the run/4
function has been called), or items, which are two-tuples
{SourceFileName,TargetFileName} (when the run/7,8 or /5 functions have
been called).
This commit is contained in:
Tomas Abrahamsson 2015-01-03 08:14:16 +01:00
parent 135e629bc0
commit 2e9706fd61

View file

@ -31,6 +31,7 @@
-export([run/4, -export([run/4,
run/7, run/7,
run/8, run/8,
run/5,
ok_tuple/3, ok_tuple/3,
error_tuple/5]). error_tuple/5]).
@ -62,23 +63,31 @@ run(Config, FirstFiles, SourceDir, SourceExt, TargetDir, TargetExt,
run(Config, FirstFiles, SourceDir, SourceExt, TargetDir, TargetExt, run(Config, FirstFiles, SourceDir, SourceExt, TargetDir, TargetExt,
Compile3Fn, Opts) -> Compile3Fn, Opts) ->
%% Convert simple extension to proper regex
SourceExtRe = "^[^._].*\\" ++ SourceExt ++ [$$],
Recursive = proplists:get_value(recursive, Opts, true),
%% Find all possible source files %% Find all possible source files
FoundFiles = rebar_utils:find_files(SourceDir, SourceExtRe, Recursive), Recursive = proplists:get_value(recursive, Opts, true),
FoundFiles = rebar_utils:find_files_by_ext(SourceDir, SourceExt, Recursive),
%% Remove first files from found files %% Remove first files from found files
RestFiles = [Source || Source <- FoundFiles, RestFiles = [Source || Source <- FoundFiles,
not lists:member(Source, FirstFiles)], not lists:member(Source, FirstFiles)],
FirstUnits = source_to_unit_each(FirstFiles,
SourceDir, SourceExt,
TargetDir, TargetExt),
RestUnits = source_to_unit_each(RestFiles,
SourceDir, SourceExt,
TargetDir, TargetExt),
run(Config, FirstUnits, RestUnits, Compile3Fn, Opts).
%% FirstUnits and RestUnits are lists of tuples: {Source,Target}
run(Config, FirstUnits, RestUnits, Compile3Fn, Opts) ->
%% Check opts for flag indicating that compile should check lastmod %% Check opts for flag indicating that compile should check lastmod
CheckLastMod = proplists:get_bool(check_last_mod, Opts), CheckLastMod = proplists:get_bool(check_last_mod, Opts),
run(Config, FirstFiles, RestFiles, run(Config, FirstUnits, RestUnits,
fun(S, C) -> fun({S, Target}, C) ->
Target = target_file(S, SourceDir, SourceExt,
TargetDir, TargetExt),
simple_compile_wrapper(S, Target, Compile3Fn, C, CheckLastMod) simple_compile_wrapper(S, Target, Compile3Fn, C, CheckLastMod)
end). end).
@ -103,6 +112,10 @@ simple_compile_wrapper(Source, Target, Compile3Fn, Config, true) ->
skipped skipped
end. end.
source_to_unit_each(Files, SourceDir, SourceExt, TargetDir, TargetExt) ->
[{File, target_file(File, SourceDir, SourceExt, TargetDir, TargetExt)}
|| File <- Files].
target_file(SourceFile, SourceDir, SourceExt, TargetDir, TargetExt) -> target_file(SourceFile, SourceDir, SourceExt, TargetDir, TargetExt) ->
BaseFile = remove_common_path(SourceFile, SourceDir), BaseFile = remove_common_path(SourceFile, SourceDir),
filename:join([TargetDir, filename:basename(BaseFile, SourceExt) ++ TargetExt]). filename:join([TargetDir, filename:basename(BaseFile, SourceExt) ++ TargetExt]).
@ -117,8 +130,8 @@ remove_common_path1(FilenameParts, _) ->
filename:join(FilenameParts). filename:join(FilenameParts).
compile(Source, Config, CompileFn) -> compile(Unit, Config, CompileFn) ->
case CompileFn(Source, Config) of case CompileFn(Unit, Config) of
ok -> ok ->
ok; ok;
skipped -> skipped ->
@ -129,24 +142,29 @@ compile(Source, Config, CompileFn) ->
compile_each([], _Config, _CompileFn) -> compile_each([], _Config, _CompileFn) ->
ok; ok;
compile_each([Source | Rest], Config, CompileFn) -> compile_each([Unit | Rest], Config, CompileFn) ->
case compile(Source, Config, CompileFn) of case compile(Unit, Config, CompileFn) of
ok -> ok ->
?CONSOLE("Compiled ~s\n", [Source]); ?CONSOLE("Compiled ~s\n", [unit_source(Unit)]);
{ok, Warnings} -> {ok, Warnings} ->
report(Warnings), report(Warnings),
?CONSOLE("Compiled ~s\n", [Source]); ?CONSOLE("Compiled ~s\n", [unit_source(Unit)]);
skipped -> skipped ->
?INFO("Skipped ~s\n", [Source]); ?INFO("Skipped ~s\n", [unit_source(Unit)]);
Error -> Error ->
?CONSOLE("Compiling ~s failed:\n", ?CONSOLE("Compiling ~s failed:\n",
[maybe_absname(Config, Source)]), [maybe_absname(Config, unit_source(Unit))]),
maybe_report(Error), maybe_report(Error),
?DEBUG("Compilation failed: ~p\n", [Error]), ?DEBUG("Compilation failed: ~p\n", [Error]),
?FAIL ?FAIL
end, end,
compile_each(Rest, Config, CompileFn). compile_each(Rest, Config, CompileFn).
unit_source({Source, _Target}) ->
Source;
unit_source(Source) ->
Source.
compile_queue(_Config, [], []) -> compile_queue(_Config, [], []) ->
ok; ok;
compile_queue(Config, Pids, Targets) -> compile_queue(Config, Pids, Targets) ->
@ -168,17 +186,17 @@ compile_queue(Config, Pids, Targets) ->
?DEBUG("Worker compilation failed: ~p\n", [Error]), ?DEBUG("Worker compilation failed: ~p\n", [Error]),
?FAIL; ?FAIL;
{compiled, Source, Warnings} -> {compiled, Unit, Warnings} ->
report(Warnings), report(Warnings),
?CONSOLE("Compiled ~s\n", [Source]), ?CONSOLE("Compiled ~s\n", [unit_source(Unit)]),
compile_queue(Config, Pids, Targets); compile_queue(Config, Pids, Targets);
{compiled, Source} -> {compiled, Unit} ->
?CONSOLE("Compiled ~s\n", [Source]), ?CONSOLE("Compiled ~s\n", [unit_source(Unit)]),
compile_queue(Config, Pids, Targets); compile_queue(Config, Pids, Targets);
{skipped, Source} -> {skipped, Unit} ->
?INFO("Skipped ~s\n", [Source]), ?INFO("Skipped ~s\n", [unit_source(Unit)]),
compile_queue(Config, Pids, Targets); compile_queue(Config, Pids, Targets);
{'DOWN', Mref, _, Pid, normal} -> {'DOWN', Mref, _, Pid, normal} ->