File 7031-Add-recursion-in-systools_make-module-checks.patch of Package erlang

From c27059a8bbdef967c936cc83f0da5c7d3198ef35 Mon Sep 17 00:00:00 2001
From: Fred Hebert <mononcqc@ferd.ca>
Date: Thu, 21 Oct 2021 13:11:37 -0400
Subject: [PATCH] Add recursion in systools_make module checks

In the current OTP release mechanisms, systools can be configured to do
a source file check to make sure any built module has a matching source
file. When such a source file is not found, a warning is emitted.

The current mechanism only supports looking in two directories: $app/src/
and $app/e_src/. This causes issues with existing OTP applications, such
as Wx, which uses $app/src/gen/ for auto-generated modules, for example,
meaning that any release relying on sub-directories as part of its build
process will not pass any of the sanity checks.

This patch changes the behaviour to look in all the subdirectories of
$app/src and $app/e_src (on top of these directories specifically)
for source files. This makes release creation warning-free for most
applications.

The only potential incompatibilities for this change would be:

- An OTP application which has various source files with the same name,
  where there is specifically one of them in a subdirectory of src/ and
  the desired one at the top-level of e_src/, where a new file is now
  going to be favoured

- Any subdirectory structure that loops onto itself or throws
  `filelib:wildcard/2` into exponential behaviour but somehow was not an
  issue when compiling the application normally might now be triggered.

These two possible incompatibilities are something we should consider
less likely than trying to build releases that contain the built-in Wx
OTP application, for example.
---
 lib/sasl/src/systools_make.erl                | 26 ++++++++++++++++++-
 lib/sasl/test/systools_SUITE.erl              | 13 ++++++++++
 .../d_missing_src/lib/db-2.1/ebin/db.app      |  2 +-
 .../d_missing_src/lib/db-2.1/src/sub/db3.erl  |  3 +++
 4 files changed, 42 insertions(+), 2 deletions(-)
 create mode 100644 lib/sasl/test/systools_SUITE_data/d_missing_src/lib/db-2.1/src/sub/db3.erl

diff --git a/lib/sasl/src/systools_make.erl b/lib/sasl/src/systools_make.erl
index ca4fb4300a..0cac1099d3 100644
--- a/lib/sasl/src/systools_make.erl
+++ b/lib/sasl/src/systools_make.erl
@@ -1162,11 +1162,35 @@ smart_guess(Dir,IncPath) ->
 	    D1 = reverse(D),
 	    Dirs = [filename:join(D1 ++ ["src"]),
 		    filename:join(D1 ++ ["src", "e_src"])],
-	    {Dirs,Dirs ++ IncPath};
+	    RecurseDirs = add_subdirs(Dirs),
+	    {RecurseDirs,RecurseDirs ++ IncPath};
 	_ ->
 	    {[Dir],[Dir] ++ IncPath}
     end.
 
+%%______________________________________________________________________
+%% add_subdirs([Dirs]) -> [Dirs]
+%% Take the directories that were used for a guess, and search them
+%% recursively. This is required for applications relying on varying
+%% nested directories. One example within OTP is the `wx' application,
+%% which has auto-generated modules in `src/gen/' and then fail any
+%% systools check.
+
+add_subdirs([]) ->
+    [];
+add_subdirs([Dir|Dirs]) ->
+    case filelib:is_dir(Dir) of
+        false ->
+            %% Keep the bad guess, but put it last in the search order
+            %% since we won't find anything there. Handling of errors
+            %% for unfound file is done in `locate_src/2'
+            add_subdirs(Dirs) ++ [Dir];
+        true ->
+            SubDirs = [File || File <- filelib:wildcard(filename:join(Dir, "**")),
+                               filelib:is_dir(File)],
+            [Dir|SubDirs] ++ add_subdirs(Dirs)
+    end.
+
 %%______________________________________________________________________
 %% generate_script(#release, 
 %%                 [{{Name,Vsn},#application}], Flags) ->
diff --git a/lib/sasl/test/systools_SUITE.erl b/lib/sasl/test/systools_SUITE.erl
index 47669b3c99..186551962c 100644
--- a/lib/sasl/test/systools_SUITE.erl
+++ b/lib/sasl/test/systools_SUITE.erl
@@ -106,6 +106,9 @@ init_per_suite(Config) when is_list(Config) ->
     %% Compile source files in the copy directory.
     Sources = filelib:wildcard(fname([CopyDir,'*','*','*','*','*.erl'])),
     lists:foreach(fun compile_source/1, Sources),
+    %% Deal with subdirectories, if any
+    SubSources = filelib:wildcard(fname([CopyDir,'*','*','*','*','*','*.erl'])),
+    lists:foreach(fun compile_subsource/1, SubSources),
 
     [{copy_dir, CopyDir}, {cwd,Cwd}, {path,Path} | Config].
 
@@ -122,6 +125,16 @@ compile_source(File) ->
     ok = file:write_file(OutFileTemp, Code),
     file:rename(OutFileTemp, OutFile).
 
+compile_subsource(File) ->
+    %% Same as compile_source/1 but works a subdirectory lower
+    U = filename:dirname(filename:dirname(filename:dirname(File))),
+    Base = filename:rootname(filename:basename(File)),
+    OutFile = filename:join([U,"ebin",Base++".beam"]),
+    OutFileTemp = OutFile ++ "#",
+    {ok,_,Code} = compile:file(File, [binary]),
+    ok = file:write_file(OutFileTemp, Code),
+    file:rename(OutFileTemp, OutFile).
+
 end_per_suite(Config) when is_list(Config) ->
     rh_test_lib:clean_dir(?privdir),
     Config.
diff --git a/lib/sasl/test/systools_SUITE_data/d_missing_src/lib/db-2.1/ebin/db.app b/lib/sasl/test/systools_SUITE_data/d_missing_src/lib/db-2.1/ebin/db.app
index a1025c306a..28d0f80d34 100644
--- a/lib/sasl/test/systools_SUITE_data/d_missing_src/lib/db-2.1/ebin/db.app
+++ b/lib/sasl/test/systools_SUITE_data/d_missing_src/lib/db-2.1/ebin/db.app
@@ -1,7 +1,7 @@
 {application, db,
    [{description, "ERICSSON NR FOR DB"},
     {vsn, "2.1"},
-    {modules, [db1, db2]},
+    {modules, [db1, db2, db3]},
     {registered, []},
     {applications, []},
     {env, []},
diff --git a/lib/sasl/test/systools_SUITE_data/d_missing_src/lib/db-2.1/src/sub/db3.erl b/lib/sasl/test/systools_SUITE_data/d_missing_src/lib/db-2.1/src/sub/db3.erl
new file mode 100644
index 0000000000..010249638f
--- /dev/null
+++ b/lib/sasl/test/systools_SUITE_data/d_missing_src/lib/db-2.1/src/sub/db3.erl
@@ -0,0 +1,3 @@
+-module(db3).
+-vsn("1.0").
+
-- 
2.31.1

openSUSE Build Service is sponsored by