Bug 11114 - make(1) does not work as documented with .POSIX: target
Summary: make(1) does not work as documented with .POSIX: target
Status: Closed Works As Intended
Alias: None
Product: Base System
Classification: Unclassified
Component: bin (show other bugs)
Version: 3.1-STABLE
Hardware: Any Any
: Normal Affects Only Me
Assignee: freebsd-bugs (Nobody)
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 1999-04-13 19:10 UTC by Jens Schweikhardt
Modified: 2014-06-04 21:04 UTC (History)
2 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Jens Schweikhardt 1999-04-13 19:10:00 UTC
Condider the following Makefile (where prog.c is hello-world):

.POSIX:
prog: prog.o
        echo $(%POSIX)
        $(CC) -o prog prog.o
clean:
        rm -f prog prog.o

When I run 'make' this is what is done:
$ make
cc -O -pipe -c prog.c
echo 1003.2
1003.2
cc -o prog prog.o

However, /usr/share/mk/sys.mk says:

#   from: @(#)sys.mk    8.2 (Berkeley) 3/21/94
#   $Id: sys.mk,v 1.43 1998/09/15 05:24:01 obrien Exp $

unix        ?=  We run FreeBSD, not UNIX.

# If the special target .POSIX appears (without prerequisites or
# commands) before the first noncomment line in the makefile, make shall
# process the makefile as specified by the Posix 1003.2 specification.
# make(1) sets the special macro %POSIX in this case (to the actual
# value "1003.2", for what it's worth).
#
# The rules below use this macro to distinguish between Posix-compliant
# and default behaviour.
...
.if defined(%POSIX)
CC      ?=  c89
.else
CC      ?=  cc
.endif
CFLAGS      ?=  -O -pipe
...

Thus, I expect CC to be c89 (I can't see where CC is set from actually).
What's more, as soon as c89 is used, CFLAGS must not contain non-POSIX
compiler options like -pipe, because otherwise c89 rightfully barfs:


$ make CC=c89            
c89 -O -pipe -c prog.c
Illegal option -p
usage: c89 [-c] [-D name[=value]] [...] [-E] [-g] [-I directory ...]
       [-L directory ...] [-o outfile] [-O] [-s] [-U name ...] operand ...
*** Error code 64

Stop.

I tried 'make -d A' for debugging, but CC=cc seems to be set in some
global place:
$ make -d A
Global:.MAKEFLAGS =  -d
Global:.MAKEFLAGS =  -d A
Global:.TARGETS = 
Caching /usr/share/mk...done
expanding "sys.mk".../usr/share/mk/sys.mk 
Global:MAKEFILE = /usr/share/mk/sys.mk
Global:unix = We run FreeBSD, not UNIX.
Global:X11BASE = /usr/X11R6
Global:AR = ar
Global:ARFLAGS = rl
Global:RANLIB = ranlib
Global:AS = as
Global:AFLAGS = 
Global:CC = cc            <----- why is this not c89?
...etc

It seems the .if defined(%POSIX) doesn't work properly. Or I have
overlooked something. Or something funny is going on.

Regards,

	Jens
-- 
Jens Schweikhardt  http://www.shuttle.de/schweikh/
SIGSIG -- signature too long (core dumped)
Comment 1 dcs 1999-04-13 19:46:26 UTC
Jens Schweikhardt wrote:
> 
> >Number:         11114
> >Category:       bin
> >Synopsis:       make(1) does not work as documented with .POSIX: target

I didn't see any mention of the .POSIX target in make(1). What do
you mean by "documented"?

--
Daniel C. Sobral			(8-DCS)
dcs@newsguy.com
dcs@freebsd.org

	"nothing better than the ability to perform cunning linguistics"
Comment 2 Will Andrews freebsd_committer freebsd_triage 2000-09-29 21:49:31 UTC
Responsible Changed
From-To: freebsd-bugs->will

Over to MAINTAINER.
Comment 3 Jens.Schweikhardt 2001-02-12 11:51:16 UTC
Regarding Daniel's question about what I mean with documented:

From make(1) I conclude that the make utility aims at POSIX conformance:

  COMPATIBILITY
     Older versions of make used MAKE instead of MAKEFLAGS. This was removed
     for POSIX compatibility.

I have considered the quoted parts from /usr/share/mk/sys.mk 
as further documentation on how make behaves when .POSIX: is used.
As I have demonstrated, the text in /usr/share/mk/sys.mk disagrees
with how make actually behaves. Specifically,

# If the special target .POSIX appears (without prerequisites or
# commands) before the first noncomment line in the makefile, make shall
# process the makefile as specified by the Posix 1003.2 specification.

1003.2 requires c89 (not cc) be used for compilation.
sys.mk even tries to do just that with

    .if defined(%POSIX)
    CC      ?=  c89
    .else
    CC      ?=  cc
    .endif

but for some reason, cc is used no matter whether .POSIX: is specified
or not.

Regards,

	Jens
-- 
Jens Schweikhardt  http://www.schweikhardt.net/
SIGSIG -- signature too long (core dumped)
Comment 4 Will Andrews freebsd_committer freebsd_triage 2001-08-30 00:26:18 UTC
Responsible Changed
From-To: will->freebsd-bugs

I don't have time for make(1) anymore...
Comment 5 iedowse freebsd_committer freebsd_triage 2002-01-20 17:47:12 UTC
State Changed
From-To: open->feedback


Does this problem still exist?
Comment 6 Jens Schweikhardt 2002-01-23 19:03:56 UTC
Yes, this problem still persists. Please note that my email address has
changed from schweikh@noc.dfn.de to @schweikhardt.net.

hal9000:/home/schweikh/tmp # make
cc -O -pipe  -c prog.c
echo 1003.2
1003.2
cc -o prog prog.o

uname -a
FreeBSD hal9000.schweikhardt.net 5.0-CURRENT FreeBSD 5.0-CURRENT #2: Tue Dec  4 22:18:01 CET 2001     toor@hal9000.schweikhardt.net:/usr/obj/src/current/sys/HAL9000  i386

Another point to take into consideration: while for POSIX 1990 CC must be c89,
for the now ratified POSIX 2001 CC must be c99.

Regards,

	Jens
-- 
Jens Schweikhardt http://www.schweikhardt.net/
SIGSIG -- signature too long (core dumped)
Comment 7 Jens Schweikhardt freebsd_committer freebsd_triage 2002-01-24 20:19:20 UTC
State Changed
From-To: feedback->open

Feedback from author: yes, problem still persists identically. 
(BTW: modified author's email in a few places because it changed. 
I hope this won't confuse gnats.)
Comment 8 Crist J. Clark freebsd_committer freebsd_triage 2002-02-20 16:23:16 UTC
The issue here is that the .POSIX target will not have its effect
until the makefile containing it is read. /usr/share/mk/sys.mk is the
first file read. make(1) doesn't know about anything that you have set
in your makefile yet.

I have no idea if that is a bug or feature. What do the standards say
(if anything)?
-- 
Crist J. Clark                     |     cjclark@alum.mit.edu
                                   |     cjclark@jhu.edu
http://people.freebsd.org/~cjc/    |     cjc@freebsd.org
Comment 9 Jens Schweikhardt 2002-02-22 19:28:50 UTC
Crist,

On Wed, Feb 20, 2002 at 08:23:16AM -0800, Crist J. Clark wrote:
# The issue here is that the .POSIX target will not have its effect
# until the makefile containing it is read. /usr/share/mk/sys.mk is the
# first file read. make(1) doesn't know about anything that you have set
# in your makefile yet.
# 
# I have no idea if that is a bug or feature. What do the standards say
# (if anything)?

The POSIX 2001 Standard defines the behavior of make and mandates that
the macros have the following values, when .POSIX: is specified as the
first noncomment line and without prerequisites and commands:

MAKE=make
AR=ar
ARFLAGS=-rv
YACC=yacc
YFLAGS=
LEX=lex
LFLAGS=
LDFLAGS=
CC=c99
CFLAGS=-O
FC=fort77
FFLAGS=-O 1
GET=get
GFLAGS=
SCCSFLAGS=
SCCSGETFLAGS=-a


Regards,

	Jens
-- 
Jens Schweikhardt http://www.schweikhardt.net/
SIGSIG -- signature too long (core dumped)
Comment 10 crist.clark 2002-02-23 08:04:44 UTC
On Fri, Feb 22, 2002 at 08:28:50PM +0100, Jens Schweikhardt wrote:
> Crist,
> 
> On Wed, Feb 20, 2002 at 08:23:16AM -0800, Crist J. Clark wrote:
> # The issue here is that the .POSIX target will not have its effect
> # until the makefile containing it is read. /usr/share/mk/sys.mk is the
> # first file read. make(1) doesn't know about anything that you have set
> # in your makefile yet.
> # 
> # I have no idea if that is a bug or feature. What do the standards say
> # (if anything)?
> 
> The POSIX 2001 Standard defines the behavior of make and mandates that
> the macros have the following values, when .POSIX: is specified as the
> first noncomment line and without prerequisites and commands:

Right, but what is the exact wording? All of this does work when the
".POSIX" target is set in sys.mk. In exactly which makefile is the
".POSIX" target supposed to work? If it is in the local one, this is a
real problem. Goes against the whole way makefiles are processed.
-- 
Crist J. Clark                     |     cjclark@alum.mit.edu
                                   |     cjclark@jhu.edu
http://people.freebsd.org/~cjc/    |     cjc@freebsd.org
Comment 11 Jens Schweikhardt 2002-02-23 14:29:56 UTC
On Sat, Feb 23, 2002 at 12:04:44AM -0800, Crist J. Clark wrote:
# On Fri, Feb 22, 2002 at 08:28:50PM +0100, Jens Schweikhardt wrote:
# > Crist,
# > 
# > On Wed, Feb 20, 2002 at 08:23:16AM -0800, Crist J. Clark wrote:
# > # The issue here is that the .POSIX target will not have its effect
# > # until the makefile containing it is read. /usr/share/mk/sys.mk is the
# > # first file read. make(1) doesn't know about anything that you have set
# > # in your makefile yet.
# > # 
# > # I have no idea if that is a bug or feature. What do the standards say
# > # (if anything)?
# > 
# > The POSIX 2001 Standard defines the behavior of make and mandates that
# > the macros have the following values, when .POSIX: is specified as the
# > first noncomment line and without prerequisites and commands:
# 
# Right, but what is the exact wording?

".POSIX   The application shall ensure that this special target is specified
          without prerequisites or commands. If it appears as the first
          non-comment line in the makefile, make shall process the makefile
          as specified by this section; otherwise, the behavior of make is
          unspecified."

Later on it mentions the list of variables and their values.

# All of this does work when the
# ".POSIX" target is set in sys.mk. In exactly which makefile is the
# ".POSIX" target supposed to work?

The application programmer's. See the example in the PR.

# If it is in the local one, this is a
# real problem. Goes against the whole way makefiles are processed.

I'm not sure what you mean with "local makefile".

Regards,

	Jens
-- 
Jens Schweikhardt http://www.schweikhardt.net/
SIGSIG -- signature too long (core dumped)
Comment 12 Tim J. Robbins 2002-04-18 06:50:09 UTC
Please try this patch & let me know whether it corrects the problems
with the special .POSIX target. It is against HEAD, to try it on a 4.x
release you will need to edit str.c and remove __DECONST macro usage.
I realise it's not a particularly clean solution, and I'd be interested
to hear how it could be done better.


Index: main.c
===================================================================
RCS file: /home/ncvs/src/usr.bin/make/main.c,v
retrieving revision 1.56
diff -u -r1.56 main.c
--- main.c	2002/04/13 12:20:51	1.56
+++ main.c	2002/04/18 06:25:35
@@ -113,7 +113,7 @@
 GNode			*DEFAULT;	/* .DEFAULT node */
 Boolean			allPrecious;	/* .PRECIOUS given on line by itself */
 
-static Boolean		noBuiltins;	/* -r flag */
+Boolean			noBuiltins;	/* -r flag */
 static Lst		makefiles;	/* ordered list of makefiles to read */
 static Boolean		printVars;	/* print value of one or more vars */
 static Boolean		expandVars;	/* fully expand printed variables */
@@ -138,7 +138,6 @@
 
 static void		MainParseArgs(int, char **);
 char *			chdir_verify_path(char *, char *);
-static int		ReadMakefile(void *, void *);
 static void		usage(void);
 
 static char *curdir;			/* startup directory */
@@ -728,22 +727,9 @@
 	}
 
 	/*
-	 * Read in the built-in rules first, followed by the specified
-	 * makefile, if it was (makefile != (char *) NULL), or the default
-	 * Makefile and makefile, in that order, if it wasn't.
+	 * Read the specified makefile, if it was (makefile != (char *) NULL),
+	 * or the default Makefile and makefile, in that order, if it wasn't.
 	 */
-	if (!noBuiltins) {
-		LstNode ln;
-
-		sysMkPath = Lst_Init (FALSE);
-		Dir_Expand (_PATH_DEFSYSMK, sysIncPath, sysMkPath);
-		if (Lst_IsEmpty(sysMkPath))
-			Fatal("make: no system rules (%s).", _PATH_DEFSYSMK);
-		ln = Lst_Find(sysMkPath, (void *)NULL, ReadMakefile);
-		if (ln != NULL)
-			Fatal("make: cannot open %s.", (char *)Lst_Datum(ln));
-	}
-
 	if (!Lst_IsEmpty(makefiles)) {
 		LstNode ln;
 
@@ -899,7 +885,7 @@
  * Side Effects:
  *	lots
  */
-static Boolean
+Boolean
 ReadMakefile(p, q)
 	void *p;
 	void *q;
Index: make.h
===================================================================
RCS file: /home/ncvs/src/usr.bin/make/make.h,v
retrieving revision 1.17
diff -u -r1.17 make.h
--- make.h	2002/04/13 10:57:56	1.17
+++ make.h	2002/04/18 06:25:36
@@ -293,6 +293,8 @@
 				 * anything, just see if the targets are out-
 				 * of-date */
 
+extern Boolean  noBuiltins;	/* TRUE if sys.mk should not be sourced */
+
 extern Boolean	checkEnvFirst;	/* TRUE if environment should be searched for
 				 * all variables before the global context */
 extern Lst	envFirstVars;	/* List of specific variables for which the
@@ -353,5 +355,6 @@
 void Make_Update(GNode *);
 void Make_DoAllVar(GNode *);
 Boolean Make_Run(Lst);
+int ReadMakefile(void *, void *);
 
 #endif /* _MAKE_H_ */
Index: parse.c
===================================================================
RCS file: /home/ncvs/src/usr.bin/make/parse.c,v
retrieving revision 1.32
diff -u -r1.32 parse.c
--- parse.c	2002/04/13 10:17:17	1.32
+++ parse.c	2002/04/18 06:25:42
@@ -252,6 +252,7 @@
 static char *ParseReadLine(void);
 static char *ParseSkipLine(int);
 static void ParseFinishLine(void);
+static void ParseSysMk(void);
 
 /*-
  *----------------------------------------------------------------------
@@ -2354,6 +2355,50 @@
     }
 }
 
+/*-
+ *-----------------------------------------------------------------------
+ * ParseSysMk --
+ *	Read and parse the builtin rules file (sys.mk)
+ *
+ * Results:
+ *	Nothing.
+ *
+ * Side Effects:
+ *	Same as Parse_File(): dependencies added, variables set, etc.
+ *
+ *-----------------------------------------------------------------------
+ */
+void
+ParseSysMk(void)
+{
+    LstNode	  ln;
+    Lst		  sysMkPath;
+    Boolean	  old_inLine;
+    int		  old_lineno;
+    char	  *old_fname;
+    FILE	  *old_curFILE;
+
+    /* Save parser globals before Parse_File() clobbers them */
+    old_inLine = inLine;
+    old_lineno = lineno;
+    old_fname = fname;
+    old_curFILE = curFILE;
+
+    /* Parse rules from sys.mk */
+    sysMkPath = Lst_Init (FALSE);
+    Dir_Expand (_PATH_DEFSYSMK, sysIncPath, sysMkPath);
+    if (Lst_IsEmpty(sysMkPath))
+	Fatal("make: no system rules (%s).", _PATH_DEFSYSMK);
+    ln = Lst_Find(sysMkPath, (void *)NULL, ReadMakefile);
+    if (ln != NULL)
+	Fatal("make: cannot open %s.", (char *)Lst_Datum(ln));
+
+    /* Restore globals */
+    inLine = old_inLine;
+    lineno = old_lineno;
+    curFILE = old_curFILE;
+    fname = old_fname;
+}
 
 /*-
  *---------------------------------------------------------------------
@@ -2375,6 +2420,7 @@
     char          *name;	/* the name of the file being read */
     FILE *	  stream;   	/* Stream open to makefile to parse */
 {
+    static int	  donesysmk;
     char	  *cp,		/* pointer into the line */
                   *line;	/* the line we're working on */
 
@@ -2386,6 +2432,20 @@
 
     do {
 	while ((line = ParseReadLine ()) != NULL) {
+	    /*
+	     * Read sys.mk right before we parse the first line that isn't
+	     * either a comment, blank, or .POSIX. The .POSIX pseudo-target
+	     * sets a variable that affects what sys.mk defines.
+	     */
+	    if (!donesysmk) {
+		for (cp = line; isspace(*cp); cp++)
+		    ;
+		if (*cp != '#' && *cp != '\0' && !noBuiltins &&
+		    strncmp(line, ".POSIX", 6) != 0) {
+		    donesysmk = 1;
+		    ParseSysMk();
+		}
+	    }
 	    if (*line == '.') {
 		/*
 		 * Lines that begin with the special character are either
Comment 13 Tim Robbins freebsd_committer freebsd_triage 2002-04-18 07:39:53 UTC
Responsible Changed
From-To: freebsd-bugs->freebsd-standards

Recategorise
Comment 14 Juli Mallett freebsd_committer freebsd_triage 2002-04-18 16:50:09 UTC
On Thu, Apr 18, 2002 at 03:50:09PM +1000, Tim J. Robbins wrote:
> Please try this patch & let me know whether it corrects the problems
> with the special .POSIX target. It is against HEAD, to try it on a 4.x
> release you will need to edit str.c and remove __DECONST macro usage.
> I realise it's not a particularly clean solution, and I'd be interested
> to hear how it could be done better.
> 

I think in the current architecture of make(1), that's probably on the right
track to doing it, assuming the Startup()/Cleanup() style thing cannot be done
or that it won't work.  Does any software include a Makefile that does the
.POSIX thing?  If so, check and see if this works as expected, and check that
it can get through a buildworld (at least as much as normal make(1) - heh),
and that there's no significant regression, and I'd say you can pretty much
go this way, though you might want to add some DEBUG() stuff, as the codepath
is a little obscured, to me anyway.

I guess that's all I can think to say right now.
-- 
jmallett@FreeBSD.org   | C, MIPS, POSIX, UNIX, BSD, IRC Geek.
http://www.FreeBSD.org | The Power to Serve
"We all need mirrors to remind ourselves who we are -- I'm no different."
Comment 15 Tim Robbins freebsd_committer freebsd_triage 2002-04-21 11:43:35 UTC
State Changed
From-To: open->feedback

Solution proposed, waiting for confirmation from originator.
Comment 16 Jens Schweikhardt 2002-04-30 08:13:15 UTC
Tim et al,

On Thu, Apr 18, 2002 at 03:50:09PM +1000, Tim J. Robbins wrote:
# Please try this patch & let me know whether it corrects the problems
# with the special .POSIX target. It is against HEAD, to try it on a 4.x
# release you will need to edit str.c and remove __DECONST macro usage.
# I realise it's not a particularly clean solution, and I'd be interested
# to hear how it could be done better.

I've applied the patch on a -current system and it does the Right Thing
for my test case:

schweikh@hal9000:~/txt/bug $ /usr/obj/src/current/usr.bin/make/make
c89 -O -g  -c prog.c
echo 1003.2
1003.2
c89 -o prog prog.o

One thing to keep in mind: as soon as we have a c99(1) we should change
the CC variable to use that instead of c89 (to comply with POSIX 2001).

Regards,

	Jens
-- 
Jens Schweikhardt http://www.schweikhardt.net/
SIGSIG -- signature too long (core dumped)
Comment 17 Jens Schweikhardt freebsd_committer freebsd_triage 2002-08-13 18:42:49 UTC
Responsible Changed
From-To: freebsd-standards->tjr

Tim, as the originator (me :-) states, the patch is good. 
Please commit and then close this PR. Thanks!
Comment 18 Tim Robbins freebsd_committer freebsd_triage 2004-02-15 07:44:19 UTC
Responsible Changed
From-To: tjr->freebsd-bugs

Unassign due to lack of time and interest. Perhaps someone else 
will pick this up.
Comment 19 Hartmut Brandt freebsd_committer freebsd_triage 2004-11-15 17:12:43 UTC
Responsible Changed
From-To: freebsd-bugs->harti

Ok, I'll work on this one.
Comment 20 Mark Linimon freebsd_committer freebsd_triage 2005-10-23 20:21:58 UTC
State Changed
From-To: feedback->open

Feedback was received quite some time ago.
Comment 21 Mark Linimon freebsd_committer freebsd_triage 2005-10-27 23:03:17 UTC
State Changed
From-To: open->suspended

From personal email from harti: 

I'm actually working on this, but this will take some time, because 
it requires a complete rewrite of the parser. Our current parser just 
cannot by made to be correct with regards to Posix. Obviously this will 
also require some extensive testing especially with ports. 

harti
Comment 22 Eitan Adler freebsd_committer freebsd_triage 2011-02-25 17:27:26 UTC
This is just a pointer to bin/155000 filed on a similar issue

-- 
Eitan Adler
Comment 23 Hartmut Brandt freebsd_committer freebsd_triage 2014-02-26 11:58:10 UTC
Responsible Changed
From-To: harti->freebsd-bugs

Now that we have bmake instead of make release responsibility 
for this bug. I suppose bmake has the same problem. In any case 
it is rather hard to fix.
Comment 24 Baptiste Daroussin freebsd_committer freebsd_triage 2014-06-04 17:11:14 UTC
Add sjg@ in CC he might be interested in that bug and can actually say if bmake is inpacted
Comment 25 Simon J. Gerraty freebsd_committer freebsd_triage 2014-06-04 21:04:11 UTC
Makefile is read *after* sys.mk so .POSIX: target in Makefile
has no influence over sys.mk

Looks to be working as defined.