mirror of
https://git.savannah.gnu.org/git/make.git
synced 2025-01-29 02:20:01 +00:00
[SV 62118] Correctly handle -f- options on re-exec
The -f, -file, and --makefile options were not properly handled when re-exec'ing due to makefile updates. This problem, plus a patch and tests, was reported by Dmitry Goncharov <dgoncharov@users.sf.net>. While examining this I found another bug: after re-exec we forgot the batch file was temporary and never deleted it. I decided to fix all these problems at once using a different fix than Dmitry's: I created a new internal-only command-line option, --temp-stdin. When reconstructing the make options for a re-exec, replace the -f/--file/--makefile option that reads from stdin with --temp-stdin=<filename> so that the re-exec'd version of make knows it's a temporary batch file and will delete it. We no longer need to add the -o options because the re-exec'd make knows this is a temporary makefile and treats it as such. To simplify, replace the --file and --makefile options taking a filename, with just -f<filename> on re-exec. Some examples of the rewrite: User command line Re-exec command line ----------------- -------------------- -f- --temp-stdin=<batch> --file - --temp-stdin=<batch> -f - --makefile a.mk --temp-stdin=<batch> -fa.mk --file=a.mk -fa.mk -fa.mk -fa.mk -Rf a.mk -Rf a.mk -Rf- -R --temp-stdin=<batch> * src/main.c (stdin_offset): Remember the offset into the makefiles list of the batch file read from stdin. Remove stdin_nm. (struct command_switch): Create a new --temp-stdin option, which also updates the makefiles list. (main): Add the temporary filename to the string cache. Move the tempfile handling after checking makefile arguments for "-" so that files provided via --temp-stdin are also handled specially. When rewriting re-exec options, we may need one more than we had originally so create a new argv list. Walk through the original list and convert it to the new list, following the above process. (decode_switches): Set the stdin_offset flag if we see --temp-stdin. * tests/scripts/options/dash-f: Add many more tests, provided by Dmitry Goncharov <dgoncharov@users.sf.net>.
This commit is contained in:
parent
b9078e5bd3
commit
667d70eac2
2 changed files with 240 additions and 62 deletions
221
src/main.c
221
src/main.c
|
@ -296,10 +296,9 @@ char cmd_prefix = '\t';
|
||||||
|
|
||||||
unsigned long command_count = 1;
|
unsigned long command_count = 1;
|
||||||
|
|
||||||
/* Remember the name of the batch file from stdin. */
|
/* Remember the location of the name of the batch file from stdin. */
|
||||||
|
|
||||||
static char *stdin_nm = 0;
|
|
||||||
|
|
||||||
|
static int stdin_offset = -1;
|
||||||
|
|
||||||
|
|
||||||
/* The usage output. We write it this way to make life easier for the
|
/* The usage output. We write it this way to make life easier for the
|
||||||
|
@ -424,6 +423,8 @@ struct command_switch
|
||||||
Order matters here: this is the order MAKEFLAGS will be constructed.
|
Order matters here: this is the order MAKEFLAGS will be constructed.
|
||||||
So be sure all simple flags (single char, no argument) come first. */
|
So be sure all simple flags (single char, no argument) come first. */
|
||||||
|
|
||||||
|
#define TEMP_STDIN_OPT (CHAR_MAX+10)
|
||||||
|
|
||||||
static const struct command_switch switches[] =
|
static const struct command_switch switches[] =
|
||||||
{
|
{
|
||||||
{ 'b', ignore, 0, 0, 0, 0, 0, 0, 0 },
|
{ 'b', ignore, 0, 0, 0, 0, 0, 0, 0 },
|
||||||
|
@ -476,6 +477,8 @@ static const struct command_switch switches[] =
|
||||||
{ CHAR_MAX+8, flag_off, &silent_flag, 1, 1, 0, 0, &default_silent_flag,
|
{ CHAR_MAX+8, flag_off, &silent_flag, 1, 1, 0, 0, &default_silent_flag,
|
||||||
"no-silent" },
|
"no-silent" },
|
||||||
{ CHAR_MAX+9, string, &jobserver_auth, 1, 0, 0, 0, 0, "jobserver-fds" },
|
{ CHAR_MAX+9, string, &jobserver_auth, 1, 0, 0, 0, 0, "jobserver-fds" },
|
||||||
|
/* There is special-case handling for this in decode_switches() as well. */
|
||||||
|
{ TEMP_STDIN_OPT, filename, &makefiles, 0, 0, 0, 0, 0, "temp-stdin" },
|
||||||
{ 0, 0, 0, 0, 0, 0, 0, 0, 0 }
|
{ 0, 0, 0, 0, 0, 0, 0, 0, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1785,9 +1788,10 @@ main (int argc, char **argv, char **envp)
|
||||||
into a temporary file and read from that. */
|
into a temporary file and read from that. */
|
||||||
FILE *outfile;
|
FILE *outfile;
|
||||||
char *template;
|
char *template;
|
||||||
|
char *newnm;
|
||||||
const char *tmpdir;
|
const char *tmpdir;
|
||||||
|
|
||||||
if (stdin_nm)
|
if (stdin_offset >= 0)
|
||||||
O (fatal, NILF,
|
O (fatal, NILF,
|
||||||
_("Makefile from standard input specified twice"));
|
_("Makefile from standard input specified twice"));
|
||||||
|
|
||||||
|
@ -1824,7 +1828,7 @@ main (int argc, char **argv, char **envp)
|
||||||
#endif /* !HAVE_DOS_PATHS */
|
#endif /* !HAVE_DOS_PATHS */
|
||||||
|
|
||||||
strcat (template, DEFAULT_TMPFILE);
|
strcat (template, DEFAULT_TMPFILE);
|
||||||
outfile = get_tmpfile (&stdin_nm, template);
|
outfile = get_tmpfile (&newnm, template);
|
||||||
if (outfile == 0)
|
if (outfile == 0)
|
||||||
OSS (fatal, NILF,
|
OSS (fatal, NILF,
|
||||||
_("fopen: temporary file %s: %s"), newnm, strerror (errno));
|
_("fopen: temporary file %s: %s"), newnm, strerror (errno));
|
||||||
|
@ -1840,24 +1844,27 @@ main (int argc, char **argv, char **envp)
|
||||||
|
|
||||||
/* Replace the name that read_all_makefiles will
|
/* Replace the name that read_all_makefiles will
|
||||||
see with the name of the temporary file. */
|
see with the name of the temporary file. */
|
||||||
makefiles->list[i] = strcache_add (stdin_nm);
|
makefiles->list[i] = strcache_add (newnm);
|
||||||
|
stdin_offset = i;
|
||||||
|
|
||||||
/* Make sure the temporary file will not be remade. */
|
free (newnm);
|
||||||
{
|
|
||||||
struct file *f = enter_file (strcache_add (stdin_nm));
|
|
||||||
f->updated = 1;
|
|
||||||
f->update_status = us_success;
|
|
||||||
f->command_state = cs_finished;
|
|
||||||
/* Can't be intermediate, or it'll be removed too early for
|
|
||||||
make re-exec. */
|
|
||||||
f->intermediate = 0;
|
|
||||||
f->dontcare = 0;
|
|
||||||
/* Avoid re-exec due to stdin. */
|
|
||||||
f->last_mtime = f->mtime_before_update = f_mtime (f, 0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Make sure the temporary file is never considered updated. */
|
||||||
|
if (stdin_offset >= 0)
|
||||||
|
{
|
||||||
|
struct file *f = enter_file (makefiles->list[stdin_offset]);
|
||||||
|
f->updated = 1;
|
||||||
|
f->update_status = us_success;
|
||||||
|
f->command_state = cs_finished;
|
||||||
|
/* Can't be intermediate, or it'll be removed before make re-exec. */
|
||||||
|
f->intermediate = 0;
|
||||||
|
f->dontcare = 0;
|
||||||
|
/* Avoid re-exec due to stdin temp file timestamps. */
|
||||||
|
f->last_mtime = f->mtime_before_update = f_mtime (f, 0);
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef __EMX__ /* Don't use a SIGCHLD handler for OS/2 */
|
#ifndef __EMX__ /* Don't use a SIGCHLD handler for OS/2 */
|
||||||
#if !defined(HAVE_WAIT_NOHANG) || defined(MAKE_JOBSERVER)
|
#if !defined(HAVE_WAIT_NOHANG) || defined(MAKE_JOBSERVER)
|
||||||
/* Set up to handle children dying. This must be done before
|
/* Set up to handle children dying. This must be done before
|
||||||
|
@ -2200,10 +2207,8 @@ main (int argc, char **argv, char **envp)
|
||||||
|
|
||||||
FILE_TIMESTAMP *makefile_mtimes;
|
FILE_TIMESTAMP *makefile_mtimes;
|
||||||
struct goaldep *skipped_makefiles = NULL;
|
struct goaldep *skipped_makefiles = NULL;
|
||||||
char **aargv = NULL;
|
const char **nargv = (const char **) argv;
|
||||||
const char **nargv;
|
|
||||||
int any_failed = 0;
|
int any_failed = 0;
|
||||||
int nargc;
|
|
||||||
enum update_status status;
|
enum update_status status;
|
||||||
|
|
||||||
DB (DB_BASIC, (_("Updating makefiles....\n")));
|
DB (DB_BASIC, (_("Updating makefiles....\n")));
|
||||||
|
@ -2425,33 +2430,118 @@ main (int argc, char **argv, char **envp)
|
||||||
|
|
||||||
if (makefiles != 0)
|
if (makefiles != 0)
|
||||||
{
|
{
|
||||||
/* These names might have changed. */
|
/* Makefile names might have changed due to expansion.
|
||||||
int i, j = 0;
|
It's possible we'll need one extra argument:
|
||||||
for (i = 1; i < argc; ++i)
|
make -Rf-
|
||||||
if (strneq (argv[i], "-f", 2)) /* XXX */
|
will expand to:
|
||||||
{
|
make -R --temp-stdin=<tmpfile>
|
||||||
if (argv[i][2] == '\0')
|
so allocate more space.
|
||||||
/* This cast is OK since we never modify argv. */
|
*/
|
||||||
argv[++i] = (char *) makefiles->list[j];
|
int mfidx = 0;
|
||||||
else
|
char** av = argv;
|
||||||
argv[i] = xstrdup (concat (2, "-f", makefiles->list[j]));
|
const char** nv;
|
||||||
++j;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Add -o option for the stdin temporary file, if necessary. */
|
nv = nargv = alloca (sizeof (char*) * (argc + 1 + 1));
|
||||||
nargc = argc;
|
*(nv++) = *(av++);
|
||||||
if (stdin_nm)
|
|
||||||
{
|
for (; *av; ++av, ++nv)
|
||||||
void *m = xmalloc ((nargc + 2) * sizeof (char *));
|
{
|
||||||
aargv = m;
|
size_t len;
|
||||||
memcpy (aargv, argv, argc * sizeof (char *));
|
char *f;
|
||||||
aargv[nargc++] = xstrdup (concat (2, "-o", stdin_nm));
|
char *a = *av;
|
||||||
aargv[nargc] = 0;
|
const char *mf = makefiles->list[mfidx];
|
||||||
nargv = m;
|
|
||||||
|
len = strlen (a);
|
||||||
|
assert (len > 0);
|
||||||
|
|
||||||
|
*nv = a;
|
||||||
|
|
||||||
|
/* Not an option: we handled option args earlier. */
|
||||||
|
if (a[0] != '-')
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* See if this option specifies a filename. If so we need
|
||||||
|
to replace it with the value from makefiles->list.
|
||||||
|
|
||||||
|
To simplify, we'll replace all possible versions of this
|
||||||
|
flag with a simple "-f<name>". */
|
||||||
|
|
||||||
|
/* Handle long options. */
|
||||||
|
if (a[1] == '-')
|
||||||
|
{
|
||||||
|
if (strcmp (a, "--file") == 0 || strcmp (a, "--makefile") == 0)
|
||||||
|
/* Skip the next arg as we'll combine them. */
|
||||||
|
++av;
|
||||||
|
else if (!strneq (a, "--file=", 7)
|
||||||
|
&& !strneq (a, "--makefile=", 11))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (mfidx == stdin_offset)
|
||||||
|
{
|
||||||
|
char *na = alloca (CSTRLEN ("--temp-stdin=")
|
||||||
|
+ strlen (mf) + 1);
|
||||||
|
sprintf (na, "--temp-stdin=%s", mf);
|
||||||
|
*nv = na;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
char *na = alloca (strlen (mf) + 3);
|
||||||
|
sprintf (na, "-f%s", mf);
|
||||||
|
*nv = na;
|
||||||
|
}
|
||||||
|
|
||||||
|
++mfidx;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Handle short options. If 'f' is the last option, it may
|
||||||
|
be followed by <name>. */
|
||||||
|
f = strchr (a, 'f');
|
||||||
|
if (!f)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* If there's an extra argument option skip it. */
|
||||||
|
if (f[1] == '\0')
|
||||||
|
++av;
|
||||||
|
|
||||||
|
if (mfidx == stdin_offset)
|
||||||
|
{
|
||||||
|
const size_t al = f - a;
|
||||||
|
char *na;
|
||||||
|
|
||||||
|
if (al > 1)
|
||||||
|
{
|
||||||
|
/* Preserve the prior options. */
|
||||||
|
na = alloca (al + 1);
|
||||||
|
memcpy (na, a, al);
|
||||||
|
na[al] = '\0';
|
||||||
|
*(nv++) = na;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Remove the "f" and any subsequent content. */
|
||||||
|
na = alloca (CSTRLEN ("--temp-stdin=") + strlen (mf) + 1);
|
||||||
|
sprintf (na, "--temp-stdin=%s", mf);
|
||||||
|
*nv = na;
|
||||||
|
}
|
||||||
|
else if (f[1] == '\0')
|
||||||
|
/* -f <name> or -xyzf <name>. Replace the name. */
|
||||||
|
*(++nv) = mf;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* -f<name> or -xyzf<name>. */
|
||||||
|
const size_t al = f - a + 1;
|
||||||
|
const size_t ml = strlen (mf) + 1;
|
||||||
|
char *na = alloca (al + ml);
|
||||||
|
memcpy (na, a, al);
|
||||||
|
memcpy (na + al, mf, ml);
|
||||||
|
*nv = na;
|
||||||
|
}
|
||||||
|
|
||||||
|
++mfidx;
|
||||||
|
}
|
||||||
|
|
||||||
|
*nv = NULL;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
nargv = (const char**)argv;
|
|
||||||
|
|
||||||
if (directories != 0 && directories->idx > 0)
|
if (directories != 0 && directories->idx > 0)
|
||||||
{
|
{
|
||||||
|
@ -2568,7 +2658,6 @@ main (int argc, char **argv, char **envp)
|
||||||
|
|
||||||
/* We shouldn't get here but just in case. */
|
/* We shouldn't get here but just in case. */
|
||||||
jobserver_post_child(1);
|
jobserver_post_child(1);
|
||||||
free (aargv);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2595,10 +2684,13 @@ main (int argc, char **argv, char **envp)
|
||||||
|
|
||||||
/* If there is a temp file from reading a makefile from stdin, get rid of
|
/* If there is a temp file from reading a makefile from stdin, get rid of
|
||||||
it now. */
|
it now. */
|
||||||
if (stdin_nm && unlink (stdin_nm) < 0 && errno != ENOENT)
|
if (stdin_offset >= 0)
|
||||||
perror_with_name (_("unlink (temporary file): "), stdin_nm);
|
{
|
||||||
|
const char *nm = makefiles->list[stdin_offset];
|
||||||
stdin_nm = NULL;
|
if (unlink (nm) < 0 && errno != ENOENT)
|
||||||
|
perror_with_name (_("unlink (temporary file): "), nm);
|
||||||
|
stdin_offset = -1;
|
||||||
|
}
|
||||||
|
|
||||||
/* If there were no command-line goals, use the default. */
|
/* If there were no command-line goals, use the default. */
|
||||||
if (goals == 0)
|
if (goals == 0)
|
||||||
|
@ -3056,10 +3148,18 @@ decode_switches (int argc, const char **argv, int env)
|
||||||
sl->list = xrealloc ((void *)sl->list,
|
sl->list = xrealloc ((void *)sl->list,
|
||||||
sl->max * sizeof (char *));
|
sl->max * sizeof (char *));
|
||||||
}
|
}
|
||||||
if (cs->type == filename)
|
if (cs->type == strlist)
|
||||||
sl->list[sl->idx++] = expand_command_line_file (coptarg);
|
|
||||||
else
|
|
||||||
sl->list[sl->idx++] = xstrdup (coptarg);
|
sl->list[sl->idx++] = xstrdup (coptarg);
|
||||||
|
else if (cs->c == TEMP_STDIN_OPT)
|
||||||
|
{
|
||||||
|
if (stdin_offset > 0)
|
||||||
|
fatal (NILF, 0, "INTERNAL: multiple --temp-stdin options provided!");
|
||||||
|
/* We don't need to expand the temp file. */
|
||||||
|
stdin_offset = sl->idx;
|
||||||
|
sl->list[sl->idx++] = strcache_add (coptarg);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
sl->list[sl->idx++] = expand_command_line_file (coptarg);
|
||||||
sl->list[sl->idx] = 0;
|
sl->list[sl->idx] = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -3589,10 +3689,13 @@ die (int status)
|
||||||
print_version ();
|
print_version ();
|
||||||
|
|
||||||
/* Get rid of a temp file from reading a makefile from stdin. */
|
/* Get rid of a temp file from reading a makefile from stdin. */
|
||||||
if (stdin_nm && unlink (stdin_nm) < 0 && errno != ENOENT)
|
if (stdin_offset >= 0)
|
||||||
perror_with_name (_("unlink (temporary file): "), stdin_nm);
|
{
|
||||||
|
const char *nm = makefiles->list[stdin_offset];
|
||||||
stdin_nm = NULL;
|
if (unlink (nm) < 0 && errno != ENOENT)
|
||||||
|
perror_with_name (_("unlink (temporary file): "), nm);
|
||||||
|
stdin_offset = -1;
|
||||||
|
}
|
||||||
|
|
||||||
/* Wait for children to die. */
|
/* Wait for children to die. */
|
||||||
err = (status != 0);
|
err = (status != 0);
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
# -*-perl-*-
|
||||||
$description = "The following test tests that if you specify greater \n"
|
$description = "The following test tests that if you specify greater \n"
|
||||||
."than one '-f makefilename' on the command line, \n"
|
."than one '-f makefilename' on the command line, \n"
|
||||||
."that make concatenates them. This test creates three \n"
|
."that make concatenates them. This test creates three \n"
|
||||||
|
@ -50,7 +51,7 @@ $answer = "This is the output from makefile 2\n";
|
||||||
&run_make_with_options($makefile,"-f $makefile2 -f $makefile3 TWO",&get_logfile,0);
|
&run_make_with_options($makefile,"-f $makefile2 -f $makefile3 TWO",&get_logfile,0);
|
||||||
|
|
||||||
&compare_output($answer,&get_logfile(1));
|
&compare_output($answer,&get_logfile(1));
|
||||||
|
|
||||||
|
|
||||||
# Run Make again with the rule from the third makefile: THREE
|
# Run Make again with the rule from the third makefile: THREE
|
||||||
|
|
||||||
|
@ -70,16 +71,90 @@ $answer .= "This is the output from the original makefile\n";
|
||||||
$answer .= "This is the output from makefile 3\n";
|
$answer .= "This is the output from makefile 3\n";
|
||||||
&run_make_with_options($makefile,
|
&run_make_with_options($makefile,
|
||||||
"-f $makefile2 -f $makefile3 TWO all THREE",
|
"-f $makefile2 -f $makefile3 TWO all THREE",
|
||||||
&get_logfile,
|
&get_logfile,
|
||||||
0);
|
0);
|
||||||
&compare_output($answer,&get_logfile(1));
|
&compare_output($answer,&get_logfile(1));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# sv 62118.
|
||||||
|
# Validate all sorts of -f etc. options
|
||||||
|
|
||||||
|
my $hello = 'hello.mk';
|
||||||
|
my $bye = 'bye.mk';
|
||||||
|
my $byesrc = 'bye.mk.src';
|
||||||
|
|
||||||
|
unlink($hello, $bye, $byesrc);
|
||||||
|
|
||||||
|
create_file($hello, 'all:; $(info hello, world)
|
||||||
|
');
|
||||||
|
|
||||||
|
create_file($bye, 'def:; $(info bye, world)
|
||||||
|
bye.mk: bye.mk.src; touch $@
|
||||||
|
bye.mk.src:; touch $@
|
||||||
|
');
|
||||||
|
|
||||||
|
# These invocations use the empty filename string so that the test framework
|
||||||
|
# doesn't add any -f options on its own.
|
||||||
|
|
||||||
|
# Incorrect order of options. -R follows -f.
|
||||||
|
# Invocation of make is equivalent to
|
||||||
|
# echo 'all:; $(info hello, world)' | make -f bye.mk -fR - all
|
||||||
|
# There is bye.mk, but there is no 'R'.
|
||||||
|
# make runs the recipes from bye.mk and prints the error about missing 'R'.
|
||||||
|
|
||||||
|
# Ensure the newly created bye.src.mk is newer than bye.mk.
|
||||||
|
&utouch(-600, $bye);
|
||||||
|
run_make_test('', "-f$bye -fR - all", "#MAKE#: R: No such file or directory
|
||||||
|
touch bye.mk.src
|
||||||
|
touch bye.mk
|
||||||
|
#MAKE#: *** No rule to make target 'R'. Stop.
|
||||||
|
", 512);
|
||||||
|
|
||||||
|
# Test double -f-.
|
||||||
|
my @opts = ('-f- -f-', '-f - -f -', '-f- -f -', '-f - -f-',
|
||||||
|
'-f- --file=-', '-f- --file -', '-f - --file=-', '-f - --file -',
|
||||||
|
'-f- --makefile=-', '-f- --makefile -',
|
||||||
|
'-f - --makefile=-', '-f - --makefile -',
|
||||||
|
'--file=- --makefile=-', '--file=- --makefile -',
|
||||||
|
'--file - --makefile=-', '--file - --makefile -');
|
||||||
|
|
||||||
|
for my $opt (@opts) {
|
||||||
|
# We shouldn't need this; if the options are wrong then make shouldn't try
|
||||||
|
# to read from stdin.
|
||||||
|
close(STDIN);
|
||||||
|
open(STDIN, "<", $hello) || die "$0: cannot open $hello for reading: $!";
|
||||||
|
run_make_test('', "-f$bye $opt", "#MAKE#: *** Makefile from standard input specified twice. Stop.\n", 512);
|
||||||
|
}
|
||||||
|
|
||||||
|
# -f is not followed by filename.
|
||||||
|
my @opts = ('-f', '--file', '--makefile');
|
||||||
|
my $answer = "/requires an argument/";
|
||||||
|
for my $opt (@opts) {
|
||||||
|
run_make_test('', $opt, $answer, 512);
|
||||||
|
}
|
||||||
|
|
||||||
|
# Test that make correctly parses all possible syntaxes to pipe make code to
|
||||||
|
# the standard input.
|
||||||
|
|
||||||
|
my $answer = "touch bye.mk.src
|
||||||
|
touch bye.mk
|
||||||
|
hello, world
|
||||||
|
#MAKE#: 'all' is up to date.\n";
|
||||||
|
|
||||||
|
my @opts = ('-f- all', '-f - all', '-Rf- all', '-Rf - all',
|
||||||
|
'--file=- all', '--file - all',
|
||||||
|
'--makefile=- all', '--makefile - all');
|
||||||
|
for my $opt (@opts) {
|
||||||
|
unlink($byesrc);
|
||||||
|
close(STDIN);
|
||||||
|
open(STDIN, "<", $hello) || die "$0: cannot open $hello for reading: $!";
|
||||||
|
# Ensure the newly created bye.src.mk is newer than bye.mk.
|
||||||
|
&utouch(-600, $bye);
|
||||||
|
|
||||||
|
run_make_test('', "-f$bye $opt", $answer);
|
||||||
|
}
|
||||||
|
|
||||||
|
unlink($hello, $bye, $byesrc);
|
||||||
|
|
||||||
|
# This tells the test driver that the perl test script executed properly.
|
||||||
|
1;
|
||||||
|
|
Loading…
Reference in a new issue