mirror of
https://git.savannah.gnu.org/git/make.git
synced 2024-11-25 04:35:44 +00:00
[SV 60188] Explicit prereqs cannot be intermediate files
If a prereq of a pattern is an explicit target, it should not be considered an intermediate file. (Minor tweaks by Paul Smith <psmith@gnu.org>) * src/dep.h (struct nameseq): Add is_explicit flag. * src/implicit.c (struct patdeps): Ditto. (pattern_search): Set the is_explicit flag appropriately for each prerequisite, based on whether it contained a pattern or not. Update the help output to note implicit vs. explicit prereqs. * tests/scripts/features/double_colon: Add tests. * tests/scripts/features/grouped_targets: Ditto. * tests/scripts/features/patternrules: Ditto. * tests/scripts/features/se_implicit: Ditto. * tests/scripts/features/statipattrules: Ditto.
This commit is contained in:
parent
144f436c4b
commit
510e5ce801
7 changed files with 233 additions and 6 deletions
|
@ -38,7 +38,10 @@ struct nameseq
|
|||
|
||||
/* Structure representing one dependency of a file.
|
||||
Each struct file's 'deps' points to a chain of these, through 'next'.
|
||||
'stem' is the stem for this dep line of static pattern rule or NULL. */
|
||||
'stem' is the stem for this dep line of static pattern rule or NULL.
|
||||
explicit is set when implicit rule search is performed and the prerequisite
|
||||
does not contain %. When explicit is set the file is not intermediate. */
|
||||
|
||||
|
||||
#define DEP(_t) \
|
||||
NAMESEQ (_t); \
|
||||
|
@ -49,7 +52,8 @@ struct nameseq
|
|||
unsigned int ignore_mtime : 1; \
|
||||
unsigned int staticpattern : 1; \
|
||||
unsigned int need_2nd_expansion : 1; \
|
||||
unsigned int ignore_automatic_vars : 1
|
||||
unsigned int ignore_automatic_vars : 1; \
|
||||
unsigned int is_explicit : 1;
|
||||
|
||||
struct dep
|
||||
{
|
||||
|
|
|
@ -153,6 +153,7 @@ struct patdeps
|
|||
struct file *file;
|
||||
unsigned int ignore_mtime : 1;
|
||||
unsigned int ignore_automatic_vars : 1;
|
||||
unsigned int is_explicit : 1;
|
||||
};
|
||||
|
||||
/* This structure stores information about pattern rules that we need
|
||||
|
@ -540,6 +541,7 @@ pattern_search (struct file *file, int archive,
|
|||
/* If we don't need a second expansion, just replace the %. */
|
||||
if (! dep->need_2nd_expansion)
|
||||
{
|
||||
int is_explicit = 1;
|
||||
p = strchr (nptr, '%');
|
||||
if (p == 0)
|
||||
strcpy (depname, nptr);
|
||||
|
@ -556,6 +558,7 @@ pattern_search (struct file *file, int archive,
|
|||
memcpy (o, stem, stemlen);
|
||||
o += stemlen;
|
||||
strcpy (o, p + 1);
|
||||
is_explicit = 0;
|
||||
}
|
||||
|
||||
/* Parse the expanded string. It might have wildcards. */
|
||||
|
@ -566,6 +569,7 @@ pattern_search (struct file *file, int archive,
|
|||
++deps_found;
|
||||
d->ignore_mtime = dep->ignore_mtime;
|
||||
d->ignore_automatic_vars = dep->ignore_automatic_vars;
|
||||
d->is_explicit = is_explicit;
|
||||
}
|
||||
|
||||
/* We've used up this dep, so next time get a new one. */
|
||||
|
@ -586,6 +590,7 @@ pattern_search (struct file *file, int archive,
|
|||
int add_dir = 0;
|
||||
size_t len;
|
||||
struct dep **dptr;
|
||||
int is_explicit;
|
||||
|
||||
nptr = get_next_word (nptr, &len);
|
||||
if (nptr == 0)
|
||||
|
@ -615,6 +620,7 @@ pattern_search (struct file *file, int archive,
|
|||
{
|
||||
memcpy (depname, nptr, len);
|
||||
depname[len] = '\0';
|
||||
is_explicit = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -635,6 +641,7 @@ pattern_search (struct file *file, int archive,
|
|||
}
|
||||
memcpy (o, p + 1, len - i - 1);
|
||||
o[len - i - 1] = '\0';
|
||||
is_explicit = 0;
|
||||
}
|
||||
|
||||
/* Set up for the next word. */
|
||||
|
@ -674,6 +681,7 @@ pattern_search (struct file *file, int archive,
|
|||
++deps_found;
|
||||
if (order_only)
|
||||
d->ignore_mtime = 1;
|
||||
d->is_explicit = is_explicit;
|
||||
dptr = &d->next;
|
||||
}
|
||||
|
||||
|
@ -726,6 +734,7 @@ pattern_search (struct file *file, int archive,
|
|||
memset (pat, '\0', sizeof (struct patdeps));
|
||||
pat->ignore_mtime = d->ignore_mtime;
|
||||
pat->ignore_automatic_vars = d->ignore_automatic_vars;
|
||||
pat->is_explicit = d->is_explicit;
|
||||
|
||||
DBS (DB_IMPLICIT,
|
||||
(is_rule
|
||||
|
@ -777,13 +786,14 @@ pattern_search (struct file *file, int archive,
|
|||
}
|
||||
|
||||
/* We could not find the file in any place we should look.
|
||||
Try to make this dependency as an intermediate file, but
|
||||
Look for an implicit rule to make this dependency, but
|
||||
only on the second pass. */
|
||||
|
||||
if (intermed_ok)
|
||||
{
|
||||
DBS (DB_IMPLICIT,
|
||||
(_("Looking for a rule with intermediate file '%s'.\n"),
|
||||
(_("Looking for a rule with %s file '%s'.\n"),
|
||||
d->is_explicit ? "explicit" : "intermediate",
|
||||
d->name));
|
||||
|
||||
if (int_file == 0)
|
||||
|
@ -899,7 +909,7 @@ pattern_search (struct file *file, int archive,
|
|||
f->pat_searched = imf->pat_searched;
|
||||
f->also_make = imf->also_make;
|
||||
f->is_target = 1;
|
||||
f->intermediate = 1;
|
||||
f->intermediate = !pat->is_explicit;
|
||||
f->tried_implicit = 1;
|
||||
|
||||
imf = lookup_file (pat->pattern);
|
||||
|
@ -916,6 +926,7 @@ pattern_search (struct file *file, int archive,
|
|||
|
||||
dep = alloc_dep ();
|
||||
dep->ignore_mtime = pat->ignore_mtime;
|
||||
dep->is_explicit = pat->is_explicit;
|
||||
dep->ignore_automatic_vars = pat->ignore_automatic_vars;
|
||||
s = strcache_add (pat->name);
|
||||
if (recursions)
|
||||
|
|
|
@ -212,6 +212,21 @@ FORCE:
|
|||
|
||||
unlink('joe-is-forced');
|
||||
|
||||
# sv 60188.
|
||||
# Even though test.x is explicitly mentioned, terminal pattern rules still
|
||||
# apply only if the prerequisite exists.
|
||||
touch('hello.z');
|
||||
|
||||
run_make_test(q!
|
||||
all: hello.z
|
||||
%.z:: test.x ; touch $@
|
||||
%.x: ;
|
||||
!, '', "#MAKE#: Nothing to be done for 'all'.\n");
|
||||
|
||||
unlink('hello.z');
|
||||
|
||||
|
||||
|
||||
# This tells the test driver that the perl test script executed properly.
|
||||
1;
|
||||
|
||||
|
|
|
@ -129,5 +129,31 @@ f g h&:: ; @echo Z
|
|||
'',
|
||||
"Z");
|
||||
|
||||
# sv 60188.
|
||||
# Test that a file explicitly mentioned by the user and made by an implicit
|
||||
# rule is not considered intermediate.
|
||||
|
||||
touch('hello.z');
|
||||
touch('hello.q');
|
||||
|
||||
# subtest 1
|
||||
# hello.x is not explicitly mentioned and thus is an intermediate file.
|
||||
run_make_test(q!
|
||||
all: hello.z
|
||||
%.z %.q: %.x ; touch $*.z $*.q
|
||||
%.x: ;
|
||||
!, '', "#MAKE#: Nothing to be done for 'all'.\n");
|
||||
|
||||
# subtest 2
|
||||
# test.x is explicitly mentioned and thus is not an intermediate file.
|
||||
run_make_test(q!
|
||||
all: hello.z
|
||||
%.z %.q: %.x test.x ; @echo $*.z $*.q
|
||||
%.x: ;
|
||||
!, '', "hello.z hello.q\n");
|
||||
|
||||
unlink('hello.z');
|
||||
unlink('hello.q');
|
||||
|
||||
# This tells the test driver that the perl test script executed properly.
|
||||
1;
|
||||
|
|
|
@ -18,7 +18,7 @@ $dir =~ s,.*/([^/]+)$,../$1,;
|
|||
run_make_test(q!
|
||||
.PHONY: all
|
||||
|
||||
all: case.1 case.2 case.3
|
||||
all: case.1 case.2 case.3 case.4
|
||||
|
||||
# We can't have this, due to "Implicit Rule Search Algorithm" step 5c
|
||||
#xxx: void
|
||||
|
@ -43,6 +43,13 @@ all: case.1 case.2 case.3
|
|||
@exit 0
|
||||
|
||||
3.implicit-phony:
|
||||
|
||||
# 4 - explicitly mentioned file made by an implicit rule
|
||||
%.4: void
|
||||
@exit 1
|
||||
%.4: test.x
|
||||
@exit 0
|
||||
%.x: ;
|
||||
!, '', '');
|
||||
|
||||
# TEST #1: make sure files that are built via implicit rules are marked
|
||||
|
@ -244,6 +251,86 @@ run_make_test(q!
|
|||
|
||||
unlink('some file.xx', 'some file.yy');
|
||||
|
||||
|
||||
# sv 60188.
|
||||
# Test that a file explicitly mentioned by the user and made by an implicit
|
||||
# rule is not considered intermediate.
|
||||
|
||||
touch('hello.z');
|
||||
unlink('hello.x');
|
||||
unlink('test.x');
|
||||
|
||||
# subtest 1
|
||||
# hello.x is not explicitly mentioned and thus is an intermediate file.
|
||||
run_make_test(q!
|
||||
all: hello.z
|
||||
%.z: %.x
|
||||
touch $@
|
||||
%.x: ;
|
||||
!, '', "#MAKE#: Nothing to be done for 'all'.\n");
|
||||
|
||||
# subtest 2
|
||||
# test.x is explicitly mentioned and thus is not an intermediate file.
|
||||
run_make_test(q!
|
||||
all: hello.z
|
||||
%.z: %.x test.x
|
||||
touch $@
|
||||
%.x: ;
|
||||
!, '', "touch hello.z");
|
||||
|
||||
unlink('hello.z');
|
||||
|
||||
# sv 60188.
|
||||
# Test that a file explicitly mentioned by the user and made by an implicit
|
||||
# rule is not considered intermediate, even when the builtin rules are used.
|
||||
|
||||
touch('hello.x');
|
||||
touch('test.x');
|
||||
touch('hello.tsk');
|
||||
|
||||
# subtest 1
|
||||
# hello.o is not explicitly mentioned and thus is an intermediate file.
|
||||
run_make_test(q!
|
||||
all: hello.tsk
|
||||
%.tsk: %.z ; @echo $@
|
||||
%.z : %.x ; @echo $@
|
||||
!, '', "#MAKE#: Nothing to be done for 'all'.\n");
|
||||
|
||||
# subtest 2
|
||||
# test.z is explicitly mentioned and thus is not an intermediate file.
|
||||
# test.z is built first because until it's built we don't know if we
|
||||
# need to rebuild the intermediate hello.z
|
||||
run_make_test(q!
|
||||
all: hello.tsk
|
||||
%.tsk: %.z test.z ; @echo $@
|
||||
%.z : %.x ; @echo $@
|
||||
!, '', "test.z\nhello.z\nhello.tsk\n");
|
||||
|
||||
# subtest 3
|
||||
# hello.o is not explicitly mentioned and thus is an intermediate file.
|
||||
run_make_test(q!
|
||||
all: hello.tsk
|
||||
dep:=%.o
|
||||
%.tsk: $(dep) ; @echo $@
|
||||
!, '', "#MAKE#: Nothing to be done for 'all'.\n");
|
||||
|
||||
# subtest 4
|
||||
# Even when test.z is constructed from 2 variables it is still explicitly
|
||||
# mentioned and thus is not an intermediate file.
|
||||
# test.z is built first because until it's built we don't know if we
|
||||
# need to rebuild the intermediate hello.z
|
||||
run_make_test(q!
|
||||
all: hello.tsk
|
||||
name:=test
|
||||
suf:=.z
|
||||
%.tsk: %.z $(name)$(suf) ; @echo $@
|
||||
%.z: %.x ; @echo $@
|
||||
!, '', "test.z\nhello.z\nhello.tsk\n");
|
||||
|
||||
unlink('hello.x');
|
||||
unlink('test.x');
|
||||
|
||||
|
||||
# This tells the test driver that the perl test script executed properly.
|
||||
1;
|
||||
|
||||
|
|
|
@ -262,5 +262,68 @@ run_make_test(q!
|
|||
!,
|
||||
'q/ux', "q/u\nq/u\n");
|
||||
|
||||
|
||||
|
||||
# sv 60188.
|
||||
# Test that a file explicitly mentioned by the user and made by an implicit
|
||||
# rule is not considered intermediate.
|
||||
|
||||
touch('hello.z');
|
||||
|
||||
# subtest 1.
|
||||
# hello.x is derived from the stem and thus is an intermediate file.
|
||||
run_make_test(q!
|
||||
.SECONDEXPANSION:
|
||||
dep:=.x
|
||||
all: hello.z
|
||||
%.z: %$$(dep) ; @echo $@
|
||||
%.x: ;
|
||||
!, '', "#MAKE#: Nothing to be done for 'all'.\n");
|
||||
|
||||
|
||||
# subtest 2.
|
||||
# test.x is explicitly mentioned and thus is not an intermediate file.
|
||||
run_make_test(q!
|
||||
.SECONDEXPANSION:
|
||||
dep:=test.x
|
||||
all: hello.z
|
||||
%.z: %.x $$(dep) ; @echo $@
|
||||
%.x: ;
|
||||
!, '', "hello.z\n");
|
||||
|
||||
unlink('hello.z');
|
||||
|
||||
|
||||
# sv 60188.
|
||||
# Test that a file explicitly mentioned by the user and made by an implicit
|
||||
# rule is not considered intermediate, even when the builtin rules are used.
|
||||
|
||||
touch('hello.x');
|
||||
touch('hello.tsk');
|
||||
|
||||
# subtest 1.
|
||||
# hello.z is explicitly mentioned and thus is not an intermediate file.
|
||||
run_make_test(q!
|
||||
.SECONDEXPANSION:
|
||||
dep:=hello.z
|
||||
all: hello.tsk
|
||||
%.tsk: $$(dep) ; @echo $@
|
||||
%.z : %.x ; @echo $@
|
||||
!, '', "hello.z\nhello.tsk");
|
||||
|
||||
# subtest 2.
|
||||
# hello.z is derived from the stem and thus is an intermediate file.
|
||||
run_make_test(q!
|
||||
.SECONDEXPANSION:
|
||||
dep:=.z
|
||||
all: hello.tsk
|
||||
%.tsk: %$$(dep) ; @echo $@
|
||||
%.z : %.x ; @echo $@
|
||||
!, '', "#MAKE#: Nothing to be done for 'all'.\n");
|
||||
|
||||
unlink('hello.x');
|
||||
unlink('hello.tsk');
|
||||
|
||||
|
||||
# This tells the test driver that the perl test script executed properly.
|
||||
1;
|
||||
|
|
|
@ -108,4 +108,25 @@ all.foo.bar:
|
|||
'all.foo
|
||||
all.one all-one all.foo.two all.foo-two');
|
||||
|
||||
# Test #8:
|
||||
# sv 60188.
|
||||
# Static pattern rules are considered explicit rules: no prerequisite of
|
||||
# a static pattern rule can ever be considered intermediate.
|
||||
|
||||
touch('hello.z');
|
||||
|
||||
# subtest 1
|
||||
run_make_test(q!
|
||||
hello.z: %.z: %.x ; @echo $@
|
||||
%.x: ;
|
||||
!, '', "hello.z\n");
|
||||
|
||||
# subtest 2
|
||||
run_make_test(q!
|
||||
hello.z: %.z: test.x ; @echo $@
|
||||
%.x: ;
|
||||
!, '', "hello.z\n");
|
||||
|
||||
unlink('hello.z');
|
||||
|
||||
1;
|
||||
|
|
Loading…
Reference in a new issue