From ca3867d783d610d1990a137d6a9387168dda6605 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?John=20H=C3=B6gberg?= <john@erlang.org>
Date: Thu, 26 Jul 2018 14:35:25 +0200
Subject: Omit include path debug info for +deterministic builds

Compiling the same file with different include paths resulted in
different files with the `+deterministic` flag even if everything
but the paths were identical. This was caused by the absolute path
of each include directory being unconditionally included in a
debug information chunk.

This commit fixes this by only including this information in
non-deterministic builds.
---
 lib/compiler/src/compile.erl        | 29 ++++++++++++++++++++++-------
 lib/compiler/test/compile_SUITE.erl | 22 ++++++++++++++++++++--
 2 files changed, 42 insertions(+), 9 deletions(-)

(limited to 'lib/compiler')

diff --git a/lib/compiler/src/compile.erl b/lib/compiler/src/compile.erl
index 50b0ba76f8..4203d79913 100644
--- a/lib/compiler/src/compile.erl
+++ b/lib/compiler/src/compile.erl
@@ -1408,16 +1408,30 @@ encrypt_debug_info(DebugInfo, Key, Opts) ->
     end.
 
 cleanup_compile_options(Opts) ->
-    lists:filter(fun keep_compile_option/1, Opts).
-
+    IsDeterministic = lists:member(deterministic, Opts),
+    lists:filter(fun(Opt) ->
+                         keep_compile_option(Opt, IsDeterministic)
+                 end, Opts).
+
+%% Include paths and current directory don't affect compilation, but they might
+%% be helpful so we include them unless we're doing a deterministic build.
+keep_compile_option({i, _}, Deterministic) ->
+    not Deterministic;
+keep_compile_option({cwd, _}, Deterministic) ->
+    not Deterministic;
 %% We are storing abstract, not asm or core.
-keep_compile_option(from_asm) -> false;
-keep_compile_option(from_core) -> false;
+keep_compile_option(from_asm, _Deterministic) ->
+    false;
+keep_compile_option(from_core, _Deterministic) ->
+    false;
 %% Parse transform and macros have already been applied.
-keep_compile_option({parse_transform, _}) -> false;
-keep_compile_option({d, _, _}) -> false;
+keep_compile_option({parse_transform, _}, _Deterministic) ->
+    false;
+keep_compile_option({d, _, _}, _Deterministic) ->
+    false;
 %% Do not affect compilation result on future calls.
-keep_compile_option(Option) -> effects_code_generation(Option).
+keep_compile_option(Option, _Deterministic) ->
+    effects_code_generation(Option).
 
 start_crypto() ->
     try crypto:start() of
@@ -1548,6 +1562,7 @@ effects_code_generation(Option) ->
 	binary -> false;
 	verbose -> false;
 	{cwd,_} -> false;
+	{i,_} -> false;
 	{outdir, _} -> false;
 	_ -> true
     end.
diff --git a/lib/compiler/test/compile_SUITE.erl b/lib/compiler/test/compile_SUITE.erl
index 96897d612d..c455afcb48 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
+         bc_options/1, deterministic_include/1
 	]).
 
 suite() -> [{ct_hooks,[ts_install_cth]}].
@@ -53,7 +53,8 @@ all() ->
      strict_record, utf8_atoms, utf8_functions, extra_chunks,
      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].
+     env_compiler_options, custom_debug_info, bc_options,
+     deterministic_include].
 
 groups() -> 
     [].
@@ -1445,6 +1446,23 @@ highest_opcode(DataDir, Mod, Opt) ->
     <<16:32,0:32,HighestOpcode:32,_/binary>> = Code,
     HighestOpcode.
 
+deterministic_include(Config) when is_list(Config) ->
+    DataDir = proplists:get_value(data_dir, Config),
+    Simple = filename:join(DataDir, "simple"),
+ 
+    %% Files without +deterministic should differ if their include paths do,
+    %% as their debug info will be different.
+    {ok,_,NonDetA} = compile:file(Simple, [binary, {i,"gurka"}]),
+    {ok,_,NonDetB} = compile:file(Simple, [binary, {i,"gaffel"}]),
+    true = NonDetA =/= NonDetB,
+
+    %% ... but files with +deterministic shouldn't.
+    {ok,_,DetC} = compile:file(Simple, [binary, deterministic, {i,"gurka"}]),
+    {ok,_,DetD} = compile:file(Simple, [binary, deterministic, {i,"gaffel"}]),
+    true = DetC =:= DetD,
+
+    ok.
+
 %%%
 %%% Utilities.
 %%%
-- 
cgit v1.2.3