LogoopenSUSE Build Service > Projects
Sign Up | Log In

View File 1006-Add-MMD-option-to-erlc.patch of Package erlang (Project home:Ledest:erlang:20)

From d455cf67203c29354ff792ea44aea09e7a2155f8 Mon Sep 17 00:00:00 2001
From: Tony Rogvall <tony@rogvall.se>
Date: Wed, 6 Dec 2017 02:28:29 +0100
Subject: [PATCH] Add -MMD option to erlc

The compile option makedep_side_effect, erlc -MMD, instructs
the compiler to emit dependencies and continue to compile
as normal.
---
 erts/doc/src/erlc.xml            |   8 +++
 erts/test/erlc_SUITE.erl         | 102 ++++++++++++++++++++++++++++++++++++++-
 lib/compiler/doc/src/compile.xml |   9 ++++
 lib/compiler/src/compile.erl     |  18 ++++++-
 lib/stdlib/src/erl_compile.erl   |   3 ++
 5 files changed, 138 insertions(+), 2 deletions(-)

diff --git a/erts/doc/src/erlc.xml b/erts/doc/src/erlc.xml
index 7355be488b..2214b76a51 100644
--- a/erts/doc/src/erlc.xml
+++ b/erts/doc/src/erlc.xml
@@ -143,6 +143,14 @@
         <p>Produces a Makefile rule to track header dependencies. The
           rule is sent to <c>stdout</c>. No object file is produced.</p>
       </item>
+
+      <tag><c>-MMD</c></tag>
+      <item>
+        <p>Generate dependencies as a side-effect. The object file
+	will be produced as normal. This option overrides the
+	option <c><![CDATA[-M]]></c>.</p>
+      </item>
+
       <tag><c>-MF &lt;Makefile&gt;</c></tag>
       <item>
         <p>As option <c><![CDATA[-M]]></c>, except that the
diff --git a/erts/test/erlc_SUITE.erl b/erts/test/erlc_SUITE.erl
index 237558a129..394ecc8964 100644
--- a/erts/test/erlc_SUITE.erl
+++ b/erts/test/erlc_SUITE.erl
@@ -257,7 +257,7 @@ erlc() ->
 make_dep_options(Config) ->
     {SrcDir,OutDir,Cmd} = get_cmd(Config),
     FileName = filename:join(SrcDir, "erl_test_ok.erl"),
-
+    BeamFileName = filename:join(OutDir, "erl_test_ok.beam"),
 
     DepRE = ["/erl_test_ok[.]beam: \\\\$",
              "/system_test/erlc_SUITE_data/src/erl_test_ok[.]erl \\\\$",
@@ -285,22 +285,29 @@ make_dep_options(Config) ->
      "missing.hrl$",
      "_OK_"],
 
+    file:delete(BeamFileName),
+
     %% Test plain -M
     run(Config, Cmd, FileName, "-M", DepRE),
+    false = exists(BeamFileName),
 
     %% Test -MF File
     DepFile = filename:join(OutDir, "my.deps"),
     run(Config, Cmd, FileName, "-MF "++DepFile, ["_OK_"]),
     {ok,MFBin} = file:read_file(DepFile),
     verify_result(binary_to_list(MFBin)++["_OK_"], DepRE),
+    false = exists(BeamFileName),
 
     %% Test -MD
     run(Config, Cmd, FileName, "-MD", ["_OK_"]),
     MDFile = filename:join(OutDir, "erl_test_ok.Pbeam"),
     {ok,MFBin} = file:read_file(MDFile),
+    file:delete(MDFile), %% used further down!
+    false = exists(BeamFileName),
 
     %% Test -M -MT Target
     run(Config, Cmd, FileName, "-M -MT target", DepRETarget),
+    false = exists(BeamFileName),
 
     %% Test -MF File -MT Target
     TargetDepFile = filename:join(OutDir, "target.deps"),
@@ -308,23 +315,110 @@ make_dep_options(Config) ->
         ["_OK_"]),
     {ok,TargetBin} = file:read_file(TargetDepFile),
     verify_result(binary_to_list(TargetBin)++["_OK_"], DepRETarget),
+    file:delete(TargetDepFile),
+    false = exists(BeamFileName),
 
     %% Test -MD -MT Target
     run(Config, Cmd, FileName, "-MD -MT target", ["_OK_"]),
     TargetMDFile = filename:join(OutDir, "erl_test_ok.Pbeam"),
     {ok,TargetBin} = file:read_file(TargetMDFile),
+    file:delete(TargetDepFile),
+    false = exists(BeamFileName),
 
     %% Test -M -MQ Target. (Note: Passing a $ on the command line
     %% portably for Unix and Windows is tricky, so we will just test
     %% that MQ works at all.)
     run(Config, Cmd, FileName, "-M -MQ target", DepRETarget),
+    false = exists(BeamFileName),
 
     %% Test -M -MP
     run(Config, Cmd, FileName, "-M -MP", DepREMP),
+    false = exists(BeamFileName),
 
     %% Test -M -MG
     MissingHeader = filename:join(SrcDir, "erl_test_missing_header.erl"),
     run(Config, Cmd, MissingHeader, "-M -MG", DepREMissing),
+    false = exists(BeamFileName),
+
+    %%
+    %% check the above variants with side-effect -MMD
+    %%
+
+    %% since compiler is run on the erlang code a warning will be
+    %% issued by the compiler, match that.
+    WarningRE = "/system_test/erlc_SUITE_data/src/erl_test_ok.erl:[0-9]+: "
+        "Warning: function foo/0 is unused$",
+    ErrorRE = "/system_test/erlc_SUITE_data/src/erl_test_missing_header.erl:"
+        "[0-9]+: can't find include file \"missing.hrl\"$",
+
+    DepRE_MMD = insert_before("_OK_", WarningRE, DepRE),
+    DepRETarget_MMD = insert_before("_OK_", WarningRE, DepRETarget),
+    DepREMP_MMD = insert_before("_OK_",WarningRE,DepREMP),
+    DepREMissing_MMD = (insert_before("_OK_",ErrorRE,DepREMissing)--
+                            ["_OK_"]) ++ ["_ERROR_"],
+    CompRE = [WarningRE,"_OK_"],
+
+
+    %% Test plain -MMD -M
+    run(Config, Cmd, FileName, "-MMD -M", DepRE_MMD),
+    true = exists(BeamFileName),
+    file:delete(BeamFileName),
+
+    %% Test -MMD -MF File
+    DepFile = filename:join(OutDir, "my.deps"),
+    run(Config, Cmd, FileName, "-MMD -MF "++DepFile, CompRE),
+    {ok,MFBin} = file:read_file(DepFile),
+    verify_result(binary_to_list(MFBin)++["_OK_"], DepRE),
+    true = exists(BeamFileName),
+    file:delete(BeamFileName),
+
+    %% Test -MMD -MD
+    run(Config, Cmd, FileName, "-MMD -MD", CompRE),
+    MDFile = filename:join(OutDir, "erl_test_ok.Pbeam"),
+    {ok,MFBin} = file:read_file(MDFile),
+    file:delete(MDFile), %% used further down!
+    true = exists(BeamFileName),
+    file:delete(BeamFileName),
+
+    %% Test -MMD -M -MT Target
+    run(Config, Cmd, FileName, "-MMD -M -MT target", DepRETarget_MMD),
+    true = exists(BeamFileName),
+    file:delete(BeamFileName),
+
+    %% Test -MMD -MF File -MT Target
+    TargetDepFile = filename:join(OutDir, "target.deps"),
+    run(Config, Cmd, FileName, "-MMD -MF "++TargetDepFile++" -MT target",
+        CompRE),
+    {ok,TargetBin} = file:read_file(TargetDepFile),
+    verify_result(binary_to_list(TargetBin)++["_OK_"], DepRETarget),
+    file:delete(TargetDepFile),
+    true = exists(BeamFileName),
+    file:delete(BeamFileName),
+
+    %% Test -MMD -MD -MT Target
+    run(Config, Cmd, FileName, "-MMD -MD -MT target", CompRE),
+    TargetMDFile = filename:join(OutDir, "erl_test_ok.Pbeam"),
+    {ok,TargetBin} = file:read_file(TargetMDFile),
+    file:delete(TargetDepFile),
+    true = exists(BeamFileName),
+    file:delete(BeamFileName),
+
+    %% Test -MMD -M -MQ Target. (Note: Passing a $ on the command line
+    %% portably for Unix and Windows is tricky, so we will just test
+    %% that MQ works at all.)
+    run(Config, Cmd, FileName, "-MMD -M -MQ target", DepRETarget_MMD),
+    true = exists(BeamFileName),
+    file:delete(BeamFileName),
+
+    %% Test -MMD -M -MP
+    run(Config, Cmd, FileName, "-MMD -M -MP", DepREMP_MMD),
+    true = exists(BeamFileName),
+    file:delete(BeamFileName),
+
+    %% Test -MMD -M -MG
+    MissingHeader = filename:join(SrcDir, "erl_test_missing_header.erl"),
+    run(Config, Cmd, MissingHeader, "-MMD -M -MG", DepREMissing_MMD),
+    false = exists(BeamFileName),
     ok.
 
 %% Runs a command.
@@ -341,6 +435,12 @@ verify_result(Result, Expect) ->
     io:format("Expected: ~p", [Expect]),
     match_messages(Messages, Expect).
 
+%% insert What before Item, crash if Item is not found
+insert_before(Item, What, [Item|List]) ->
+    [What,Item|List];
+insert_before(Item, What, [Other|List]) ->
+    [Other|insert_before(Item, What, List)].
+
 split([$\n|Rest], Current, Lines) ->
     split(Rest, [], [lists:reverse(Current)|Lines]);
 split([$\r|Rest], Current, Lines) ->
diff --git a/lib/compiler/doc/src/compile.xml b/lib/compiler/doc/src/compile.xml
index b398871ddf..06afc55c07 100644
--- a/lib/compiler/doc/src/compile.xml
+++ b/lib/compiler/doc/src/compile.xml
@@ -233,6 +233,15 @@ module.beam: module.erl \
   header.hrl</code>
           </item>
 
+          <tag><c>makedep_side_effect</c></tag>
+          <item>
+	    <p>The dependecies are created as a side effect to the
+	    normal compilation process. This means that the object
+	    file will also be produced. This option override the
+	    <c>makedep</c> option.
+	    </p>
+	  </item>
+
           <tag><c>{makedep_output, Output}</c></tag>
           <item>
             <p>Writes generated rules to <c>Output</c> instead of the
diff --git a/lib/compiler/src/compile.erl b/lib/compiler/src/compile.erl
index 327fecf0e6..ad57eae855 100644
--- a/lib/compiler/src/compile.erl
+++ b/lib/compiler/src/compile.erl
@@ -203,7 +203,12 @@ expand_opts(Opts0) ->
 	       {_,_,undefined} -> [debug_info|Opts0];
 	       {_,_,_} -> Opts0
 	   end,
-    foldr(fun expand_opt/2, [], Opts).
+    %% iff,unless processing is to complex...
+    Opts1 = case proplists:is_defined(makedep_side_effect,Opts) of
+                true -> proplists:delete(makedep,Opts);
+                false -> Opts
+            end,
+    foldr(fun expand_opt/2, [], Opts1).
 
 expand_opt(basic_validation, Os) ->
     [no_code_generation,to_pp,binary|Os];
@@ -674,6 +679,7 @@ select_list_passes_1([], _, Acc) ->
 standard_passes() ->
     [?pass(transform_module),
 
+     {iff,makedep_side_effect,?pass(makedep_and_output)},
      {iff,makedep,[
 	 ?pass(makedep),
 	 {unless,binary,?pass(makedep_output)}
@@ -1128,6 +1134,16 @@ core_lint_module(Code, St) ->
 			      errors=St#compile.errors ++ Es}}
     end.
 
+%% makedep + output and continue
+makedep_and_output(Code0, St) ->
+    {ok,DepCode,St1} = makedep(Code0,St),
+    case makedep_output(DepCode, St1) of
+        {ok,_IgnoreCode,St2} ->
+            {ok,Code0,St2};
+        {error,St2} ->
+            {error,St2}
+    end.
+
 makedep(Code0, #compile{ifile=Ifile,ofile=Ofile,options=Opts}=St) ->
 
     %% Get the target of the Makefile rule.
diff --git a/lib/stdlib/src/erl_compile.erl b/lib/stdlib/src/erl_compile.erl
index 18d7548fdc..f781312ca2 100644
--- a/lib/stdlib/src/erl_compile.erl
+++ b/lib/stdlib/src/erl_compile.erl
@@ -188,6 +188,8 @@ parse_dep_option("", T) ->
     {[makedep,{makedep_output,standard_io}],T};
 parse_dep_option("D", T) ->
     {[makedep],T};
+parse_dep_option("MD", T) ->
+    {[makedep_side_effect],T};
 parse_dep_option("F"++Opt, T0) ->
     {File,T} = get_option("MF", Opt, T0),
     {[makedep,{makedep_output,File}],T};
@@ -221,6 +223,7 @@ usage() ->
 	  "the dependencies"},
 	 {"-MP","add a phony target for each dependency"},
 	 {"-MD","same as -M -MT file (with default 'file')"},
+	 {"-MMD","generate dependencies as a side-effect"},
 	 {"-o name","name output directory or file"},
 	 {"-pa path","add path to the front of Erlang's code path"},
 	 {"-pz path","add path to the end of Erlang's code path"},
-- 
2.15.1