mirror of
https://github.com/mirror/make.git
synced 2024-12-26 12:50:20 +08:00
[SV 64571] Add --print-targets option
Add an option to print a list of targets defined in the makefiles. Don't print targets of implicit rules, or special targets. To support this remember which files are deemed suffix rule targets. Add a missing warning for single-suffix targets with prerequisites. Suggested by many. Sample implementation by Tim <tdhutt@gmail.com>. * NEWS: Announce the new option and single-suffix warning. * doc/make.1: Add --print-targets to the man page. * doc/make.texi: Add --print-targets to the documentation. Clean up the text around the definition of suffix rules. * src/main.c (print_targets_flag): New variable for --print-targets. (switches): Add a new long option --print-targets. (main): If the option was provided call print_targets() and exit. * src/filedef.h (struct file): Add a "suffix" boolean value. Remove print_prereqs() since it's static. Add new print_targets(). * src/file.c (rehash_file): Merge the new suffix value. (print_prereqs): Used only locally: change to static. (print_target): Print targets which are not suffix rule targets and are not special targets. (print_targets): Call print_target() on each file. * src/rule.c (convert_to_pattern): Make maxsuffix local; it doesn't need to be static. Emit ignoring prerequisites for single-suffix rules as well as double-suffix rules. Remember which files are actually suffix rules. * tests/scripts/features/suffixrules: Test single-suffix behavior. * tests/scripts/options/print-targets: Add tests for --print-targets.
This commit is contained in:
parent
1ff728bff4
commit
31036e648f
9
NEWS
9
NEWS
@ -37,6 +37,10 @@ https://sv.gnu.org/bugs/index.php?group=make&report_id=111&fix_release_id=111&se
|
||||
things like "ifeq ((foo,bar),)" are now syntax errors. Use a variable to
|
||||
hide the comma if needed: "COMMA = ," / "ifeq ((foo$(COMMA)bar),)".
|
||||
|
||||
* NOTE: Deprecated behavior.
|
||||
The check in GNU Make 4.3 for suffix rules with prerequisites didn't check
|
||||
single-suffix rules, only double-suffix rules. Add the missing check.
|
||||
|
||||
* New feature: Unload function for loaded objects
|
||||
When a loaded object needs to be unloaded by GNU Make, it will invoke an
|
||||
unload function (if one is defined) beforehand that allows the object to
|
||||
@ -56,6 +60,11 @@ https://sv.gnu.org/bugs/index.php?group=make&report_id=111&fix_release_id=111&se
|
||||
invoked recursively, warnings can be controlled only for the current
|
||||
instance of make using the .WARNINGS variable.
|
||||
|
||||
* New feature: Printing targets defined by the makefile
|
||||
A new option "--print-targets" will print all explicit, non-special targets
|
||||
defined in the makefiles, one per line, then exit with success. No recipes
|
||||
are invoked and no makefiles are re-built.
|
||||
|
||||
* 'make --print-data-base' (or 'make -p') now outputs time of day
|
||||
using the same form as for file timestamps, e.g., "2023-05-10
|
||||
10:43:57.570558743". Previously it used the form "Wed May 10
|
||||
|
@ -270,10 +270,15 @@ reading the makefiles; then execute as usual or as otherwise
|
||||
specified.
|
||||
This also prints the version information given by the
|
||||
.B \-v
|
||||
switch (see below).
|
||||
To print the data base without trying to remake any files, use
|
||||
switch (see below). To print the built-in data base only, use
|
||||
.IR "make \-p \-f/dev/null" .
|
||||
.TP 0.5i
|
||||
\fB\-\-print\-targets\fR
|
||||
Print each target defined as a result of reading the makefiles, one target per
|
||||
line, then exit with success. Implicit rule targets are not printed, nor are
|
||||
special targets (target names that consist of "." followed by all upper-case
|
||||
letters). No recipe commands are invoked and no makefiles are rebuilt.
|
||||
.TP 0.5i
|
||||
\fB\-q\fR, \fB\-\-question\fR
|
||||
``Question mode''.
|
||||
Do not run any commands, or print anything; just return an exit status
|
||||
|
@ -9677,15 +9677,28 @@ performed. @xref{Parallel Output, ,Output During Parallel Execution}.
|
||||
@cindex @code{--print-data-base}
|
||||
@cindex data base of @code{make} rules
|
||||
@cindex predefined rules and variables, printing
|
||||
Print the data base (rules and variable values) that results from
|
||||
reading the makefiles; then execute as usual or as otherwise
|
||||
specified. This also prints the version information given by the
|
||||
@samp{-v} switch (see below). To print the data base without trying
|
||||
to remake any files, use @w{@samp{make -qp}}. To print the data base
|
||||
of predefined rules and variables, use @w{@samp{make -p -f /dev/null}}.
|
||||
The data base output contains file name and line number information for
|
||||
recipe and variable definitions, so it can be a useful debugging tool
|
||||
in complex environments.
|
||||
Print the data base (rules and variable values) that results from reading the
|
||||
makefiles; then execute as usual or as otherwise specified. This also prints
|
||||
the version information given by the @samp{-v} switch (see below). To print
|
||||
the data base without trying to remake any files, use @w{@samp{make -qp}}. To
|
||||
print the data base of predefined rules and variables, use @w{@samp{make -p -f
|
||||
/dev/null}}. The data base output contains file name and line number
|
||||
information for recipe and variable definitions, so it can be a useful
|
||||
debugging tool in complex environments.
|
||||
|
||||
@item --print-targets
|
||||
@cindex @code{--print-targets}
|
||||
@cindex print @file{makefile} targets
|
||||
@cindex targets, printing
|
||||
Print all the targets defined by reading the makefiles, one target per line,
|
||||
then exit immediately with success. No implicit targets are printed. No
|
||||
special targets (target names consisting of ``.'' followed by all upper-case
|
||||
letters) are printed.
|
||||
|
||||
No commands are run, including commands that would rebuild makefiles
|
||||
(@pxref{Remaking Makefiles, ,How Makefiles Are Remade}); if makefiles need to
|
||||
be rebuilt then the targets listed might be outdated. Also, @code{make} will
|
||||
not generate any errors or warnings for missing @code{include} files.
|
||||
|
||||
@item -q
|
||||
@cindex @code{-q}
|
||||
@ -11237,26 +11250,26 @@ You can use a last-resort rule to override part of another makefile.
|
||||
@section Old-Fashioned Suffix Rules
|
||||
@cindex old-fashioned suffix rules
|
||||
@cindex suffix rule
|
||||
@cindex inference rule
|
||||
|
||||
@dfn{Suffix rules} are the old-fashioned way of defining implicit rules for
|
||||
@code{make}. Suffix rules are obsolete because pattern rules are more
|
||||
general and clearer. They are supported in GNU @code{make} for
|
||||
compatibility with old makefiles. They come in two kinds:
|
||||
@dfn{double-suffix} and @dfn{single-suffix}.
|
||||
|
||||
A double-suffix rule is defined by a pair of suffixes: the target
|
||||
suffix and the source suffix. It matches any file whose name ends
|
||||
with the target suffix. The corresponding implicit prerequisite is
|
||||
made by replacing the target suffix with the source suffix in the file
|
||||
name. A two-suffix rule @samp{.c.o} (whose target and source suffixes
|
||||
are @samp{.o} and @samp{.c}) is equivalent to the pattern rule
|
||||
@samp{%.o : %.c}.
|
||||
@dfn{Suffix rules} (called @dfn{inference rules} in POSIX) are an
|
||||
old-fashioned way of defining implicit rules for @code{make}. Suffix rules
|
||||
are less powerful and harder to use than pattern rules (@pxref{Pattern Rules,
|
||||
,Defining and Redefining Pattern Rules}); they are supported by GNU Make
|
||||
primarily for POSIX compatibility. They come in two flavors:
|
||||
@dfn{single-suffix} and @dfn{double-suffix}.
|
||||
|
||||
A single-suffix rule is defined by a single suffix, which is the source
|
||||
suffix. It matches any file name, and the corresponding implicit
|
||||
prerequisite name is made by appending the source suffix. A single-suffix
|
||||
rule whose source suffix is @samp{.c} is equivalent to the pattern rule
|
||||
@samp{% : %.c}.
|
||||
suffix. It matches any file name, and the corresponding implicit prerequisite
|
||||
name is made by appending the source suffix. A single-suffix rule whose
|
||||
source suffix is @samp{.c} is equivalent to the pattern rule @samp{% : %.c}.
|
||||
|
||||
A double-suffix rule is defined by a pair of suffixes: the source suffix and
|
||||
the target suffix. It matches any file whose name ends with the target
|
||||
suffix. The corresponding implicit prerequisite is made by replacing the
|
||||
target suffix with the source suffix in the file name. A two-suffix rule
|
||||
@samp{.c.o} has a source suffix @samp{.c} and a target suffix @samp{.o}, and
|
||||
is equivalent to the pattern rule @samp{%.o : %.c}.
|
||||
|
||||
Suffix rule definitions are recognized by comparing each rule's target
|
||||
against a defined list of known suffixes. When @code{make} sees a rule
|
||||
|
32
src/file.c
32
src/file.c
@ -26,6 +26,7 @@ this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
#include "debug.h"
|
||||
#include "hash.h"
|
||||
#include "shuffle.h"
|
||||
#include "rule.h"
|
||||
|
||||
|
||||
/* Remember whether snap_deps has been invoked: we need this to be sure we
|
||||
@ -334,6 +335,7 @@ rehash_file (struct file *from_file, const char *to_hname)
|
||||
MERGE (notintermediate);
|
||||
MERGE (ignore_vpath);
|
||||
MERGE (snapped);
|
||||
MERGE (suffix);
|
||||
#undef MERGE
|
||||
|
||||
to_file->builtin = 0;
|
||||
@ -1050,7 +1052,7 @@ file_timestamp_sprintf (char *p, FILE_TIMESTAMP ts)
|
||||
|
||||
/* Print the data base of files. */
|
||||
|
||||
void
|
||||
static void
|
||||
print_prereqs (const struct dep *deps)
|
||||
{
|
||||
const struct dep *ood = 0;
|
||||
@ -1201,6 +1203,34 @@ print_file_data_base (void)
|
||||
fputs (_("\n# files hash-table stats:\n# "), stdout);
|
||||
hash_print_stats (&files, stdout);
|
||||
}
|
||||
|
||||
static void
|
||||
print_target (const void *item)
|
||||
{
|
||||
const struct file *f = item;
|
||||
|
||||
if (!f->is_target || f->suffix)
|
||||
return;
|
||||
|
||||
/* Ignore any special targets, as defined by POSIX. */
|
||||
if (f->name[0] == '.' && isupper ((unsigned char)f->name[1]))
|
||||
{
|
||||
const char *cp = f->name + 1;
|
||||
while (*(++cp) != '\0')
|
||||
if (!isupper ((unsigned char)*cp))
|
||||
break;
|
||||
if (*cp == '\0')
|
||||
return;
|
||||
}
|
||||
|
||||
puts (f->name);
|
||||
}
|
||||
|
||||
void
|
||||
print_targets (void)
|
||||
{
|
||||
hash_map (&files, print_target);
|
||||
}
|
||||
|
||||
/* Verify the integrity of the data base of files. */
|
||||
|
||||
|
@ -113,6 +113,7 @@ struct file
|
||||
--shuffle passes through the graph. */
|
||||
unsigned int snapped:1; /* True if the deps of this file have been
|
||||
secondary expanded. */
|
||||
unsigned int suffix:1; /* True if this is a suffix rule. */
|
||||
};
|
||||
|
||||
|
||||
@ -134,8 +135,8 @@ void notice_finished_file (struct file *file);
|
||||
void init_hash_files (void);
|
||||
void verify_file_data_base (void);
|
||||
char *build_target_list (char *old_list);
|
||||
void print_prereqs (const struct dep *deps);
|
||||
void print_file_data_base (void);
|
||||
void print_targets (void);
|
||||
int try_implicit_rule (struct file *file, unsigned int depth);
|
||||
int stemlen_compare (const void *v1, const void *v2);
|
||||
|
||||
|
18
src/main.c
18
src/main.c
@ -167,11 +167,16 @@ int env_overrides = 0;
|
||||
|
||||
int ignore_errors_flag = 0;
|
||||
|
||||
/* Nonzero means don't remake anything, just print the data base
|
||||
that results from reading the makefile (-p). */
|
||||
/* Nonzero means print the data base that results from reading the makefile.
|
||||
(-p or --print-data-base). */
|
||||
|
||||
int print_data_base_flag = 0;
|
||||
|
||||
/* Nonzero means don't remake anything, just print a list of targets defined
|
||||
by reading the makefile (--print-targets). */
|
||||
|
||||
int print_targets_flag = 0;
|
||||
|
||||
/* Nonzero means don't remake anything; just return a nonzero status
|
||||
if the specified targets are not up to date (-q). */
|
||||
|
||||
@ -509,6 +514,7 @@ static struct command_switch switches[] =
|
||||
{ CHAR_MAX+11, string, &shuffle_mode, 1, 1, 0, 0, "random", 0, "shuffle", 0 },
|
||||
{ CHAR_MAX+12, string, &jobserver_style, 1, 0, 0, 0, 0, 0, "jobserver-style", 0 },
|
||||
{ WARN_OPT, strlist, &warn_flags, 1, 1, 0, 0, "warn", NULL, "warn", NULL },
|
||||
{ CHAR_MAX+14, flag, &print_targets_flag, 1, 1, 0, 0, 0, 0, "print-targets", 0 },
|
||||
{ 0, 0, NULL, 0, 0, 0, 0, NULL, NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
@ -2289,6 +2295,14 @@ main (int argc, char **argv, char **envp)
|
||||
}
|
||||
}
|
||||
|
||||
/* If the user wants to see a list of targets show it now then quit.
|
||||
We do this before rebuilding makefiles to avoid extraneous output. */
|
||||
if (print_targets_flag)
|
||||
{
|
||||
print_targets ();
|
||||
die (EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
if (!restarts && new_files != 0)
|
||||
{
|
||||
const char **p;
|
||||
|
33
src/rule.c
33
src/rule.c
@ -56,10 +56,6 @@ size_t max_pattern_dep_length;
|
||||
|
||||
struct file *suffix_file;
|
||||
|
||||
/* Maximum length of a suffix. */
|
||||
|
||||
static size_t maxsuffix;
|
||||
|
||||
/* Return the rule definition: space separated rule targets, followed by
|
||||
either a colon or two colons in the case of a terminal rule, followed by
|
||||
space separated rule prerequisites, followed by a pipe, followed by
|
||||
@ -304,7 +300,7 @@ convert_to_pattern (void)
|
||||
suffixes in the .SUFFIXES target's dependencies and see if it exists.
|
||||
First find the longest of the suffixes. */
|
||||
|
||||
maxsuffix = 0;
|
||||
size_t maxsuffix = 0;
|
||||
for (d = suffix_file->deps; d != 0; d = d->next)
|
||||
{
|
||||
size_t l = strlen (dep_name (d));
|
||||
@ -317,6 +313,7 @@ convert_to_pattern (void)
|
||||
|
||||
for (d = suffix_file->deps; d != 0; d = d->next)
|
||||
{
|
||||
struct file *f;
|
||||
size_t slen;
|
||||
|
||||
/* Make a rule that is just the suffix, with no deps or commands.
|
||||
@ -327,14 +324,26 @@ convert_to_pattern (void)
|
||||
/* Record a pattern for this suffix's null-suffix rule. */
|
||||
convert_suffix_rule ("", dep_name (d), d->file->cmds);
|
||||
|
||||
slen = strlen (dep_name (d));
|
||||
memcpy (rulename, dep_name (d), slen + 1);
|
||||
|
||||
f = lookup_file (rulename);
|
||||
if (f && f->cmds)
|
||||
{
|
||||
if (!f->deps)
|
||||
f->suffix = 1;
|
||||
else if (!posix_pedantic)
|
||||
{
|
||||
O (error, &f->cmds->fileinfo,
|
||||
_("warning: ignoring prerequisites on suffix rule definition"));
|
||||
f->suffix = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Add every other suffix to this one and see if it exists as a
|
||||
two-suffix rule. */
|
||||
slen = strlen (dep_name (d));
|
||||
memcpy (rulename, dep_name (d), slen);
|
||||
|
||||
for (d2 = suffix_file->deps; d2 != 0; d2 = d2->next)
|
||||
{
|
||||
struct file *f;
|
||||
size_t s2len;
|
||||
|
||||
s2len = strlen (dep_name (d2));
|
||||
@ -359,10 +368,12 @@ convert_to_pattern (void)
|
||||
{
|
||||
if (posix_pedantic)
|
||||
continue;
|
||||
error (&f->cmds->fileinfo, 0,
|
||||
_("warning: ignoring prerequisites on suffix rule definition"));
|
||||
O (error, &f->cmds->fileinfo,
|
||||
_("warning: ignoring prerequisites on suffix rule definition"));
|
||||
}
|
||||
|
||||
f->suffix = 1;
|
||||
|
||||
if (s2len == 2 && rulename[slen] == '.' && rulename[slen + 1] == 'a')
|
||||
/* A suffix rule '.X.a:' generates the pattern rule '(%.o): %.X'.
|
||||
It also generates a normal '%.a: %.X' rule below. */
|
||||
|
@ -51,12 +51,30 @@ run_make_test(q!
|
||||
|
||||
unlink('foo.baz');
|
||||
|
||||
# SV 40657: Test #4: "Suffix rules" with deps are normal rules
|
||||
# SV 40657: "Suffix rules" with deps are normal rules
|
||||
|
||||
my $prewarn = 'warning: ignoring prerequisites on suffix rule definition';
|
||||
|
||||
touch('foo.bar');
|
||||
|
||||
# Verify warnings for single-suffix rules
|
||||
|
||||
run_make_test(q!
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .baz
|
||||
|
||||
.baz: foo.bar ; @echo make $@ from $<
|
||||
|
||||
$X.POSIX:
|
||||
!,
|
||||
'X=1 .baz', "#MAKEFILE#:5: $prewarn\nmake .baz from foo.bar\n");
|
||||
|
||||
# In POSIX mode we don't get a warning
|
||||
|
||||
run_make_test(undef, 'X= .baz', "make .baz from foo.bar\n");
|
||||
|
||||
# Test double-suffix rules
|
||||
|
||||
run_make_test(q!
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .biz .baz
|
||||
@ -67,25 +85,25 @@ $X.POSIX:
|
||||
!,
|
||||
'X=1 .baz.biz', "#MAKEFILE#:7: $prewarn\nmake .baz.biz from foo.bar\n");
|
||||
|
||||
# SV 40657: Test #5: In POSIX mode we don't get a warning
|
||||
# SV 40657: In POSIX mode we don't get a warning
|
||||
|
||||
run_make_test(undef, 'X= .baz.biz', "make .baz.biz from foo.bar\n");
|
||||
|
||||
unlink('foo.bar');
|
||||
|
||||
# SV 40657: Test #6: In POSIX mode, no pattern rules should be created
|
||||
# SV 40657: In POSIX mode, no pattern rules should be created
|
||||
|
||||
utouch(-20, 'foo.baz');
|
||||
|
||||
run_make_test(undef,
|
||||
'X= foo.biz', "#MAKE#: *** No rule to make target 'foo.biz'. Stop.\n", 512);
|
||||
|
||||
# SV 40657: Test #7: In Non-POSIX mode, a pattern rule is created
|
||||
# SV 40657: In Non-POSIX mode, a pattern rule is created
|
||||
|
||||
run_make_test(undef,
|
||||
'X=1 foo.biz', "#MAKEFILE#:7: $prewarn\nmake foo.biz from foo.baz\n");
|
||||
|
||||
# SV 40657: Test #8: ... but any prerequisites are ignored
|
||||
# SV 40657: ... but any prerequisites are ignored
|
||||
|
||||
utouch(-10, 'foo.biz');
|
||||
touch('foo.bar');
|
||||
|
32
tests/scripts/options/print-targets
Normal file
32
tests/scripts/options/print-targets
Normal file
@ -0,0 +1,32 @@
|
||||
# -*-perl-*-
|
||||
|
||||
$description = "Test the --print-targets option to GNU Make.";
|
||||
|
||||
# Define various things and verify the output
|
||||
run_make_test(q!
|
||||
.PHONY: all
|
||||
all: ;@:
|
||||
|
||||
# "special" target
|
||||
.BOGUS: ;@:
|
||||
|
||||
# Check various forms of suffix rule
|
||||
.SUFFIXES: .q
|
||||
.q: ;@:
|
||||
.c.o: ;@:
|
||||
|
||||
# Not a suffix rule
|
||||
.x.z: ;@:
|
||||
|
||||
# Verify included files aren't built / don't fail
|
||||
|
||||
include badfile
|
||||
include goodfile
|
||||
|
||||
submake: ; $(MAKE) all
|
||||
always: ; +echo always
|
||||
goodfile: ; touch goodfile
|
||||
!,
|
||||
"--print-targets", "submake\n.x.z\nalways\nall\ngoodfile\n");
|
||||
|
||||
1;
|
Loading…
Reference in New Issue
Block a user