Subject: bin/11800: make doesn't warn about duplicate : rule commands
To: None <gnats-bugs@gnats.netbsd.org>
From: None <cgd@netbsd.org>
List: netbsd-bugs
Date: 12/22/2000 15:44:17
>Number:         11800
>Category:       bin
>Synopsis:       make doesn't warn about duplicate : rule commands
>Confidential:   no
>Severity:       serious
>Priority:       high
>Responsible:    bin-bug-people
>State:          open
>Class:          change-request
>Submitter-Id:   net
>Arrival-Date:   Fri Dec 22 15:44:00 PST 2000
>Closed-Date:
>Last-Modified:
>Originator:     Chris G. Demetriou
>Release:        NetBSD 1.5, NetBSD-current as of 2000-12-22.
>Organization:
>Environment:
NetBSD 1.5 or current NetBSD sources.

>Description:

NetBSD make doesn't warn about targets which are made by : rules
but which are given multiple (confliction) lists of commands
to use to make them.

>How-To-Repeat:

cat > /tmp/lose << __EOF__
foo:
	echo foo

foo:
	echo bar
__EOF__

make -f /tmp/lose foo

This chooses the former rule's command(s) to make the target, and thus
invokes "echo foo".  The latter rule's commands are silently ignored.
Operation here is obviously not well defined.  GNU make uses the latter
set of commands, Solaris make the former.  But bother warn about it.

>Fix:

The patch below issues a warning when the situation above is encountered.
It also provides an option that can cause all makefile-parsing warnings
(e.g. the one added 8-) to be treated as errors.

Personally, I think this is an error situation, but other makes treat
it as a warning, and certain makfiles in our source tree would stop
working if it were made an error...  8-)

The patch below also makes the program name printed on errors and
warnings a bit more consistent.  in most places, make just says
"make", but in a few (in particular, calls through Error()) it
uses 'progname' set from argv[0].  This patch converts it to use
"make" all over.  (Not the right solution, but at least it gets
rid of the inconsistency.)

Index: main.c
===================================================================
RCS file: /cvsroot/basesrc/usr.bin/make/main.c,v
retrieving revision 1.57
diff -c -r1.57 main.c
*** main.c	2000/06/06 03:00:11	1.57
--- main.c	2000/12/22 23:32:58
***************
*** 137,142 ****
--- 137,143 ----
  Boolean			beSilent;	/* -s flag */
  Boolean			oldVars;	/* variable substitution style */
  Boolean			checkEnvFirst;	/* -e flag */
+ Boolean			parseWarnFatal;	/* -W flag */
  static Boolean		jobsRunning;	/* TRUE if the jobs might be running */
  
  static char *		Check_Cwd_av __P((int, char **, int));
***************
*** 174,182 ****
  
  	optind = 1;	/* since we're called more than once */
  #ifdef REMOTE
! # define OPTFLAGS "BD:I:L:PSV:d:ef:ij:km:nqrst"
  #else
! # define OPTFLAGS "BD:I:PSV:d:ef:ij:km:nqrst"
  #endif
  rearg:	while((c = getopt(argc, argv, OPTFLAGS)) != -1) {
  		switch(c) {
--- 175,183 ----
  
  	optind = 1;	/* since we're called more than once */
  #ifdef REMOTE
! # define OPTFLAGS "BD:I:L:PSV:Wd:ef:ij:km:nqrst"
  #else
! # define OPTFLAGS "BD:I:PSV:Wd:ef:ij:km:nqrst"
  #endif
  rearg:	while((c = getopt(argc, argv, OPTFLAGS)) != -1) {
  		switch(c) {
***************
*** 218,223 ****
--- 219,227 ----
  			keepgoing = FALSE;
  			Var_Append(MAKEFLAGS, "-S", VAR_GLOBAL);
  			break;
+ 		case 'W':
+ 			parseWarnFatal = TRUE;
+ 			break;
  		case 'd': {
  			char *modules = optarg;
  
***************
*** 1302,1308 ****
  	va_start(ap);
  	fmt = va_arg(ap, char *);
  #endif
! 	fprintf(stderr, "%s: ", progname);
  	(void)vfprintf(stderr, fmt, ap);
  	va_end(ap);
  	(void)fprintf(stderr, "\n");
--- 1306,1316 ----
  	va_start(ap);
  	fmt = va_arg(ap, char *);
  #endif
! 	/*
! 	 * XXX should be progname, but then so should every other
! 	 * XXX isntance of 'make: '!
! 	 */
! 	fprintf(stderr, "make: ");
  	(void)vfprintf(stderr, fmt, ap);
  	va_end(ap);
  	(void)fprintf(stderr, "\n");
Index: make.1
===================================================================
RCS file: /cvsroot/basesrc/usr.bin/make/make.1,v
retrieving revision 1.43
diff -c -r1.43 make.1
*** make.1	2000/09/05 17:57:52	1.43
--- make.1	2000/12/22 23:32:59
***************
*** 41,47 ****
  .Nd maintain program dependencies
  .Sh SYNOPSIS
  .Nm ""
! .Op Fl Beiknqrst
  .Bk -words
  .Op Fl D Ar variable
  .Ek
--- 41,47 ----
  .Nd maintain program dependencies
  .Sh SYNOPSIS
  .Nm ""
! .Op Fl BeiknqrstW
  .Bk -words
  .Op Fl D Ar variable
  .Ek
***************
*** 197,202 ****
--- 197,206 ----
  Multiple instances of this option may be specified;
  the variables will be printed one per line,
  with a blank line for each null or undefined variable.
+ .It Fl W
+ Treat any
+ .Nm
+ makefile-parsing warnings as errors.
  .It Ar variable=value
  Set the value of the variable
  .Ar variable
Index: make.h
===================================================================
RCS file: /cvsroot/basesrc/usr.bin/make/make.h,v
retrieving revision 1.29
diff -c -r1.29 make.h
*** make.h	2000/06/11 07:39:53	1.29
--- make.h	2000/12/22 23:32:59
***************
*** 338,343 ****
--- 338,346 ----
  extern Boolean	checkEnvFirst;	/* TRUE if environment should be searched for
  				 * variables before the global context */
  
+ extern Boolean	parseWarnFatal;	/* TRUE if makefile parsing warnings are
+ 				 * treated as errors */
+ 
  extern GNode    *DEFAULT;    	/* .DEFAULT rule */
  
  extern GNode    *VAR_GLOBAL;   	/* Variables defined in a global context, e.g
Index: parse.c
===================================================================
RCS file: /cvsroot/basesrc/usr.bin/make/parse.c,v
retrieving revision 1.54
diff -c -r1.54 parse.c
*** parse.c	2000/12/05 17:07:01	1.54
--- parse.c	2000/12/22 23:32:59
***************
*** 337,342 ****
--- 337,344 ----
  	va_dcl
  #endif
  {
+ 	static Boolean fatal_warning_error_printed = FALSE;
+ 
  	(void)fprintf(stderr, "\"%s\", line %d: ", cfname, (int) clineno);
  	if (type == PARSE_WARNING)
  		(void)fprintf(stderr, "warning: ");
***************
*** 344,351 ****
  	va_end(ap);
  	(void)fprintf(stderr, "\n");
  	(void)fflush(stderr);
! 	if (type == PARSE_FATAL)
  		fatals += 1;
  }
  
  /*-
--- 346,357 ----
  	va_end(ap);
  	(void)fprintf(stderr, "\n");
  	(void)fflush(stderr);
! 	if (type == PARSE_FATAL || parseWarnFatal)
  		fatals += 1;
+ 	if (parseWarnFatal && !fatal_warning_error_printed) {
+ 		Error("parsing warnings being treated as errors");
+ 		fatal_warning_error_printed = TRUE;
+ 	}
  }
  
  /*-
***************
*** 1576,1581 ****
--- 1582,1591 ----
  	gn = (GNode *) Lst_Datum (Lst_Last (gn->cohorts));
      if (!(gn->type & OP_HAS_COMMANDS))
  	(void)Lst_AtEnd(gn->commands, cmd);
+     else
+ 	Parse_Error (PARSE_WARNING,
+ 		     "duplicate script for target \"%s\" ignored",
+ 		     gn->name);
      return(0);
  }
  

>Release-Note:
>Audit-Trail:
>Unformatted: