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).
@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
@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
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}
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 *);
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)
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);
}
/* 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);
+ }
}
}
# -*-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
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;
.PHONY: all
all:;@:
',
-'',
-'');
+ '', '');
# Test #2: Make sure -I paths end up in .INCLUDE_DIRS.
.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;