From 08c8105c5468ff743d2f2ff2fdf3b77a6313b53e Mon Sep 17 00:00:00 2001 From: Paul Smith Date: Sun, 16 May 2004 19:16:52 +0000 Subject: [PATCH] Various enhancements - OS/2 Patches - OpenVMS updates - Sanitize the handling of -include/sinclude with and without -k - Fix the setting of $< for order-only rules. --- ChangeLog | 55 ++++++++++++++++ Makefile.am | 4 +- commands.c | 12 +++- configure.in | 3 +- default.c | 6 +- dep.h | 2 +- doc/make.texi | 26 +++++--- file.c | 6 +- getloadavg.c | 2 +- job.c | 36 +++++++++-- main.c | 18 +++++- make.h | 2 +- makefile.vms | 4 +- read.c | 8 +-- readme.vms | 51 +++++++++++++++ remake.c | 100 +++++++++++++++++------------ tests/run_make_tests.pl | 132 ++++++++++++++++++++++++-------------- tests/scripts/features/echoing | 9 +-- tests/scripts/features/errors | 25 ++++---- tests/scripts/features/include | 33 ++++++++-- tests/scripts/features/order_only | 11 ++++ tests/scripts/functions/wildcard | 7 +- tests/scripts/options/dash-C | 9 ++- tests/scripts/options/dash-k | 14 ++++ tests/scripts/targets/FORCE | 13 ++-- tests/scripts/targets/PHONY | 15 ++--- tests/scripts/targets/SILENT | 12 ++-- tests/scripts/targets/clean | 5 +- tests/scripts/variables/special | 22 ++----- tests/test_driver.pl | 47 ++++++-------- 30 files changed, 458 insertions(+), 231 deletions(-) diff --git a/ChangeLog b/ChangeLog index 30f13b9..759c4e4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,58 @@ +2004-05-16 Paul D. Smith + + * remake.c (update_goal_chain): Change the argument specifying + whether we're rebuilding makefiles to be a global variable, + REBUILDING_MAKEFILES. + (complain): Extract the code that complains about no rules to make + a target into a separate function. + (update_file_1): If we tried to rebuild a file during the makefile + rebuild phase and it was dontcare, then no message was printed. + If we then try to build the same file during the normal build, + print a message this time. + (remake_file): Don't complain about un-remake-able files when + we're rebuilding makefiles. + +2004-05-11 Paul D. Smith + + * job.c (construct_command_argv_internal): OS/2 patches from + Andreas Buening . + +2004-05-10 Paul D. Smith + + * remake.c (update_file): Don't walk the double-colon chain unless + this is a double-colon rule. Fix suggested by Boris Kolpackov + . + + * makefile.vms (CFLAGS): Remove glob/globfree (see readme.vms docs) + * readme.vms: New section describing OpenVMS support and issues. + * default.c (default_variables): Add support for IA64. + * job.c (tryToSetupYAst) [VMS]: On VMS running make in batch mode + without some privilege aborts make with the error + %SYSTEM-F-NOPRIV. It happens when setting up a handler for + pressing Ctrl+Y and the input device is no terminal. The change + catches this error and just continues. + + Patches by Hartmut Becker + +2004-04-25 Paul D. Smith + + * commands.c (set_file_variables): Set $< properly in the face of + order-only prerequisites. + Patch from Boris Kolpackov + +2004-04-21 Bob Byrnes + + * main.c (main): Notice failures to remake makefiles. + +2004-03-28 Paul D. Smith + + Patches for Acorn RISC OS by Peter Naulls + + * job.c: No default shell for RISC OS. + (load_too_high): Hard-code the return to 1. + (construct_command_argv_internal): No sh_chars or sh_cmds. + * getloadavg.c: Don't set LOAD_AVE_TYPE on RISC OS. + 2004-03-20 Paul D. Smith * variable.c (do_variable_definition): Don't append from the diff --git a/Makefile.am b/Makefile.am index 77ebdf6..96fb188 100644 --- a/Makefile.am +++ b/Makefile.am @@ -114,11 +114,11 @@ check-local: check-regression check-loadavg .PHONY: check-loadavg check-regression -check-loadavg: loadavg +check-loadavg: loadavg$(EXEEXT) @echo The system uptime program believes the load average to be: -uptime @echo The GNU load average checking code thinks: - -./loadavg + -./loadavg$(EXEEXT) # The loadavg function is invoked during "make check" to test getloadavg. noinst_PROGRAMS = loadavg diff --git a/commands.c b/commands.c index a1766b4..b202f6c 100644 --- a/commands.c +++ b/commands.c @@ -41,6 +41,7 @@ extern int getpid (); static void set_file_variables (struct file *file) { + struct dep *d; char *at, *percent, *star, *less; #ifndef NO_ARCHIVES @@ -105,8 +106,14 @@ set_file_variables (struct file *file) } star = file->stem; - /* $< is the first dependency. */ - less = file->deps != 0 ? dep_name (file->deps) : ""; + /* $< is the first not order-only dependency. */ + less = ""; + for (d = file->deps; d != 0; d = d->next) + if (!d->ignore_mtime) + { + less = dep_name (d); + break; + } if (file->cmds == default_file->cmds) /* This file got its commands from .DEFAULT. @@ -134,7 +141,6 @@ set_file_variables (struct file *file) char *caret_value; char *qp; char *bp; - struct dep *d; unsigned int len; /* Compute first the value for $+, which is supposed to contain diff --git a/configure.in b/configure.in index b28c3fb..15c2b88 100644 --- a/configure.in +++ b/configure.in @@ -259,7 +259,8 @@ if test "$make_cv_sa_restart" != no; then [Define if defines the SA_RESTART constant.]) fi -# enable make_cv_sa_restart for OS/2 +# enable make_cv_sa_restart for OS/2 so that the jobserver will be enabled, +# but do it after HAVE_SA_RESTART has been defined. case "$host_os" in os2*) make_cv_sa_restart=yes ;; esac diff --git a/default.c b/default.c index b07f152..58855c6 100644 --- a/default.c +++ b/default.c @@ -308,7 +308,11 @@ static char *default_variables[] = #ifdef VMS #ifdef __ALPHA "ARCH", "ALPHA", -#else +#endif +#ifdef __ia64 + "ARCH", "IA64", +#endif +#ifdef __VAX "ARCH", "VAX", #endif "AR", "library/obj", diff --git a/dep.h b/dep.h index 7f4380b..4c9a152 100644 --- a/dep.h +++ b/dep.h @@ -74,5 +74,5 @@ extern char *dep_name (); extern struct dep *copy_dep_chain PARAMS ((struct dep *d)); extern struct dep *read_all_makefiles PARAMS ((char **makefiles)); extern int eval_buffer PARAMS ((char *buffer)); -extern int update_goal_chain PARAMS ((struct dep *goals, int makefiles)); +extern int update_goal_chain PARAMS ((struct dep *goals)); extern void uniquize_deps PARAMS ((struct dep *)); diff --git a/doc/make.texi b/doc/make.texi index 7270134..e694068 100644 --- a/doc/make.texi +++ b/doc/make.texi @@ -9,11 +9,11 @@ @set RCSID $Id$ @set EDITION 0.61 -@set VERSION 3.81 -@set UPDATED 02 May 2003 -@set UPDATE-MONTH May 2003 -@comment The ISBN number might need to change on next publication. -@set ISBN 1-882114-81-7 @c From Brian Youmans <3diff@gnu.org>, 25 Apr 2000 +@set VERSION 3.80 +@set UPDATED 23 Feb 2003 +@set UPDATE-MONTH Feb 2003 +@c ISBN provided by Lisa M. Opus Goldstein , 5 May 2004 +@set ISBN 1-882114-83-5 @c finalout @@ -6637,7 +6637,8 @@ files := $(shell echo *.c) @noindent sets @code{files} to the expansion of @samp{*.c}. Unless @code{make} is using a very strange shell, this has the same result as -@w{@samp{$(wildcard *.c)}}.@refill +@w{@samp{$(wildcard *.c)}} (as long as at least one @samp{.c} file +exists).@refill @node Make Control Functions, , Shell Function, Functions @section Functions That Control Make @@ -7519,8 +7520,8 @@ retained for compatibility. * Implicit Variables:: How to change what predefined rules do. * Chained Rules:: How to use a chain of implicit rules. * Pattern Rules:: How to define new implicit rules. -* Last Resort:: How to defining commands for rules - which cannot find any. +* Last Resort:: How to define commands for rules which + cannot find any. * Suffix Rules:: The old-fashioned style of implicit rule. * Implicit Rule Search:: The precise algorithm for applying implicit rules. @@ -9445,6 +9446,7 @@ Various new built-in implicit rules. @item The built-in variable @samp{MAKE_VERSION} gives the version number of @code{make}. +@vindex MAKE_VERSION @end itemize @node Missing, Makefile Conventions, Features, Top @@ -10220,9 +10222,11 @@ AUX = README COPYING ChangeLog Makefile.in \ level-0 level-1 backup-specs testpad.c @end group +.PHONY: all all: tar rmt tar.info @group +.PHONY: tar tar: $(OBJS) $(CC) $(LDFLAGS) -o $@@ $(OBJS) $(LIBS) @end group @@ -10238,6 +10242,7 @@ tar.info: tar.texinfo @end group @group +.PHONY: install install: all $(INSTALL) tar $(bindir)/$(binprefix)tar -test ! -f rmt || $(INSTALL) rmt /etc/rmt @@ -10266,21 +10271,25 @@ TAGS: $(SRCS) @end group @group +.PHONY: clean clean: rm -f *.o tar rmt testpad testpad.h core @end group @group +.PHONY: distclean distclean: clean rm -f TAGS Makefile config.status @end group @group +.PHONY: realclean realclean: distclean rm -f tar.info* @end group @group +.PHONY: shar shar: $(SRCS) $(AUX) shar $(SRCS) $(AUX) | compress \ > tar-`sed -e '/version_string/!d' \ @@ -10290,6 +10299,7 @@ shar: $(SRCS) $(AUX) @end group @group +.PHONY: dist dist: $(SRCS) $(AUX) echo tar-`sed \ -e '/version_string/!d' \ diff --git a/file.c b/file.c index 0d577d1..8f89503 100644 --- a/file.c +++ b/file.c @@ -342,6 +342,10 @@ remove_intermediates (int sig) if (! HASH_VACANT (*file_slot)) { register struct file *f = *file_slot; + /* Is this file eligible for automatic deletion? + Yes, IFF: it's marked intermediate, it's not secondary, it wasn't + given on the command-line, and it's either a -include makefile or + it's not precious. */ if (f->intermediate && (f->dontcare || !f->precious) && !f->secondary && !f->cmd_target) { @@ -679,7 +683,7 @@ print_file (const void *item) if (f->cmd_target) puts (_("# Command-line target.")); if (f->dontcare) - puts (_("# A default or MAKEFILES makefile.")); + puts (_("# A default, MAKEFILES, or -include/sinclude makefile.")); puts (f->tried_implicit ? _("# Implicit rule search has been done.") : _("# Implicit rule search has not been done.")); diff --git a/getloadavg.c b/getloadavg.c index c4d9746..16deff5 100644 --- a/getloadavg.c +++ b/getloadavg.c @@ -355,7 +355,7 @@ extern int errno; /* LOAD_AVE_TYPE should only get defined if we're going to use the nlist method. */ -# if !defined(LOAD_AVE_TYPE) && (defined(BSD) || defined(LDAV_CVT) || defined(KERNEL_FILE) || defined(LDAV_SYMBOL)) +# if !defined(LOAD_AVE_TYPE) && (defined(BSD) || defined(LDAV_CVT) || defined(KERNEL_FILE) || defined(LDAV_SYMBOL)) && !defined(__riscos__) # define LOAD_AVE_TYPE double # endif diff --git a/job.c b/job.c index 0153995..13431d3 100644 --- a/job.c +++ b/job.c @@ -63,6 +63,11 @@ int batch_mode_shell = 0; char default_shell[] = ""; int batch_mode_shell = 0; +#elif defined (__riscos__) + +char default_shell[] = ""; +int batch_mode_shell = 0; + #else char default_shell[] = "/bin/sh"; @@ -1725,7 +1730,7 @@ job_next_command (struct child *child) static int load_too_high (void) { -#if defined(__MSDOS__) || defined(VMS) || defined(_AMIGA) +#if defined(__MSDOS__) || defined(VMS) || defined(_AMIGA) || defined(__riscos__) return 1; #else static double last_sec; @@ -1953,7 +1958,9 @@ static void tryToSetupYAst(void) { } status= sys$qiow (0, chan, IO$_SETMODE|IO$M_CTRLYAST,&iosb,0,0, astHandler,0,0,0,0,0); - if (status==SS$_ILLIOFUNC) { + if (status==SS$_NORMAL) + status= iosb.status; + if (status==SS$_ILLIOFUNC || status==SS$_NOPRIV) { sys$dassgn(chan); #ifdef CTRLY_ENABLED_ANYWAY fprintf (stderr, @@ -1962,9 +1969,8 @@ static void tryToSetupYAst(void) { return; #endif } - if (status==SS$_NORMAL) - status= iosb.status; - if (!(status&SS$_NORMAL)) { + else if (!(status&SS$_NORMAL)) { + sys$dassgn(chan); lib$signal(status); return; } @@ -2773,6 +2779,9 @@ construct_command_argv_internal (char *line, char **restp, char *shell, 0 }; char* sh_chars; char** sh_cmds; +#elif defined(__riscos__) + static char sh_chars[] = ""; + static char *sh_cmds[] = { 0 }; #else /* must be UNIX-ish */ static char sh_chars[] = "#;\"*?[]&|<>(){}$`^~!"; static char *sh_cmds[] = { ".", ":", "break", "case", "cd", "continue", @@ -3295,7 +3304,22 @@ construct_command_argv_internal (char *line, char **restp, char *shell, We use line here instead of new_line because we run the shell manually. */ size_t line_len = strlen (line); + char *p = new_line; + char *q = new_line; memcpy (new_line, line, line_len + 1); + /* replace all backslash-newline combination and also following tabs */ + while (*q != '\0') + { + if (q[0] == '\\' && q[1] == '\n') + { + q += 2; /* remove '\\' and '\n' */ + if (q[0] == '\t') + q++; /* remove 1st tab in the next line */ + } + else + *p++ = *q++; + } + *p = '\0'; # ifndef NO_CMD_DEFAULT if (strnicmp (new_line, "echo", 4) == 0 @@ -3338,7 +3362,7 @@ construct_command_argv_internal (char *line, char **restp, char *shell, new_argv[1] = new_argv[0] + sh_len + 1; memcpy (new_argv[1], "/c", 3); new_argv[2] = new_argv[1] + 3; - memcpy (new_argv[2], new_line, line_len); + memcpy (new_argv[2], new_line, line_len + 1); new_argv[3] = NULL; } } diff --git a/main.c b/main.c index d17e576..13c3415 100644 --- a/main.c +++ b/main.c @@ -259,6 +259,11 @@ int warn_undefined_variables_flag; they appear out of date or not. */ int always_make_flag = 0; + +/* If nonzero, we're in the "try to rebuild makefiles" phase. */ + +int rebuilding_makefiles = 0; + /* The usage output. We write it this way to make life easier for the translators, especially those trying to translate to right-to-left @@ -839,6 +844,7 @@ main (int argc, char **argv, char **envp) static char *stdin_nm = 0; struct file *f; int i; + int makefile_status = MAKE_SUCCESS; char **p; struct dep *read_makefiles; PATH_VAR (current_directory); @@ -1666,6 +1672,7 @@ main (int argc, char **argv, char **envp) char **nargv = argv; int nargc = argc; int orig_db_level = db_level; + int status; if (! ISDB (DB_MAKEFILES)) db_level = DB_NONE; @@ -1726,7 +1733,11 @@ main (int argc, char **argv, char **envp) /* Set up `MAKEFLAGS' specially while remaking makefiles. */ define_makeflags (1, 1); - switch (update_goal_chain (read_makefiles, 1)) + rebuilding_makefiles = 1; + status = update_goal_chain (read_makefiles); + rebuilding_makefiles = 0; + + switch (status) { case 1: /* The only way this can happen is if the user specified -q and asked @@ -1775,6 +1786,7 @@ main (int argc, char **argv, char **envp) mtime = file_mtime_no_search (d->file); any_remade |= (mtime != NONEXISTENT_MTIME && mtime != makefile_mtimes[i]); + makefile_status = MAKE_FAILURE; } } else @@ -1985,13 +1997,13 @@ main (int argc, char **argv, char **envp) DB (DB_BASIC, (_("Updating goal targets....\n"))); - switch (update_goal_chain (goals, 0)) + switch (update_goal_chain (goals)) { case -1: /* Nothing happened. */ case 0: /* Updated successfully. */ - status = MAKE_SUCCESS; + status = makefile_status; break; case 1: /* We are under -q and would run some commands. */ diff --git a/make.h b/make.h index ea8f07c..ce88d5c 100644 --- a/make.h +++ b/make.h @@ -496,7 +496,7 @@ extern int print_data_base_flag, question_flag, touch_flag, always_make_flag; extern int env_overrides, no_builtin_rules_flag, no_builtin_variables_flag; extern int print_version_flag, print_directory_flag; extern int warn_undefined_variables_flag, posix_pedantic, not_parallel; -extern int clock_skew_detected; +extern int clock_skew_detected, rebuilding_makefiles; /* can we run commands via 'sh -c xxx' or must we use batch files? */ extern int batch_mode_shell; diff --git a/makefile.vms b/makefile.vms index 3ada831..6ed86c1 100644 --- a/makefile.vms +++ b/makefile.vms @@ -5,6 +5,7 @@ # Klaus Kämpf (kkaempf@rmi.de) # Modified for version 3.78.1 by Hartmut.Becker@compaq.com. # Modified for version 3.80 by zinser@decus.de +# Modified for version 3.81 by Hartmut Becker # # GNU Make is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -31,7 +32,7 @@ CP = copy # ifeq ($(CC),cc) -CFLAGS = $(defines) /include=([],[.glob])/prefix=all/standard=relaxed +CFLAGS = $(defines) /include=([],[.glob])/prefix=(all,except=(glob,globfree))/standard=relaxed else CFLAGS = $(defines) /include=([],[.glob]) endif @@ -111,7 +112,6 @@ make.exe: $(objs) clean: $$ purge [...] -$(RM) make.exe;,*.obj; - -$(RM) *.opt; -$(RM) [.glob]*.obj; # Automatically generated dependencies. diff --git a/read.c b/read.c index 1da2eac..e2ad630 100644 --- a/read.c +++ b/read.c @@ -367,16 +367,14 @@ eval_makefile (char *filename, int flags) deps->name = 0; deps->file = lookup_file (filename); if (deps->file == 0) - { - deps->file = enter_file (xstrdup (filename)); - if (flags & RM_DONTCARE) - deps->file->dontcare = 1; - } + deps->file = enter_file (xstrdup (filename)); if (filename != ebuf.floc.filenm) free (filename); filename = deps->file->name; deps->changed = flags; deps->ignore_mtime = 0; + if (flags & RM_DONTCARE) + deps->file->dontcare = 1; /* If the makefile can't be found at all, give up entirely. */ diff --git a/readme.vms b/readme.vms index d4a9667..6e1436f 100644 --- a/readme.vms +++ b/readme.vms @@ -1,3 +1,54 @@ +This is the VMS version of GNU Make, updated by Hartmut Becker + +Changes are based on GNU make 3.80. Latest changes are for OpenVMS/I64 +and new VMS CRTLs. + +This version was tested on OpenVMS/I64 V8.2 (field test) with hp C +X7.1-024 OpenVMS/Alpha V7.3-2 with Compaq C V6.5-001 and OpenVMS/VAX 7.1 +with Compaq C V6.2-003 There are still some warning and informational +message issued by the compilers. + +Build instructions +Make a 1st version + $ @makefile.com + $ rena make.exe 1st-make.exe +Use the 1st version to generate a 2nd version + $ mc sys$disk:[]1st-make clean + $ mc sys$disk:[]1st-make +Verify your 2nd version + $ rena make.exe 2nd-make.exe + $ mc sys$disk:[]2nd-make clean + $ mc sys$disk:[]2nd-make + +Changes: + +. In default.c define variable ARCH as IA64 for VMS on Itanium systems. + +. In makefile.vms avoid name collision for glob and globfree. + +In newer version of the VMS CRTL there are glob and globfree implemented. +Compiling and linking may result in + + %ILINK-W-MULDEFLNKG, symbol DECC$GLOBFREE has subsequent linkage definition + in module DECC$SHR file SYS$COMMON:[SYSLIB]DECC$SHR.EXE;1 + %ILINK-W-MULDEF, symbol DECC$GLOBFREE multiply defined + in module DECC$SHR file SYS$COMMON:[SYSLIB]DECC$SHR.EXE;1 + +linker messages (and similar for DECC$GLOB). The messages just say, that +globfree is a known CRTL whose name was mapped by the compiler to +DECC$GLOBFREE. This is done in glob.c as well, so this name is defined +twice. One possible solution is to use the VMS versions of glob and +globfree. However, then the build environment needs to figure out if +there is a new CRTL supporting these or not. This adds complexity. Even +more, these functions return VMS file specifications, which is not +expected by the other make sources. There is a switch at run time (a VMS +logical DECC$GLOB_UNIX_STYLE), which can be set to get Unix style +names. This may conflict with other software. The recommended solution +for this is to set this switch just prior to calling main: in an +initialization routine. This adds more complexity and more VMS specific +code. It is easier to tell the compiler NOT to map the routine names +with a simple change in makefile.vms. + This is the VMS port of GNU Make done by Hartmut.Becker@compaq.com. It is based on the specific version 3.77k and on 3.78.1. 3.77k was done diff --git a/remake.c b/remake.c index 619aec0..b0c76dc 100644 --- a/remake.c +++ b/remake.c @@ -73,19 +73,20 @@ static int library_search PARAMS ((char **lib, FILE_TIMESTAMP *mtime_ptr)); /* Remake all the goals in the `struct dep' chain GOALS. Return -1 if nothing was done, 0 if all goals were updated successfully, or 1 if a goal failed. - If MAKEFILES is nonzero, these goals are makefiles, so -t, -q, and -n should - be disabled for them unless they were also command-line targets, and we - should only make one goal at a time and return as soon as one goal whose - `changed' member is nonzero is successfully made. */ + + If rebuilding_makefiles is nonzero, these goals are makefiles, so -t, -q, + and -n should be disabled for them unless they were also command-line + targets, and we should only make one goal at a time and return as soon as + one goal whose `changed' member is nonzero is successfully made. */ int -update_goal_chain (struct dep *goals, int makefiles) +update_goal_chain (struct dep *goals) { int t = touch_flag, q = question_flag, n = just_print_flag; unsigned int j = job_slots; int status = -1; -#define MTIME(file) (makefiles ? file_mtime_no_search (file) \ +#define MTIME(file) (rebuilding_makefiles ? file_mtime_no_search (file) \ : file_mtime (file)) /* Duplicate the chain so we can remove things from it. */ @@ -135,7 +136,7 @@ update_goal_chain (struct dep *goals, int makefiles) unsigned int ocommands_started; int x; check_renamed (file); - if (makefiles) + if (rebuilding_makefiles) { if (file->cmd_target) { @@ -152,7 +153,7 @@ update_goal_chain (struct dep *goals, int makefiles) actually run. */ ocommands_started = commands_started; - x = update_file (file, makefiles ? 1 : 0); + x = update_file (file, rebuilding_makefiles ? 1 : 0); check_renamed (file); /* Set the goal's `changed' flag if any commands were started @@ -176,7 +177,7 @@ update_goal_chain (struct dep *goals, int makefiles) matter how much more we run, since we already know the answer to return. */ stop = (!keep_going_flag && !question_flag - && !makefiles); + && !rebuilding_makefiles); } else { @@ -192,10 +193,10 @@ update_goal_chain (struct dep *goals, int makefiles) as a command-line target), don't change STATUS. If STATUS is changed, we will get re-exec'd, and enter an infinite loop. */ - if (!makefiles + if (!rebuilding_makefiles || (!just_print_flag && !question_flag)) status = 0; - if (makefiles && file->dontcare) + if (rebuilding_makefiles && file->dontcare) /* This is a default makefile; stop remaking. */ stop = 1; } @@ -218,7 +219,7 @@ update_goal_chain (struct dep *goals, int makefiles) /* If we have found nothing whatever to do for the goal, print a message saying nothing needs doing. */ - if (!makefiles + if (!rebuilding_makefiles /* If the update_status is zero, we updated successfully or not at all. G->changed will have been set above if any commands were actually started for this goal. */ @@ -257,7 +258,7 @@ update_goal_chain (struct dep *goals, int makefiles) considered = !considered; } - if (makefiles) + if (rebuilding_makefiles) { touch_flag = t; question_flag = q; @@ -321,19 +322,44 @@ update_file (struct file *file, unsigned int depth) /* Process the remaining rules in the double colon chain so they're marked considered. Start their prerequisites, too. */ - for (; f != 0 ; f = f->prev) - { - struct dep *d; + if (file->double_colon) + for (; f != 0 ; f = f->prev) + { + struct dep *d; - f->considered = considered; + f->considered = considered; - for (d = f->deps; d != 0; d = d->next) - status |= update_file (d->file, depth + 1); - } + for (d = f->deps; d != 0; d = d->next) + status |= update_file (d->file, depth + 1); + } return status; } +/* Show a message stating the target failed to build. */ + +static void +complain (const struct file *file) +{ + const char *msg_noparent + = _("%sNo rule to make target `%s'%s"); + const char *msg_parent + = _("%sNo rule to make target `%s', needed by `%s'%s"); + + if (!keep_going_flag) + { + if (file->parent == 0) + fatal (NILF, msg_noparent, "", file->name, ""); + + fatal (NILF, msg_parent, "", file->name, file->parent->name, ""); + } + + if (file->parent == 0) + error (NILF, msg_noparent, "*** ", file->name, "."); + else + error (NILF, msg_parent, "*** ", file->name, file->parent->name, "."); +} + /* Consider a single `struct file' and update it as appropriate. */ static int @@ -353,6 +379,17 @@ update_file_1 (struct file *file, unsigned int depth) { DBF (DB_VERBOSE, _("Recently tried and failed to update file `%s'.\n")); + + /* If the file we tried to make is marked dontcare then no message + was printed about it when it failed during the makefile rebuild. + If we're trying to build it again in the normal rebuild, print a + message now. */ + if (file->dontcare && !rebuilding_makefiles) + { + file->dontcare = 0; + complain (file); + } + return file->update_status; } @@ -1008,28 +1045,9 @@ remake_file (struct file *file) file->update_status = 0; else { - const char *msg_noparent - = _("%sNo rule to make target `%s'%s"); - const char *msg_parent - = _("%sNo rule to make target `%s', needed by `%s'%s"); - /* This is a dependency file we cannot remake. Fail. */ - if (!keep_going_flag && !file->dontcare) - { - if (file->parent == 0) - fatal (NILF, msg_noparent, "", file->name, ""); - - fatal (NILF, msg_parent, "", file->name, file->parent->name, ""); - } - - if (!file->dontcare) - { - if (file->parent == 0) - error (NILF, msg_noparent, "*** ", file->name, "."); - else - error (NILF, msg_parent, "*** ", - file->name, file->parent->name, "."); - } + if (!rebuilding_makefiles || !file->dontcare) + complain (file); file->update_status = 2; } } diff --git a/tests/run_make_tests.pl b/tests/run_make_tests.pl index 4389d43..8452c6b 100755 --- a/tests/run_make_tests.pl +++ b/tests/run_make_tests.pl @@ -48,66 +48,100 @@ sub valid_option return 0; } -sub run_make_with_options + +# This is an "all-in-one" function. Arguments are as follows: +# +# [0] (string): The makefile to be tested. +# [1] (string): Arguments to pass to make. +# [2] (string): Answer we should get back. +# [3] (integer): Exit code we expect. A missing code means 0 (success) + +sub run_make_test { - local ($filename,$options,$logname,$expected_code) = @_; - local($code); - local($command) = $make_path; + local ($makestring, $options, $answer, $err_code) = @_; - $expected_code = 0 unless defined($expected_code); + if (! defined($makefile)) { + $makefile = &get_tmpfile(); + } - if ($filename) - { - $command .= " -f $filename"; - } + # Replace @MAKEFILE@ with the makefile name and @MAKE@ with the path to + # make in both $makestring and $answer. - if ($options) - { - $command .= " $options"; - } + $makestring =~ s/#MAKEFILE#/$makefile/g; + $makestring =~ s/#MAKE#/$make_name/g; - if ($valgrind) { - print VALGRIND "\n\nExecuting: $command\n"; - } + $answer =~ s/#MAKEFILE#/$makefile/g; + $answer =~ s/#MAKE#/$make_name/g; - $code = &run_command_with_output($logname,$command); + open(MAKEFILE, "> $makefile") || die "Failed to open $makefile: $!\n"; + print MAKEFILE $makestring, "\n"; + close(MAKEFILE) || die "Failed to write $makefile: $!\n"; - # Check to see if we have Purify errors. If so, keep the logfile. - # For this to work you need to build with the Purify flag -exit-status=yes + &run_make_with_options($makefile, $options, &get_logfile(0), $err_code); + &compare_output($answer, &get_logfile(1)); - if ($pure_log && -f $pure_log) { - if ($code & 0x7000) { - $code &= ~0x7000; + $makefile = undef; +} - # If we have a purify log, save it - $tn = $pure_testname . ($num_of_logfiles ? ".$num_of_logfiles" : ""); - print("Renaming purify log file to $tn\n") if $debug; - rename($pure_log, "$tn") - || die "Can't rename $log to $tn: $!\n"; - ++$purify_errors; - } - else { - unlink($pure_log); - } - } +# The old-fashioned way... +sub run_make_with_options { + local ($filename,$options,$logname,$expected_code) = @_; + local($code); + local($command) = $make_path; - if ($code != $expected_code) - { - print "Error running $make_path ($code): $command\n"; - $test_passed = 0; - # If it's a SIGINT, stop here - if ($code & 127) { - print STDERR "\nCaught signal ".($code & 127)."!\n"; - exit($code); - } - return 0; - } + $expected_code = 0 unless defined($expected_code); - if ($profile & $vos) - { - system "add_profile $make_path"; - } -1; + # Reset to reflect this one test. + $test_passed = 1; + + if ($filename) { + $command .= " -f $filename"; + } + + if ($options) { + $command .= " $options"; + } + + if ($valgrind) { + print VALGRIND "\n\nExecuting: $command\n"; + } + + $code = &run_command_with_output($logname,$command); + + # Check to see if we have Purify errors. If so, keep the logfile. + # For this to work you need to build with the Purify flag -exit-status=yes + + if ($pure_log && -f $pure_log) { + if ($code & 0x7000) { + $code &= ~0x7000; + + # If we have a purify log, save it + $tn = $pure_testname . ($num_of_logfiles ? ".$num_of_logfiles" : ""); + print("Renaming purify log file to $tn\n") if $debug; + rename($pure_log, "$tn") + || die "Can't rename $log to $tn: $!\n"; + ++$purify_errors; + } else { + unlink($pure_log); + } + } + + if ($code != $expected_code) { + print "Error running $make_path (expected $expected_code; got $code): $command\n"; + $test_passed = 0; + # If it's a SIGINT, stop here + if ($code & 127) { + print STDERR "\nCaught signal ".($code & 127)."!\n"; + exit($code); + } + return 0; + } + + if ($profile & $vos) { + system "add_profile $make_path"; + } + + 1; } sub print_usage diff --git a/tests/scripts/features/echoing b/tests/scripts/features/echoing index ed1e862..2e366cd 100644 --- a/tests/scripts/features/echoing +++ b/tests/scripts/features/echoing @@ -54,13 +54,10 @@ $answer = "echo This makefile did not clean the dir... good\n" # ------- &run_make_with_options($makefile,"clean",&get_logfile,0); -$answer = ""; -&compare_output($answer,&get_logfile(1)); - -if (-f $example) -{ - $test_passed = 0; +if (-f $example) { + $test_passed = 0; } +&compare_output('',&get_logfile(1)); # TEST #3 # ------- diff --git a/tests/scripts/features/errors b/tests/scripts/features/errors index a39064f..253f50f 100644 --- a/tests/scripts/features/errors +++ b/tests/scripts/features/errors @@ -52,6 +52,13 @@ $answer = "$delete_command cleanit\n" &run_make_with_options($makefile,"",&get_logfile); +# If make acted as planned, it should ignore the error from the first +# command in the target and execute the second which deletes the file "foo" +# This file, therefore, should not exist if the test PASSES. +if (-f "foo") { + $test_passed = 0; +} + # The output for this on VOS is too hard to replicate, so we only check it # on unix. if (!$vos) @@ -59,14 +66,6 @@ if (!$vos) &compare_output($answer,&get_logfile(1)); } -# If make acted as planned, it should ignore the error from the first -# command in the target and execute the second which deletes the file "foo" -# This file, therefore, should not exist if the test PASSES. -if (-f "foo") -{ - $test_passed = 0; -} - &touch("foo"); @@ -80,14 +79,12 @@ $answer = "$delete_command cleanit\n" &run_make_with_options($makefile,"clean2 -i",&get_logfile); -if (!$vos) -{ - &compare_output($answer,&get_logfile(1)); +if (-f "foo") { + $test_passed = 0; } -if (-f "foo") -{ - $test_passed = 0; +if (!$vos) { + &compare_output($answer,&get_logfile(1)); } 1; diff --git a/tests/scripts/features/include b/tests/scripts/features/include index 60f4482..5f20ad8 100644 --- a/tests/scripts/features/include +++ b/tests/scripts/features/include @@ -2,7 +2,8 @@ $description = "Test various forms of the GNU make `include' command."; -$details = "Test include, -include, sinclude and various regressions involving them. +$details = "\ +Test include, -include, sinclude and various regressions involving them. Test extra whitespace at the end of the include, multiple -includes and sincludes (should not give an error) and make sure that errors are reported for targets that were also -included."; @@ -46,16 +47,36 @@ $answer = "There should be no errors for this makefile.\n"; $answer = "This is another included makefile\n"; &compare_output($answer, &get_logfile(1)); +$makefile = undef; + # Try to build the "error" target; this will fail since we don't know # how to create makeit.mk, but we should also get a message (even though # the -include suppressed it during the makefile read phase, we should # see one during the makefile run phase). -# The fix to this caused more problems than the error, so I removed it. -# pds -- 22 Jan 2000 +run_make_test + (' +-include foo.mk +error: foo.mk ; @echo $@ +', + '', + "#MAKE#: *** No rule to make target `foo.mk', needed by `error'. Stop.\n", + 512 + ); + +# Make sure that target-specific variables don't impact things. This could +# happen because a file record is created when a target-specific variable is +# set. + +run_make_test + (' +bar.mk: foo := baz +-include bar.mk +hello: ; @echo hello +', + '', + "hello\n" + ); -#&run_make_with_options($makefile, "error", &get_logfile, 512); -#$answer = "$make_name: *** No rule to make target `makeit.mk', needed by `error'.\n"; -#&compare_output($answer, &get_logfile(1)); 1; diff --git a/tests/scripts/features/order_only b/tests/scripts/features/order_only index ac0d538..82a7253 100644 --- a/tests/scripts/features/order_only +++ b/tests/scripts/features/order_only @@ -144,4 +144,15 @@ $answer = "touch baz\n"; unlink(qw(foo.w foo.x baz)); +# TEST #9 -- make sure that $< is set correctly in the face of order-only +# prerequisites in pattern rules. + +run_make_test(' +%r: | baz ; @echo $< $^ $| +bar: foo +foo:;@: +baz:;@: +', '', "foo foo baz\n"); + + 1; diff --git a/tests/scripts/functions/wildcard b/tests/scripts/functions/wildcard index 0f79acc..5e5a5ff 100644 --- a/tests/scripts/functions/wildcard +++ b/tests/scripts/functions/wildcard @@ -85,13 +85,12 @@ else &run_make_with_options($makefile,"clean",&get_logfile); -&compare_output($answer,&get_logfile(1)); - -if ((-f "example.1")||(-f "example.two")||(-f "example.3")||(-f "example.for")) -{ +if ((-f "example.1")||(-f "example.two")||(-f "example.3")||(-f "example.for")) { $test_passed = 0; } +&compare_output($answer,&get_logfile(1)); + 1; diff --git a/tests/scripts/options/dash-C b/tests/scripts/options/dash-C index 3f2b3a1..f31238f 100644 --- a/tests/scripts/options/dash-C +++ b/tests/scripts/options/dash-C @@ -33,6 +33,10 @@ chdir $workdir; $wpath = &get_this_pwd; chdir $pwd; +if (-f $example) { + $test_passed = 0; +} + # Create the answer to what should be produced by this Makefile $answer = "$make_name: Entering directory `$wpath'\n" . "$delete_command EXAMPLE_FILE\n" @@ -40,9 +44,4 @@ $answer = "$make_name: Entering directory `$wpath'\n" &compare_output($answer,&get_logfile(1)); -if (-f $example) -{ - $test_passed = 0; -} - 1; diff --git a/tests/scripts/options/dash-k b/tests/scripts/options/dash-k index fe5689e..d87a786 100644 --- a/tests/scripts/options/dash-k +++ b/tests/scripts/options/dash-k @@ -97,4 +97,18 @@ $make_name: Target `all' not remade because of errors.\n"; &compare_output($answer, &get_logfile(1)); +# TEST -- make sure we keep the error code if we can't create an included +# makefile. + +run_make_test('all: ; @echo hi +include ifile +ifile: no-such-file; @false +', + '-k', + "#MAKEFILE#:2: ifile: No such file or directory +#MAKE#: *** No rule to make target `no-such-file', needed by `ifile'. +#MAKE#: Failed to remake makefile `ifile'. +hi\n", + 512); + 1; diff --git a/tests/scripts/targets/FORCE b/tests/scripts/targets/FORCE index 90ee48d..befb326 100644 --- a/tests/scripts/targets/FORCE +++ b/tests/scripts/targets/FORCE @@ -1,4 +1,4 @@ -$description = "The following tests rules without Commands or Dependencies."; +$description = "The following tests rules without Commands or Dependencies."; $details = "If the rule ...\n"; @@ -17,7 +17,7 @@ open(MAKEFILE,"> $makefile"); print MAKEFILE ".IGNORE :\n"; print MAKEFILE "clean: FORCE\n"; -print MAKEFILE "\t$delete_command clean\n"; +print MAKEFILE "\t$delete_command clean\n"; print MAKEFILE "FORCE:\n"; # END of Contents of MAKEFILE @@ -26,20 +26,15 @@ close(MAKEFILE); # Create a file named "clean". This is the same name as the target clean -# and tricks the target into thinking that it is up to date. (Unless you +# and tricks the target into thinking that it is up to date. (Unless you # use the .PHONY target. &touch("clean"); $answer = "$delete_command clean\n"; &run_make_with_options($makefile,"clean",&get_logfile); -&compare_output($answer,&get_logfile(1)); +&compare_output($answer,&get_logfile(1)); -if (-f $example) -{ - $test_passed = 0; -} - 1; diff --git a/tests/scripts/targets/PHONY b/tests/scripts/targets/PHONY index 14d5ae1..dd46b3f 100644 --- a/tests/scripts/targets/PHONY +++ b/tests/scripts/targets/PHONY @@ -27,7 +27,7 @@ print MAKEFILE ".PHONY : clean \n"; print MAKEFILE "all: \n"; print MAKEFILE "\t\@echo This makefile did not clean the dir ... good\n"; print MAKEFILE "clean: \n"; -print MAKEFILE "\t$delete_command $example clean\n"; +print MAKEFILE "\t$delete_command $example clean\n"; # END of Contents of MAKEFILE @@ -36,20 +36,19 @@ close(MAKEFILE); &touch($example); # Create a file named "clean". This is the same name as the target clean -# and tricks the target into thinking that it is up to date. (Unless you +# and tricks the target into thinking that it is up to date. (Unless you # use the .PHONY target. &touch("clean"); $answer = "$delete_command $example clean\n"; &run_make_with_options($makefile,"clean",&get_logfile); -&compare_output($answer,&get_logfile(1)); - -if (-f $example) -{ - $test_passed = 0; +if (-f $example) { + $test_passed = 0; } - + +&compare_output($answer,&get_logfile(1)); + 1; diff --git a/tests/scripts/targets/SILENT b/tests/scripts/targets/SILENT index 375cad4..5f9a1db 100644 --- a/tests/scripts/targets/SILENT +++ b/tests/scripts/targets/SILENT @@ -22,7 +22,7 @@ open(MAKEFILE,"> $makefile"); print MAKEFILE ".SILENT : clean\n"; print MAKEFILE "clean: \n"; -print MAKEFILE "\t$delete_command EXAMPLE_FILE\n"; +print MAKEFILE "\t$delete_command EXAMPLE_FILE\n"; # END of Contents of MAKEFILE @@ -32,13 +32,11 @@ close(MAKEFILE); $answer = ""; &run_make_with_options($makefile,"clean",&get_logfile,0); - -&compare_output($answer,&get_logfile(1)); -if (-f $example) -{ - $test_passed = 0; +if (-f $example) { + $test_passed = 0; } - +&compare_output($answer,&get_logfile(1)); + 1; diff --git a/tests/scripts/targets/clean b/tests/scripts/targets/clean index 69f4fd1..b32c976 100644 --- a/tests/scripts/targets/clean +++ b/tests/scripts/targets/clean @@ -33,11 +33,10 @@ $answer = "This makefile did not clean the dir... good\n"; $answer = "$delete_command $example\n"; &run_make_with_options($makefile,"clean",&get_logfile,0); - -&compare_output($answer,&get_logfile(1)) || &error ("abort"); if (-f $example) { - $test_passed = 0; + $test_passed = 0; } +&compare_output($answer,&get_logfile(1)) || &error ("abort"); 1; diff --git a/tests/scripts/variables/special b/tests/scripts/variables/special index 58c8655..77b355c 100644 --- a/tests/scripts/variables/special +++ b/tests/scripts/variables/special @@ -4,12 +4,7 @@ $description = "Test special GNU make variables."; $details = ""; -$makefile2 = &get_tmpfile; - - -open(MAKEFILE, "> $makefile"); - -print MAKEFILE <<'EOF'; +&run_make_test(' X1 := $(sort $(filter FOO BAR,$(.VARIABLES))) @@ -23,21 +18,12 @@ all: @echo X1 = $(X1) @echo X2 = $(X2) @echo LAST = $(sort $(filter FOO BAR,$(.VARIABLES))) - -EOF - -close(MAKEFILE); - -# TEST #1 -# ------- - -&run_make_with_options($makefile, "", &get_logfile); -$answer = "X1 =\nX2 = FOO\nLAST = BAR FOO\n"; -&compare_output($answer, &get_logfile(1)); - +', + '', "X1 =\nX2 = FOO\nLAST = BAR FOO\n"); +# $makefile2 = &get_tmpfile; # open(MAKEFILE, "> $makefile2"); # print MAKEFILE <<'EOF'; diff --git a/tests/test_driver.pl b/tests/test_driver.pl index 0ddb884..0bca669 100644 --- a/tests/test_driver.pl +++ b/tests/test_driver.pl @@ -28,6 +28,10 @@ $tests_run = 0; # The number of tests in this category that have passed $tests_passed = 0; + +# Yeesh. This whole test environment is such a hack! +$test_passed = 1; + sub toplevel { # Get a clean environment @@ -376,7 +380,7 @@ sub run_each_test foreach $testname (sort @TESTS) { ++$categories_run; - $passed = 1; # reset by test on failure + $suite_passed = 1; # reset by test on failure $num_of_logfiles = 0; $num_of_tmpfiles = 0; $description = ""; @@ -423,7 +427,7 @@ sub run_each_test # How did it go? if (!defined($code)) { - $passed = 0; + $suite_passed = 0; if (length ($@)) { warn "\n*** Test died ($testname): $@\n"; @@ -434,14 +438,14 @@ sub run_each_test } } elsif ($code == -1) { - $passed = 0; + $suite_passed = 0; } elsif ($code != 1 && $code != -1) { - $passed = 0; + $suite_passed = 0; warn "\n*** Test returned $code\n"; } - if ($passed) { + if ($suite_passed) { ++$categories_passed; $status = "ok ($tests_passed passed)"; for ($i = $num_of_tmpfiles; $i; $i--) @@ -608,10 +612,7 @@ sub compare_output local($answer,$logfile) = @_; local($slurp); - if ($debug) - { - print "Comparing Output ........ "; - } + print "Comparing Output ........ " if $debug; $slurp = &read_file_into_string ($logfile); @@ -622,34 +623,28 @@ sub compare_output ++$tests_run; - if ($slurp eq $answer) + if ($slurp eq $answer && $test_passed) { - if ($debug) - { - print "ok\n"; - } + print "ok\n" if $debug; ++$tests_passed; return 1; } - else - { - if ($debug) - { - print "DIFFERENT OUTPUT\n"; - } - $passed = 0; + + if ($slurp ne $answer) { + print "DIFFERENT OUTPUT\n" if $debug; + &create_file (&get_basefile, $answer); - if ($debug) - { - print "\nCreating Difference File ...\n"; - } + print "\nCreating Difference File ...\n" if $debug; + # Create the difference file local($command) = "diff -c " . &get_basefile . " " . $logfile; &run_command_with_output(&get_difffile,$command); - return 0; } + + $suite_passed = 0; + return 0; } sub read_file_into_string -- 2.7.4