summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/rebar_base_compiler.erl12
-rw-r--r--src/rebar_erlc_compiler.erl39
-rw-r--r--src/rebar_file_utils.erl20
-rw-r--r--test/rebar_file_utils_SUITE.erl27
4 files changed, 87 insertions, 11 deletions
diff --git a/src/rebar_base_compiler.erl b/src/rebar_base_compiler.erl
index 31292af..2f67f25 100644
--- a/src/rebar_base_compiler.erl
+++ b/src/rebar_base_compiler.erl
@@ -153,12 +153,12 @@ format_errors(_MainSource, Extra, Errors) ->
end
|| {Source, Descs} <- Errors].
-format_error(AbsSource, Extra, {{Line, Column}, Mod, Desc}) ->
+format_error(Source, Extra, {{Line, Column}, Mod, Desc}) ->
ErrorDesc = Mod:format_error(Desc),
- ?FMT("~s:~w:~w: ~s~s~n", [AbsSource, Line, Column, Extra, ErrorDesc]);
-format_error(AbsSource, Extra, {Line, Mod, Desc}) ->
+ ?FMT("~s:~w:~w: ~s~s~n", [Source, Line, Column, Extra, ErrorDesc]);
+format_error(Source, Extra, {Line, Mod, Desc}) ->
ErrorDesc = Mod:format_error(Desc),
- ?FMT("~s:~w: ~s~s~n", [AbsSource, Line, Extra, ErrorDesc]);
-format_error(AbsSource, Extra, {Mod, Desc}) ->
+ ?FMT("~s:~w: ~s~s~n", [Source, Line, Extra, ErrorDesc]);
+format_error(Source, Extra, {Mod, Desc}) ->
ErrorDesc = Mod:format_error(Desc),
- ?FMT("~s: ~s~s~n", [AbsSource, Extra, ErrorDesc]).
+ ?FMT("~s: ~s~s~n", [Source, Extra, ErrorDesc]).
diff --git a/src/rebar_erlc_compiler.erl b/src/rebar_erlc_compiler.erl
index 3480cf6..4955357 100644
--- a/src/rebar_erlc_compiler.erl
+++ b/src/rebar_erlc_compiler.erl
@@ -54,6 +54,8 @@
-define(DEFAULT_OUTDIR, "ebin").
-define(RE_PREFIX, "^[^._]").
+-type compiler_source_format() :: absolute | relative | unchanged.
+-define(DEFAULT_COMPILER_SOURCE_FORMAT, unchanged).
%% ===================================================================
%% Public API
@@ -500,7 +502,7 @@ expand_file_names(Files, Dirs) ->
-spec internal_erl_compile(rebar_dict(), file:filename(), file:filename(),
file:filename(), list()) -> ok | {ok, any()} | {error, any(), any()}.
-internal_erl_compile(_Opts, Dir, Module, OutDir, ErlOpts) ->
+internal_erl_compile(Opts, Dir, Module, OutDir, ErlOpts) ->
Target = target_base(OutDir, Module) ++ ".beam",
ok = filelib:ensure_dir(Target),
AllOpts = [{outdir, filename:dirname(Target)}] ++ ErlOpts ++
@@ -511,9 +513,42 @@ internal_erl_compile(_Opts, Dir, Module, OutDir, ErlOpts) ->
{ok, _Mod, Ws} ->
rebar_base_compiler:ok_tuple(Module, Ws);
{error, Es, Ws} ->
- rebar_base_compiler:error_tuple(Module, Es, Ws, AllOpts)
+ error_tuple(Module, Es, Ws, AllOpts, source_format(Opts))
end.
+-spec source_format(rebar_dict()) -> compiler_source_format().
+source_format(Opts) ->
+ case rebar_opts:get(Opts, compiler_source_format,
+ ?DEFAULT_COMPILER_SOURCE_FORMAT) of
+ V when V == absolute;
+ V == relative;
+ V == unchanged -> V;
+ Other ->
+ ?WARN("Invalid argument ~p for compiler_source_format - "
+ "assuming ~s~n", [Other, ?DEFAULT_COMPILER_SOURCE_FORMAT]),
+ ?DEFAULT_COMPILER_SOURCE_FORMAT
+ end.
+
+error_tuple(Module, Es, Ws, Opts, SourceFormat) ->
+ Cwd = rebar_dir:get_cwd(),
+ FormattedEs = format_error_sources(Es, SourceFormat, Cwd),
+ FormattedWs = format_error_sources(Ws, SourceFormat, Cwd),
+ rebar_base_compiler:error_tuple(Module, FormattedEs, FormattedWs, Opts).
+
+format_error_sources(Es, Format, Cwd) ->
+ [{format_error_source(Src, Format, Cwd), Desc} || {Src, Desc} <- Es].
+
+format_error_source(Src, absolute, _Cwd) ->
+ resolve_linked_source(Src);
+format_error_source(Src, relative, Cwd) ->
+ rebar_dir:make_relative_path(resolve_linked_source(Src), Cwd);
+format_error_source(Src, unchanged, _Cwd) ->
+ Src.
+
+resolve_linked_source(Src) ->
+ {Dir, Base} = rebar_file_utils:split_dirname(Src),
+ filename:join(rebar_file_utils:resolve_link(Dir), Base).
+
target_base(OutDir, Source) ->
filename:join(OutDir, filename:basename(Source, ".erl")).
diff --git a/src/rebar_file_utils.erl b/src/rebar_file_utils.erl
index 0f84520..19cc94d 100644
--- a/src/rebar_file_utils.erl
+++ b/src/rebar_file_utils.erl
@@ -39,7 +39,9 @@
reset_dir/1,
touch/1,
path_from_ancestor/2,
- canonical_path/1]).
+ canonical_path/1,
+ resolve_link/1,
+ split_dirname/1]).
-include("rebar.hrl").
@@ -273,6 +275,22 @@ canonical_path([_|Acc], [".."|Rest]) -> canonical_path(Acc, Rest);
canonical_path([], [".."|Rest]) -> canonical_path([], Rest);
canonical_path(Acc, [Component|Rest]) -> canonical_path([Component|Acc], Rest).
+%% returns canonical target of path if path is a link, otherwise returns path
+-spec resolve_link(string()) -> string().
+
+resolve_link(Path) ->
+ case file:read_link(Path) of
+ {ok, Target} ->
+ canonical_path(filename:absname(Target, filename:dirname(Path)));
+ {error, _} -> Path
+ end.
+
+%% splits a path into dirname and basename
+-spec split_dirname(string()) -> {string(), string()}.
+
+split_dirname(Path) ->
+ {filename:dirname(Path), filename:basename(Path)}.
+
%% ===================================================================
%% Internal functions
%% ===================================================================
diff --git a/test/rebar_file_utils_SUITE.erl b/test/rebar_file_utils_SUITE.erl
index c1f85b3..23c5792 100644
--- a/test/rebar_file_utils_SUITE.erl
+++ b/test/rebar_file_utils_SUITE.erl
@@ -12,7 +12,9 @@
reset_empty_dir/1,
reset_dir/1,
path_from_ancestor/1,
- canonical_path/1]).
+ canonical_path/1,
+ resolve_link/1,
+ split_dirname/1]).
-include_lib("common_test/include/ct.hrl").
-include_lib("eunit/include/eunit.hrl").
@@ -22,7 +24,9 @@
all() ->
[{group, tmpdir},
{group, reset_dir},
- path_from_ancestor, canonical_path].
+ canonical_path,
+ resolve_link,
+ split_dirname].
groups() ->
[{tmpdir, [], [raw_tmpdir, empty_tmpdir, simple_tmpdir, multi_tmpdir]},
@@ -111,3 +115,22 @@ canonical_path(_Config) ->
?assertEqual(Root ++ "foo", rebar_file_utils:canonical_path("/foo/./.")),
?assertEqual(filename:nativename(Root ++ "foo/bar"),
rebar_file_utils:canonical_path("/foo/./bar")).
+
+resolve_link(_Config) ->
+ TmpDir = rebar_file_utils:system_tmpdir(
+ ["rebar_file_utils_SUITE", "resolve_link"]),
+ Link = filename:join(TmpDir, "link"),
+ Target = filename:join(TmpDir, "link-target"),
+ ec_file:remove(TmpDir, [recursive]),
+ ok = filelib:ensure_dir(Target),
+ ok = file:write_file(Target, <<>>),
+ ok = file:make_symlink(Target, Link),
+ ?assertEqual(Target, rebar_file_utils:resolve_link(Link)).
+
+split_dirname(_Config) ->
+ ?assertEqual({".", ""}, rebar_file_utils:split_dirname("")),
+ ?assertEqual({"/", ""}, rebar_file_utils:split_dirname("/")),
+ ?assertEqual({"/", "foo"}, rebar_file_utils:split_dirname("/foo")),
+ ?assertEqual({".", "foo"}, rebar_file_utils:split_dirname("foo")),
+ ?assertEqual({"/foo", "bar"}, rebar_file_utils:split_dirname("/foo/bar")),
+ ?assertEqual({"foo", "bar"}, rebar_file_utils:split_dirname("foo/bar")).