]> git.ipfire.org Git - thirdparty/make.git/commitdiff
[SV 60412] Allow -I- to throw out the current directory path
authorPaul Smith <psmith@gnu.org>
Sun, 30 May 2021 22:47:50 +0000 (18:47 -0400)
committerPaul Smith <psmith@gnu.org>
Fri, 3 Sep 2021 16:08:11 +0000 (12:08 -0400)
Accept a "-" directory value to the -I option to clear the set of
directories to be searched up to that point, including the default
directories.

* NEWS: Announce the change.
* doc/make.texi (Summary of Options): Add documentation.
* src/read.c (construct_include_path): Check for '-' and if found,
clear the list of directories to be searched.
* tests/scripts/options/dash-I: Add tests for -I-.
* tests/scripts/variables/INCLUDE_DIRS: Add tests for -I-.

NEWS
doc/make.texi
src/read.c
tests/scripts/options/dash-I
tests/scripts/variables/INCLUDE_DIRS

diff --git a/NEWS b/NEWS
index c45ef741fdc6c6af8d540ef422b8ecec81b8aef8..26a272e33831b771bf6acf37119eb444d875926e 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -50,6 +50,10 @@ https://sv.gnu.org/bugs/index.php?group=make&report_id=111&fix_release_id=109&se
   user-defined function and they will not impact global variable assignments.
   Implementation provided by Jouke Witteveen <j.witteveen@gmail.com>
 
+* The -I option accepts an argument "-" (e.g., "-I-") which means "reset the
+  list of search directories to empty".  Among other things this can be used
+  to prevent GNU make from searching in its default list of directories.
+
 * New debug option "print" will show the recipe to be run, even when silent
   mode is set, and new debug option "why" will show why a target is rebuilt
   (which prerequisites caused the target to be considered out of date).
index db4d7e7a273c914f90530c51dd197fe0e2c74cf0..411fb69258f40e1bdd21eaaa8b331265657d5842 100644 (file)
@@ -1281,6 +1281,16 @@ hierarchy.})
 @file{/usr/gnu/include},
 @file{/usr/local/include}, @file{/usr/include}.
 
+The @code{.INCLUDE_DIRS} variable will contain the current list of
+directories that make will search for included files.  @xref{Special
+Variables, ,Other Special Variables}.
+
+You can avoid searching in these default directories by adding the
+command line option @code{-I} with the special value @code{-} (e.g.,
+@code{-I-}) to the command line.  This will cause @code{make} to
+forget any already-set include directories, including the default
+directories.
+
 If an included makefile cannot be found in any of these directories it
 is not an immediately fatal error; processing of the makefile
 containing the @code{include} continues.  Once it has finished reading
@@ -6676,6 +6686,8 @@ Supports dynamically loadable objects for creating custom extensions.
 @item .INCLUDE_DIRS
 Expands to a list of directories that @code{make} searches for
 included makefiles (@pxref{Include, , Including Other Makefiles}).
+Note that modifying this variable's value does not change the list of
+directories which are searched.
 
 @vindex .EXTRA_PREREQS @r{(prerequisites not added to automatic variables)}
 @item .EXTRA_PREREQS
@@ -9058,7 +9070,11 @@ Ignore all errors in recipes executed to remake files.
 Specifies a directory @var{dir} to search for included makefiles.
 @xref{Include, ,Including Other Makefiles}.  If several @samp{-I}
 options are used to specify several directories, the directories are
-searched in the order specified.
+searched in the order specified.  If the directory @var{dir} is a
+single dash (@code{-}) then any already-specified directories up to
+that point (including the default directory paths) will be discarded.
+You can examine the current list of directories to be searched via the
+@code{.INCLUDE_DIRS} variable.
 
 @item -j [@var{jobs}]
 @cindex @code{-j}
index 4b285c5778fd4e8f3d66943529a8390332158f7d..5cdb5139e0905fb8955b6982ccf78924f923aa7f 100644 (file)
@@ -2926,6 +2926,7 @@ construct_include_path (const char **arg_dirs)
   const char **dirs;
   const char **cpp;
   size_t idx;
+  int disable = 0;
 
   /* Compute the number of pointers we need in the table.  */
   idx = sizeof (default_include_directories) / sizeof (const char *);
@@ -2944,7 +2945,8 @@ construct_include_path (const char **arg_dirs)
   max_incl_len = 0;
 
   /* First consider any dirs specified with -I switches.
-     Ignore any that don't exist.  Remember the maximum string length.  */
+     Ignore any that don't exist.  Restart if we find "-".
+     Remember the maximum string length.  */
 
   if (arg_dirs)
     while (*arg_dirs != 0)
@@ -2953,6 +2955,14 @@ construct_include_path (const char **arg_dirs)
         char *expanded = 0;
         int e;
 
+        if (dir[0] == '-' && dir[1] == '\0')
+          {
+            disable = 1;
+            idx = 0;
+            max_incl_len = 0;
+            continue;
+          }
+
         if (dir[0] == '~')
           {
             expanded = tilde_expand (dir);
@@ -2976,41 +2986,40 @@ construct_include_path (const char **arg_dirs)
       }
 
   /* Now add the standard default dirs at the end.  */
-
+  if (!disable)
+    {
 #ifdef  __MSDOS__
-  {
-    /* The environment variable $DJDIR holds the root of the DJGPP directory
-       tree; add ${DJDIR}/include.  */
-    struct variable *djdir = lookup_variable ("DJDIR", 5);
-
-    if (djdir)
-      {
-        size_t len = strlen (djdir->value) + 8;
-        char *defdir = alloca (len + 1);
+      /* The environment variable $DJDIR holds the root of the DJGPP directory
+         tree; add ${DJDIR}/include.  */
+      struct variable *djdir = lookup_variable ("DJDIR", 5);
 
-        strcat (strcpy (defdir, djdir->value), "/include");
-        dirs[idx++] = strcache_add (defdir);
-
-        if (len > max_incl_len)
-          max_incl_len = len;
-      }
-  }
-#endif
+      if (djdir)
+        {
+          size_t len = strlen (djdir->value) + 8;
+          char *defdir = alloca (len + 1);
 
-  for (cpp = default_include_directories; *cpp != 0; ++cpp)
-    {
-      int e;
+          strcat (strcpy (defdir, djdir->value), "/include");
+          dirs[idx++] = strcache_add (defdir);
 
-      EINTRLOOP (e, stat (*cpp, &stbuf));
-      if (e == 0 && S_ISDIR (stbuf.st_mode))
-        {
-          size_t len = strlen (*cpp);
-          /* If dir name is written with trailing slashes, discard them.  */
-          while (len > 1 && (*cpp)[len - 1] == '/')
-            --len;
           if (len > max_incl_len)
             max_incl_len = len;
-          dirs[idx++] = strcache_add_len (*cpp, len);
+        }
+#endif
+      for (cpp = default_include_directories; *cpp != 0; ++cpp)
+        {
+          int e;
+
+          EINTRLOOP (e, stat (*cpp, &stbuf));
+          if (e == 0 && S_ISDIR (stbuf.st_mode))
+            {
+              size_t len = strlen (*cpp);
+              /* If dir name is written with trailing slashes, discard them.  */
+              while (len > 1 && (*cpp)[len - 1] == '/')
+                --len;
+              if (len > max_incl_len)
+                max_incl_len = len;
+              dirs[idx++] = strcache_add_len (*cpp, len);
+            }
         }
     }
 
index 5d2df3898645830bb0bf5a8d7f75dc5a0c67e25e..e46460142791028fbc77061945ad225b789116d5 100644 (file)
@@ -1,6 +1,6 @@
 #                                                                    -*-perl-*-
 
-$description ="The following test creates a makefile to test the -I option.";
+$description = "The following test creates a makefile to test the -I option.";
 
 $details = "\
 This test tests the -I option by including a filename in
@@ -9,53 +9,108 @@ under -I in the command line.  Without this option, the make
 would fail to find the included file.  It also checks to make
 sure that the -I option gets passed to recursive makes.";
 
-$makefile2 = &get_tmpfile;
+use File::Spec;
 
-open(MAKEFILE,"> $makefile");
+# Create a directory and put a makefile in it.
+# We can't put it in the current directory since that's automatically searched
+# anyway.
+my $subdir = 'idir';
+mkdir($subdir, 0777);
 
-# The Contents of the MAKEFILE ...
-
-$mf2 = substr ($makefile2, index ($makefile2, $pathsep) + 1);
-print MAKEFILE <<EOF;
-include $mf2
-all:
-\t\@echo There should be no errors for this makefile.
-EOF
-
-# END of Contents of MAKEFILE
-
-close(MAKEFILE);
-
-
-open(MAKEFILE,"> $makefile2");
-
-print MAKEFILE <<EOF;
+my $included = 'ifile.mk';
+my $ipath = File::Spec->catfile($subdir, $included);
+create_file($ipath, "
 ANOTHER:
 \t\@echo This is another included makefile
 recurse:
-\t\$(MAKE) ANOTHER -f $makefile
-EOF
+\t\@\$(MAKE) ANOTHER -f \$(main_makefile)\n");
+
+my $nosuch = "#MAKEFILE#:5: $included: $ERR_no_such_file
+#MAKE#: *** No rule to make target '$included'.  Stop.\n";
+
 
-close(MAKEFILE);
+# Verify that we get an error if we don't have -I
+run_make_test(qq!
+main_makefile := \$(firstword \$(MAKEFILE_LIST))
+all:
+\t\@echo There should be no errors for this makefile
+include $included
+!,
+              '', $nosuch, 512);
+
+# Check basic -I works
+run_make_test(undef, "-I $subdir all",
+              "There should be no errors for this makefile\n");
+
+# Check that the included target works
+run_make_test(undef, "-I $subdir ANOTHER",
+              "This is another included makefile\n");
+
+# Check that -I is passed down through MAKEFLAGS
+run_make_test(undef, "-I $subdir recurse",
+              "#MAKE#[1]: Entering directory '#PWD#'
+This is another included makefile
+#MAKE#[1]: Leaving directory '#PWD#'\n");
 
-&run_make_with_options($makefile,"-I $workdir all",&get_logfile);
+# Verify that we get an error if we add -I- to delete previous includes
+run_make_test(undef, "-I $subdir -I- all", $nosuch, 512);
 
-# Create the answer to what should be produced by this Makefile
-$answer = "There should be no errors for this makefile.\n";
-&compare_output($answer,&get_logfile(1));
+# Make another directory with the same name and make sure the right one is
+# chosen if -I- stops the path.
 
+mkdir('idir2', 0777);
+my $ipath2 = File::Spec->catfile('idir2', $included);
+create_file($ipath2, "This is a bad makefile!!\n");
 
-$answer = "This is another included makefile\n";
-&run_make_with_options($makefile,"-I $workdir ANOTHER",&get_logfile);
-&compare_output($answer,&get_logfile(1));
+run_make_test(undef, "-I idir2 -I $subdir ANOTHER",
+              "$included:1: *** missing separator.  Stop.\n", 512);
 
+run_make_test(undef, "-I idir2 -I - -I $subdir ANOTHER",
+              "This is another included makefile\n");
 
-$answer = subst_make_string("$mkpath ANOTHER -f $makefile
-#MAKE#[1]: Entering directory '#PWD#'
+# Check that -I- is passed down through MAKEFLAGS
+run_make_test(undef, "-I idir2 -I - -I $subdir recurse",
+              "#MAKE#[1]: Entering directory '#PWD#'
 This is another included makefile
 #MAKE#[1]: Leaving directory '#PWD#'\n");
 
-&run_make_with_options($makefile,"-I $workdir recurse",&get_logfile);
-&compare_output($answer,&get_logfile(1));
+unlink($ipath2);
+rmdir('idir2');
+
+# The only way to check if -I- voids included directories is to see if a file
+# exists in one and try to include it.  We very likely can't add our own files
+# to the default directories since they're probably write-protected.  This
+# won't work if none of the default directories contain any files :-/
+
+create_file('defaultdirs.mk', "\$(info \$(.INCLUDE_DIRS))\nall:;\@:\n");
+my $cmd = subst_make_string("#MAKEPATH# -f defaultdirs.mk");
+my @dirs = `$cmd`;
+my $dirs = $dirs[0];
+chomp $dirs;
+unlink('defaultdirs.mk');
+
+my $fn = undef;
+foreach my $dn (split ' ', $dirs) {
+    # On Windows the default is "." which is bogus!
+    if ($dn != '.') {
+        my @files = glob(File::Spec->catfile($dn, "*"));
+        if (@files) {
+            (undef, undef, $fn) = File::Spec->splitpath($files[0]);
+            last;
+        }
+    }
+}
+
+if ($fn) {
+    run_make_test("
+all:;
+include $fn
+",
+                  '-I-', "#MAKEFILE#:3: $fn: $ERR_no_such_file
+#MAKE#: *** No rule to make target '$fn'.  Stop.\n", 512);
+}
+
+unlink($ipath);
+rmdir($subdir);
 
 1;
index c9662e94bbf5a6ccb788e509fa6cbfe71ba7ef57..e00b06ee7998f2cfe42dd0f6ce60e05b0fc1edbb 100644 (file)
@@ -20,8 +20,7 @@ endif
 .PHONY: all
 all:;@:
 ',
-'',
-'');
+              '', '');
 
 
 # Test #2: Make sure -I paths end up in .INCLUDE_DIRS.
@@ -38,9 +37,56 @@ endif
 .PHONY: all
 all:;@:
 ',
-"-I$dir dir=$dir",
-'');
+              "-I$dir dir=$dir", '');
 
+# Find the default .INCLUDE_DIRS
+create_file('defaultdirs.mk', "\$(info \$(.INCLUDE_DIRS))\nall:;\@:\n");
+my $cmd = subst_make_string("#MAKEPATH# -f defaultdirs.mk");
+my @dirs = `$cmd`;
+my $dirs = $dirs[0];
+chomp $dirs;
+unlink('defaultdirs.mk');
+
+run_make_test("
+ifneq (\$(.INCLUDE_DIRS),$dirs)
+\$(warning Mismatched \$(.INCLUDE_DIRS) != $dirs)
+endif
+all:;\@:
+",
+              '', '');
+
+# Verify that -I- disables content from .INCLUDE_DIRS
+
+run_make_test("
+ifneq (\$(.INCLUDE_DIRS),)
+\$(warning Mismatched \$(.INCLUDE_DIRS) != )
+endif
+all:;\@:
+",
+              '-I-', '');
+
+# Prefix -I dirs to the front
+mkdir('somedir', 0777);
+
+run_make_test("
+ifneq (\$(.INCLUDE_DIRS),somedir $dirs)
+\$(warning Mismatched \$(.INCLUDE_DIRS) != somedir $dirs)
+endif
+all:;\@:
+",
+              '-I somedir', '');
+
+# Verify .INCLUDE_DIRS contains files after -I-
+
+run_make_test("
+ifneq (\$(.INCLUDE_DIRS),somedir)
+\$(warning Mismatched \$(.INCLUDE_DIRS) != somedir)
+endif
+all:;\@:
+",
+              '-I - -I somedir', '');
+
+rmdir('somedir');
 
 # This tells the test driver that the perl test script executed properly.
 1;