From 3a34f37fbc5af8eca7a70f5dab61dca7ee1706b0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?John=20H=C3=B6gberg?= <john@erlang.org>
Date: Fri, 5 Oct 2018 10:06:35 +0200
Subject: compiler: Forward +source flag to epp and fix bug in +deterministic

The source file path as given to `erlc` was included in an implicit
file attribute inserted by epp, even when the +source flag was
set to something else which was a bit surprising. It was also
included when +deterministic was specified, breaking the flag's
promise.

This commit forwards the +source flag to epp so it inserts the
right information, and if +deterministic is given it will be shaved
to just the base name of the file, guaranteeing the same result
regardless of how the input is reached.
---
 lib/compiler/doc/src/compile.xml    |  7 ++++---
 lib/compiler/src/compile.erl        | 14 ++++++++++----
 lib/compiler/test/compile_SUITE.erl | 28 ++++++++++++++++++++++++++--
 3 files changed, 40 insertions(+), 9 deletions(-)

(limited to 'lib/compiler')

diff --git a/lib/compiler/doc/src/compile.xml b/lib/compiler/doc/src/compile.xml
index 1a71c83521..cfbd4c7fda 100644
--- a/lib/compiler/doc/src/compile.xml
+++ b/lib/compiler/doc/src/compile.xml
@@ -203,7 +203,8 @@
           <tag><c>deterministic</c></tag>
           <item>
             <p>Omit the <c>options</c> and <c>source</c> tuples in
-	    the list returned by <c>Module:module_info(compile)</c>.
+            the list returned by <c>Module:module_info(compile)</c>, and
+            reduce the paths in stack traces to the module name alone.
 	    This option will make it easier to achieve reproducible builds.
 	    </p>
           </item>
@@ -347,8 +348,8 @@ module.beam: module.erl \
 
 	  <tag><c>{source,FileName}</c></tag>
           <item>
-            <p>Sets the value of the source, as returned by
-              <c>module_info(compile)</c>.</p>
+            <p>Overrides the source file name as presented in
+              <c>module_info(compile)</c> and stack traces.</p>
           </item>
 
 	  <tag><c>{outdir,Dir}</c></tag>
diff --git a/lib/compiler/src/compile.erl b/lib/compiler/src/compile.erl
index 562d57a6ef..6510571441 100644
--- a/lib/compiler/src/compile.erl
+++ b/lib/compiler/src/compile.erl
@@ -931,11 +931,17 @@ parse_module(_Code, St0) ->
     end.
 
 do_parse_module(DefEncoding, #compile{ifile=File,options=Opts,dir=Dir}=St) ->
+    SourceName0 = proplists:get_value(source, Opts, File),
+    SourceName = case member(deterministic, Opts) of
+                     true -> filename:basename(SourceName0);
+                     false -> SourceName0
+                 end,
     R = epp:parse_file(File,
-		       [{includes,[".",Dir|inc_paths(Opts)]},
-			{macros,pre_defs(Opts)},
-			{default_encoding,DefEncoding},
-			extra]),
+                       [{includes,[".",Dir|inc_paths(Opts)]},
+                        {source_name, SourceName},
+                        {macros,pre_defs(Opts)},
+                        {default_encoding,DefEncoding},
+                        extra]),
     case R of
 	{ok,Forms,Extra} ->
 	    Encoding = proplists:get_value(encoding, Extra),
diff --git a/lib/compiler/test/compile_SUITE.erl b/lib/compiler/test/compile_SUITE.erl
index 1ecae06128..6b230710b3 100644
--- a/lib/compiler/test/compile_SUITE.erl
+++ b/lib/compiler/test/compile_SUITE.erl
@@ -36,7 +36,7 @@
 	 core_roundtrip/1, asm/1, optimized_guards/1,
 	 sys_pre_attributes/1, dialyzer/1,
 	 warnings/1, pre_load_check/1, env_compiler_options/1,
-         bc_options/1, deterministic_include/1
+         bc_options/1, deterministic_include/1, deterministic_paths/1
 	]).
 
 suite() -> [{ct_hooks,[ts_install_cth]}].
@@ -53,7 +53,7 @@ all() ->
      cover, env, core_pp, core_roundtrip, asm, optimized_guards,
      sys_pre_attributes, dialyzer, warnings, pre_load_check,
      env_compiler_options, custom_debug_info, bc_options,
-     custom_compile_info, deterministic_include].
+     custom_compile_info, deterministic_include, deterministic_paths].
 
 groups() -> 
     [].
@@ -1531,6 +1531,30 @@ deterministic_include(Config) when is_list(Config) ->
 
     ok.
 
+deterministic_paths(Config) when is_list(Config) ->
+    DataDir = proplists:get_value(data_dir, Config),
+
+    %% Files without +deterministic should differ if they were compiled from a
+    %% different directory.
+    true = deterministic_paths_1(DataDir, "simple", []),
+
+    %% ... but files with +deterministic shouldn't.
+    false = deterministic_paths_1(DataDir, "simple", [deterministic]),
+
+    ok.
+
+deterministic_paths_1(DataDir, Name, Opts) ->
+    Simple = filename:join(DataDir, "simple"),
+    {ok, Cwd} = file:get_cwd(),
+    try
+        {ok,_,A} = compile:file(Simple, [binary | Opts]),
+        ok = file:set_cwd(DataDir),
+        {ok,_,B} = compile:file(Name, [binary | Opts]),
+        A =/= B
+    after
+        file:set_cwd(Cwd)
+    end.
+
 %%%
 %%% Utilities.
 %%%
-- 
cgit v1.2.3