(Make version 3.79.) Consider this Makefile:
%.1 %.2: %.src
cp $< $*.1
cp $< $*.2
Create a file sub/foo.src and 'make -Rp sub/foo.1'. Here's
an excerpt from the output:
# Not a target:
sub/foo.1: sub/foo.src
# Command-line target.
# Implicit rule search has been done.
# Implicit/static pattern stem: `sub/foo'
# Also makes: foo.2
# Last modified 2000-06-15 17:49:23
# File has been updated.
# Successfully updated.
# automatic
# ^ := sub/foo.src
# automatic
# @ := sub/foo.1
# automatic
# + := sub/foo.src
# automatic
# ? := sub/foo.src
# automatic
# * := sub/foo
# automatic
# % :=
# automatic
# < := sub/foo.src
# 7 variables in 23 hash buckets.
# average of 0.3 variables per bucket, max 2 in one bucket.
# commands to execute (from `Makefile', line 2):
cp $< $*.1
cp $< $*.2
# Not a target:
foo.2:
# Implicit rule search has not been done.
# File does not exist.
# File has been updated.
# Successfully updated.
Note that make is incorrectly dropping the subdirectory path from the
extra targets. Here's a patch to fix it:
diff -rc /x/sethml/src/make-3.79/implicit.c ./implicit.c
*** /x/sethml/src/make-3.79/implicit.c Fri Jan 21 21:43:03 2000
--- ./implicit.c Thu Jun 15 17:28:50 2000
***************
*** 117,122 ****
--- 117,123 ----
/* The start and length of the stem of FILENAME for the current rule. */
register char *stem = 0;
register unsigned int stemlen = 0;
+ unsigned int fstemlen;
/* Buffer in which we store all the rules that are possibly applicable. */
struct rule **tryrules
***************
*** 582,599 ****
}
if (!checked_lastslash[foundrule])
! /* Always allocate new storage, since STEM might be
! on the stack for an intermediate file. */
! file->stem = savestring (stem, stemlen);
else
{
/* We want to prepend the directory from
the original FILENAME onto the stem. */
! file->stem = (char *) xmalloc (((lastslash + 1) - filename)
! + stemlen + 1);
bcopy (filename, file->stem, (lastslash + 1) - filename);
bcopy (stem, file->stem + ((lastslash + 1) - filename), stemlen);
! file->stem[((lastslash + 1) - filename) + stemlen] = '\0';
}
file->cmds = rule->cmds;
--- 583,603 ----
}
if (!checked_lastslash[foundrule])
! {
! /* Always allocate new storage, since STEM might be
! on the stack for an intermediate file. */
! file->stem = savestring (stem, stemlen);
! fstemlen = stemlen;
! }
else
{
/* We want to prepend the directory from
the original FILENAME onto the stem. */
! fstemlen = ((lastslash + 1) - filename) + stemlen;
! file->stem = (char *) xmalloc (fstemlen + 1);
bcopy (filename, file->stem, (lastslash + 1) - filename);
bcopy (stem, file->stem + ((lastslash + 1) - filename), stemlen);
! file->stem[fstemlen] = '\0';
}
file->cmds = rule->cmds;
***************
*** 606,617 ****
if (i != matches[foundrule])
{
struct dep *new = (struct dep *) xmalloc (sizeof (struct dep));
! new->name = p = (char *) xmalloc (rule->lens[i] + stemlen + 1);
bcopy (rule->targets[i], p,
rule->suffixes[i] - rule->targets[i] - 1);
p += rule->suffixes[i] - rule->targets[i] - 1;
! bcopy (stem, p, stemlen);
! p += stemlen;
bcopy (rule->suffixes[i], p,
rule->lens[i] - (rule->suffixes[i] - rule->targets[i]) + 1);
new->file = enter_file (new->name);
--- 610,621 ----
if (i != matches[foundrule])
{
struct dep *new = (struct dep *) xmalloc (sizeof (struct dep));
! new->name = p = (char *) xmalloc (rule->lens[i] + fstemlen + 1);
bcopy (rule->targets[i], p,
rule->suffixes[i] - rule->targets[i] - 1);
p += rule->suffixes[i] - rule->targets[i] - 1;
! bcopy (file->stem, p, fstemlen);
! p += fstemlen;
bcopy (rule->suffixes[i], p,
rule->lens[i] - (rule->suffixes[i] - rule->targets[i]) + 1);
new->file = enter_file (new->name);