mirror of
https://github.com/mirror/make.git
synced 2025-01-27 04:40:33 +08:00
Implement SysV-style $$@ support. I looked at E.Parmelan's patch but
decided to implement this a different way, and didn't use it.
This commit is contained in:
parent
6c9a393f95
commit
4d72c4c11e
15
ChangeLog
15
ChangeLog
@ -1,3 +1,18 @@
|
||||
2002-07-10 Paul D. Smith <psmith@gnu.org>
|
||||
|
||||
Implement the SysV make syntax $$@, $$(@D), and $$(@F) in the
|
||||
prerequisite list. A real SysV make will expand the entire
|
||||
prerequisites list _twice_: we don't do that as it's a big
|
||||
backward-compatibility problem. We only replace those specific
|
||||
variables.
|
||||
|
||||
* read.c (record_files): Replace any $@, $(@D), and $(@F) variable
|
||||
references left in the list of prerequisites. Check for .POSIX as
|
||||
we record targets, so we can disable non-POSIX behavior while
|
||||
reading makefiles as well as running them.
|
||||
(eval): Check the prerequisite list to see if we have anything
|
||||
that looks like a SysV prerequisite variable reference.
|
||||
|
||||
2002-07-09 Paul D. Smith <psmith@gnu.org>
|
||||
|
||||
* doc/make.texi (Prerequisite Types): Add a new section describing
|
||||
|
11
NEWS
11
NEWS
@ -1,6 +1,6 @@
|
||||
GNU make NEWS -*-indented-text-*-
|
||||
History of user-visible changes.
|
||||
06 July 2002
|
||||
10 July 2002
|
||||
|
||||
Copyright (C) 2002 Free Software Foundation, Inc.
|
||||
See the end for copying conditions.
|
||||
@ -12,7 +12,7 @@ Please send GNU make bug reports to <bug-make@gnu.org>.
|
||||
See the README file and the GNU make manual for details on sending bug
|
||||
reports.
|
||||
|
||||
Version <next>
|
||||
Version 3.80
|
||||
|
||||
* A new feature exists: order-only prerequisites. These prerequisites
|
||||
affect the order in which targets are built, but they do not impact
|
||||
@ -21,6 +21,13 @@ Version <next>
|
||||
requiring that target A will always be rebuilt if target B is updated.
|
||||
Patch for this feature provided by Greg McGary <greg@mcgary.org>.
|
||||
|
||||
* For compatibility with SysV make, GNU make now supports the peculiar
|
||||
syntax $$@, $$(@D), and $$(@F) in the prerequisites list of a rule.
|
||||
This syntax is only valid within explicit and static pattern rules: it
|
||||
cannot be used in implicit (suffix or pattern) rules. Edouard G. Parmelan
|
||||
<egp@free.fr> provided a patch implementing this feature; however, I
|
||||
decided to implemented it myself in a different way.
|
||||
|
||||
* A new function is defined: $(quote ...). The argument to this
|
||||
function is the _name_ of a variable. The result of the function is
|
||||
the value of the variable, without having been expanded.
|
||||
|
@ -8410,6 +8410,16 @@ part of the first prerequisite.
|
||||
Lists of the directory parts and the file-within-directory
|
||||
parts of all prerequisites.
|
||||
|
||||
@vindex $(+D)
|
||||
@vindex +D @r{(automatic variable)}
|
||||
@item $(+D)
|
||||
@vindex $(+F)
|
||||
@vindex +F @r{(automatic variable)}
|
||||
@itemx $(+F)
|
||||
Lists of the directory parts and the file-within-directory
|
||||
parts of all prerequisites, including multiple instances of duplicated
|
||||
prerequisites.
|
||||
|
||||
@vindex $(?D)
|
||||
@vindex ?D @r{(automatic variable)}
|
||||
@item $(?D)
|
||||
@ -8429,6 +8439,32 @@ deep significance; @samp{$<} refers to the variable named @code{<} just
|
||||
as @samp{$(CFLAGS)} refers to the variable named @code{CFLAGS}.
|
||||
You could just as well use @samp{$(<)} in place of @samp{$<}.
|
||||
|
||||
@vindex $$@@
|
||||
@vindex $$(@@D)
|
||||
@vindex $$(@@F)
|
||||
@cindex $$@@, support for
|
||||
GNU @code{make} provides support for the SysV @code{make} feature that
|
||||
allows special variable references @code{$$@@}, @code{$$(@@D)}, and
|
||||
@code{$$(@@F)} (note the required double-''$''!) to appear with the
|
||||
@emph{prerequisites list} (normal automatic variables are available
|
||||
only within a command script). When appearing in a prerequisites
|
||||
list, these variables are expanded to the name of the target, the
|
||||
directory component of the target, and the file component of the
|
||||
target, respectively.
|
||||
|
||||
Note that these variables are available only within explicit and
|
||||
static pattern (@pxref{Static Pattern, ,Static Pattern Rules}) rules;
|
||||
they have no special significance within implicit (suffix or pattern)
|
||||
rules. Also note that while SysV @code{make} actually expands its
|
||||
entire prerequisite list @emph{twice}, GNU @code{make} does not behave
|
||||
this way: instead it simply expands these special variables without
|
||||
re-expanding any other part of the prerequisites list.
|
||||
|
||||
This somewhat bizarre feature is included only to provide some
|
||||
compatibility with SysV makefiles. In a native GNU @code{make} file
|
||||
there are other ways to accomplish the same results. This feature is
|
||||
disabled if the special pseudo target @code{.POSIX} is defined.
|
||||
|
||||
@node Pattern Match, Match-Anything Rules, Automatic, Pattern Rules
|
||||
@subsection How Patterns Match
|
||||
|
||||
@ -9322,29 +9358,6 @@ pattern rules for extraction from SCCS, in combination with the
|
||||
general feature of rule chaining.
|
||||
@xref{Chained Rules, ,Chains of Implicit Rules}.
|
||||
|
||||
@item
|
||||
In System V @code{make}, the string @samp{$$@@} has the strange meaning
|
||||
that, in the prerequisites of a rule with multiple targets, it stands
|
||||
for the particular target that is being processed.
|
||||
|
||||
This is not defined in GNU @code{make} because @samp{$$} should always
|
||||
stand for an ordinary @samp{$}.
|
||||
|
||||
It is possible to get portions of this functionality through the use of
|
||||
static pattern rules (@pxref{Static Pattern, ,Static Pattern Rules}).
|
||||
The System V @code{make} rule:
|
||||
|
||||
@example
|
||||
$(targets): $$@@.o lib.a
|
||||
@end example
|
||||
|
||||
@noindent
|
||||
can be replaced with the GNU @code{make} static pattern rule:
|
||||
|
||||
@example
|
||||
$(targets): %: %.o lib.a
|
||||
@end example
|
||||
|
||||
@item
|
||||
In System V and 4.3 BSD @code{make}, files found by @code{VPATH} search
|
||||
(@pxref{Directory Search, ,Searching Directories for Prerequisites}) have their names changed inside command
|
||||
|
4
main.c
4
main.c
@ -2169,9 +2169,9 @@ print_usage (bad)
|
||||
}
|
||||
|
||||
if (!remote_description || *remote_description == '\0')
|
||||
fprintf (usageto, _("\nBuilt for %s"), make_host);
|
||||
fprintf (usageto, _("\nThis program built for %s"), make_host);
|
||||
else
|
||||
fprintf (usageto, "\nBuilt for %s (%s)", make_host, remote_description);
|
||||
fprintf (usageto, "\nThis program built for %s (%s)", make_host, remote_description);
|
||||
|
||||
fprintf (usageto, _("\nReport bugs to <bug-make@gnu.org>\n"));
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
*.gmo *.mo *.pot
|
||||
*.gmo *.mo *.pot *.po
|
||||
|
||||
Makefile.in Makefile
|
||||
POTFILES
|
||||
|
129
read.c
129
read.c
@ -132,7 +132,8 @@ static int conditional_line PARAMS ((char *line, const struct floc *flocp));
|
||||
static void record_files PARAMS ((struct nameseq *filenames, char *pattern, char *pattern_percent,
|
||||
struct dep *deps, unsigned int cmds_started, char *commands,
|
||||
unsigned int commands_idx, int two_colon,
|
||||
const struct floc *flocp, int set_default));
|
||||
int have_sysv_atvar,
|
||||
const struct floc *flocp, int set_default));
|
||||
static void record_target_var PARAMS ((struct nameseq *filenames, char *defn,
|
||||
int two_colon,
|
||||
enum variable_origin origin,
|
||||
@ -430,6 +431,7 @@ eval (ebuf, set_default)
|
||||
unsigned int cmds_started, tgts_started;
|
||||
int ignoring = 0, in_ignored_define = 0;
|
||||
int no_targets = 0; /* Set when reading a rule without targets. */
|
||||
int have_sysv_atvar = 0;
|
||||
struct nameseq *filenames = 0;
|
||||
struct dep *deps = 0;
|
||||
long nlines = 0;
|
||||
@ -450,7 +452,7 @@ eval (ebuf, set_default)
|
||||
fi.lineno = tgts_started; \
|
||||
record_files (filenames, pattern, pattern_percent, deps, \
|
||||
cmds_started, commands, commands_idx, two_colon, \
|
||||
&fi, set_default); \
|
||||
have_sysv_atvar, &fi, set_default); \
|
||||
} \
|
||||
filenames = 0; \
|
||||
commands_idx = 0; \
|
||||
@ -1057,6 +1059,16 @@ eval (ebuf, set_default)
|
||||
}
|
||||
}
|
||||
|
||||
/* Do any of the prerequisites appear to have $@ etc.? */
|
||||
have_sysv_atvar = 0;
|
||||
if (!posix_pedantic)
|
||||
for (p = strchr (p2, '$'); p != 0; p = strchr (p+1, '$'))
|
||||
if (p[1] == '@' || (p[1] == '(' && p[2] == '@'))
|
||||
{
|
||||
have_sysv_atvar = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Is this a static pattern rule: `target: %targ: %dep; ...'? */
|
||||
p = strchr (p2, ':');
|
||||
while (p != 0 && p[-1] == '\\')
|
||||
@ -1654,7 +1666,8 @@ record_target_var (filenames, defn, two_colon, origin, flocp)
|
||||
|
||||
static void
|
||||
record_files (filenames, pattern, pattern_percent, deps, cmds_started,
|
||||
commands, commands_idx, two_colon, flocp, set_default)
|
||||
commands, commands_idx, two_colon, have_sysv_atvar,
|
||||
flocp, set_default)
|
||||
struct nameseq *filenames;
|
||||
char *pattern, *pattern_percent;
|
||||
struct dep *deps;
|
||||
@ -1662,6 +1675,7 @@ record_files (filenames, pattern, pattern_percent, deps, cmds_started,
|
||||
char *commands;
|
||||
unsigned int commands_idx;
|
||||
int two_colon;
|
||||
int have_sysv_atvar;
|
||||
const struct floc *flocp;
|
||||
int set_default;
|
||||
{
|
||||
@ -1684,16 +1698,22 @@ record_files (filenames, pattern, pattern_percent, deps, cmds_started,
|
||||
|
||||
for (; filenames != 0; filenames = nextf)
|
||||
{
|
||||
|
||||
register char *name = filenames->name;
|
||||
register struct file *f;
|
||||
register struct dep *d;
|
||||
char *name = filenames->name;
|
||||
struct file *f;
|
||||
struct dep *d;
|
||||
struct dep *this;
|
||||
char *implicit_percent;
|
||||
|
||||
nextf = filenames->next;
|
||||
free (filenames);
|
||||
|
||||
/* Check for .POSIX. We used to do this in snap_deps() but that's not
|
||||
good enough: it doesn't happen until after the makefile is read,
|
||||
which means we cannot use its value during parsing. */
|
||||
|
||||
if (streq (name, ".POSIX"))
|
||||
posix_pedantic = 1;
|
||||
|
||||
implicit_percent = find_percent (name);
|
||||
implicit |= implicit_percent != 0;
|
||||
|
||||
@ -1772,6 +1792,101 @@ record_files (filenames, pattern, pattern_percent, deps, cmds_started,
|
||||
}
|
||||
}
|
||||
|
||||
/* If at least one of the dependencies uses $$@ etc. deal with that.
|
||||
It would be very nice and very simple to just expand everything, but
|
||||
it would break a lot of backward compatibility. Maybe that's OK
|
||||
since we're just emulating a SysV function, and if we do that then
|
||||
why not emulate it completely (that's what SysV make does: it
|
||||
re-expands the entire prerequisite list, all the time, with $@
|
||||
etc. in scope. But, it would be a pain indeed to document this
|
||||
("iff you use $$@, your prerequisite lists is expanded twice...")
|
||||
Ouch. Maybe better to make the code more complex. */
|
||||
|
||||
if (have_sysv_atvar)
|
||||
{
|
||||
char *p;
|
||||
int tlen = strlen (name);
|
||||
char *fnp = strrchr (name, '/');
|
||||
int dlen;
|
||||
int flen;
|
||||
|
||||
if (fnp)
|
||||
{
|
||||
dlen = fnp - name;
|
||||
++fnp;
|
||||
flen = strlen (fnp);
|
||||
}
|
||||
else
|
||||
{
|
||||
dlen = 0;
|
||||
fnp = name;
|
||||
flen = tlen;
|
||||
}
|
||||
|
||||
|
||||
for (d = this; d != 0; d = d->next)
|
||||
for (p = strchr (d->name, '$'); p != 0; p = strchr (p+1, '$'))
|
||||
{
|
||||
char *s = p;
|
||||
char *at;
|
||||
int atlen;
|
||||
|
||||
/* If it's a '$@' or '$(@', it's escaped */
|
||||
if ((++p)[0] == '$'
|
||||
&& (p[1] == '@' || (p[1] == '(' && p[2] == '@')))
|
||||
{
|
||||
bcopy (p, s, strlen (p)+1);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Maybe found one. Check. p will point to '@' [for $@] or
|
||||
')' [for $(@)] or 'D' [for $(@D)] or 'F' [for $(@F)]. */
|
||||
if (p[0] != '@'
|
||||
&& (p[0] != '(' || (++p)[0] != '@'
|
||||
|| ((++p)[0] != ')'
|
||||
&& (p[1] != ')' || (p[0] != 'D' && p[0] != 'F')))))
|
||||
continue;
|
||||
|
||||
/* Found one. Compute the length and string ptr. Move p
|
||||
past the variable reference. */
|
||||
switch (p[0])
|
||||
{
|
||||
case 'D':
|
||||
atlen = dlen;
|
||||
at = name;
|
||||
p += 2;
|
||||
break;
|
||||
|
||||
case 'F':
|
||||
atlen = flen;
|
||||
at = fnp;
|
||||
p += 2;
|
||||
break;
|
||||
|
||||
default:
|
||||
atlen = tlen;
|
||||
at = name;
|
||||
++p;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Get more space. */
|
||||
{
|
||||
int soff = s - d->name;
|
||||
int poff = p - d->name;
|
||||
d->name = (char *) xrealloc (d->name,
|
||||
strlen (d->name) + atlen + 1);
|
||||
s = d->name + soff;
|
||||
p = d->name + poff;
|
||||
}
|
||||
|
||||
/* Copy the string over. */
|
||||
bcopy(p, s+atlen, strlen (p)+1);
|
||||
bcopy(at, s, atlen);
|
||||
p = s + atlen - 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!two_colon)
|
||||
{
|
||||
/* Single-colon. Combine these dependencies
|
||||
|
@ -1,3 +1,8 @@
|
||||
2002-07-10 Paul D. Smith <psmith@gnu.org>
|
||||
|
||||
* scripts/variables/automatic: Add some tests for $$@, $$(@D), and
|
||||
$$(@F).
|
||||
|
||||
2002-07-09 Paul D. Smith <psmith@gnu.org>
|
||||
|
||||
* scripts/variables/automatic: Create a test for automatic variables.
|
||||
|
@ -30,9 +30,8 @@ close(MAKEFILE);
|
||||
# TEST #1 -- simple test
|
||||
# -------
|
||||
|
||||
&touch(qw(foo.x baz.z));
|
||||
|
||||
sleep(1);
|
||||
# Touch these into the past
|
||||
&utouch(-10, qw(foo.x baz.z));
|
||||
|
||||
&run_make_with_options($makefile, "", &get_logfile);
|
||||
$answer = "touch $dir/bar.y
|
||||
@ -47,4 +46,28 @@ touch $dir/foo.x\n";
|
||||
|
||||
unlink(qw(foo.x bar.y baz.z));
|
||||
|
||||
# TEST #2 -- test the SysV emulation of $$@ etc.
|
||||
# -------
|
||||
|
||||
$makefile2 = &get_tmpfile;
|
||||
|
||||
open(MAKEFILE, "> $makefile2");
|
||||
print MAKEFILE "dir = $dir\n";
|
||||
print MAKEFILE <<'EOF';
|
||||
.SUFFIXES:
|
||||
.DEFAULT: ; @echo '$@'
|
||||
|
||||
$(dir)/foo $(dir)/bar: $@.x $$@.x $$$@.x $$$$@.x $$(@D).x $$(@F).x
|
||||
|
||||
$(dir)/x.z $(dir)/y.z: $(dir)/%.z : $@.% $$@.% $$$@.% $$$$@.% $$(@D).% $$(@F).%
|
||||
EOF
|
||||
|
||||
&run_make_with_options($makefile2, "$dir/foo $dir/bar", &get_logfile);
|
||||
$answer = ".x\n$dir/foo.x\n\$.x\n\$@.x\n$dir.x\nfoo.x\n$dir/bar.x\nbar.x\n";
|
||||
&compare_output($answer, &get_logfile(1));
|
||||
|
||||
&run_make_with_options($makefile2, "$dir/x.z $dir/y.z", &get_logfile);
|
||||
$answer = ".x\n$dir/x.z.x\n\$.x\n\$@.x\n$dir.x\nx.z.x\n.y\n$dir/y.z.y\n\$.y\n\$@.y\n$dir.y\ny.z.y\n";
|
||||
&compare_output($answer, &get_logfile(1));
|
||||
|
||||
1;
|
||||
|
@ -825,15 +825,29 @@ sub remove_directory_tree_inner
|
||||
|
||||
sub touch
|
||||
{
|
||||
local (@filenames) = @_;
|
||||
local ($file);
|
||||
|
||||
foreach $file (@filenames) {
|
||||
foreach $file (@_) {
|
||||
(open(T, ">> $file") && print(T "\n") && close(T))
|
||||
|| &error("Couldn't touch $file: $!\n", 1);
|
||||
}
|
||||
}
|
||||
|
||||
# Touch with a time offset. To DTRT, call touch() then use stat() to get the
|
||||
# access/mod time for each file and apply the offset.
|
||||
|
||||
sub utouch
|
||||
{
|
||||
local ($off) = shift;
|
||||
local ($file);
|
||||
|
||||
&touch(@_);
|
||||
|
||||
local (@s) = stat($_[0]);
|
||||
|
||||
utime($s[8]+$off, $s[9]+$off, @_);
|
||||
}
|
||||
|
||||
# open a file, write some stuff to it, and close it.
|
||||
|
||||
sub create_file
|
||||
|
Loading…
Reference in New Issue
Block a user