/* 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); \
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
{
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
/* 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);
memcpy (o, stem, stemlen);
o += stemlen;
strcpy (o, p + 1);
+ is_explicit = 0;
}
/* Parse the expanded string. It might have wildcards. */
++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. */
int add_dir = 0;
size_t len;
struct dep **dptr;
+ int is_explicit;
nptr = get_next_word (nptr, &len);
if (nptr == 0)
{
memcpy (depname, nptr, len);
depname[len] = '\0';
+ is_explicit = 1;
}
else
{
}
memcpy (o, p + 1, len - i - 1);
o[len - i - 1] = '\0';
+ is_explicit = 0;
}
/* Set up for the next word. */
++deps_found;
if (order_only)
d->ignore_mtime = 1;
+ d->is_explicit = is_explicit;
dptr = &d->next;
}
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
}
/* 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)
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);
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)
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;
'',
"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;
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
@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
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;
!,
'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;
'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;