Subject: Re: why not "make includes" before "make do-tools" for build.sh?
To: Ben Harris <bjh21@netbsd.org>
From: Greg A. Woods <woods@weird.com>
List: tech-userlevel
Date: 05/18/2003 20:15:26
[ On Saturday, May 17, 2003 at 23:39:40 (+0100), Ben Harris wrote: ]
> Subject: Re: why not "make includes" before "make do-tools" for build.sh?
>
> In article <m19Gw8E-000B40C@proven.weird.com> you write:
> >[ On Thursday, May 8, 2003 at 23:20:36 (+0100), Ben Harris wrote: ]
> >> Subject: Re: why not "make includes" before "make do-tools" for build.sh?
> >>
> >> In article <m19Doxf-000B3kC@proven.weird.com> you write:
> >> > If the tools build doesn't use $DESTDIR/include then my suggestion is
> >> > obviously pointless, however it seems to me that if the build of the
> >> > tools does use $DESTDIR/include then "make includes" must be run before
> >> > the (rest of the) tools are built.
> >> 
> >> It shouldn't (since $DESTDIR/usr/include might not even exist at that
> >> point), but your experience suggests that under some circumstances, it does.
> >> Someone should work out why, and how to fix that.
> >
> >Well I have not yet had a chance to repeat my experiment with <paths.h>
> >(i.e. the one that prompted me to post initially), however I have just
> >found an example of a host tool which definitely should be compiled
> >against at least one of the target system's header files:  nbpwd_mkdb.
> 
> I think this is a subtly different problem.

It may be, though I thought the problem I was seeing with <paths.h> was
also during the tools build, but as I may have mentioned I won't be sure
until I try to repeat it as an experiment.

>  There are three places we can
> find header files:
> 
> (a) /usr/include: the host system's headers
> (b) ${NETBSDSRCDIR}/...: the target system's uninstalled headers
> (c) ${DESTDIR}/usr/include: the target system's installed headers
> 
> Your <tools.h> problem was a host tool using (c), which should never happen. 

<paths.h>, but yes, that's what I thought the problem was then....

> This problem is (I think) that a host tool is using the wrong mix of (a) and
> (b), and hence ending up with an inappropriate definition of UID_MAX. 

Yup, that's this new problem for certain.....

> You're right about the namespace issues.  In fact, almost everywhere that we
> include a NetBSD header file in a host tool, we're risking this kind of
> disaster -- we're just lucky they only bite occasionally.  The fundamental
> problem is that lots of our headers expect to be part of the implementation,
> so they carefully restrict themselves to the implementation's namespace. 
> Obviously this is a bad thing to be doing if you suddenly find yourself
> being part of an application, as some of our headers do when building host
> tools.

Building cross-build tools is indeed "Hard(tm)" to do 100% correctly,
even without trying to be clever at using the headers from the source
tree to provide definitions corresponding to the target system
environment where needed.

> It's all horrid.  I'm going to bed.

The really horrid part is the hack I used to fix this latest problem.  :-)

A more reliable hack, and one that could be used to solve all similar
problems in a generic manner, would be to have "compat_pwd.h" provide
definitions for _TARGET_UID_MAX, _TARGET_GID_MAX, etc. or something like
those, that are carefully kept in sync with the source tree's
definitions, and then to use these special target-specific defines
carefully and deliberately in pw_scan.c when building for the
cross-build host tools.

Index: lib/libc/gen/pw_scan.c
===================================================================
RCS file: /cvs/master/m-NetBSD/main/src/lib/libc/gen/pw_scan.c,v
retrieving revision 1.11
diff -c -r1.11 pw_scan.c
*** lib/libc/gen/pw_scan.c	29 Jan 2002 10:20:30 -0000	1.11
--- lib/libc/gen/pw_scan.c	18 May 2003 01:28:23 -0000
***************
*** 34,42 ****
   */
  
  #if HAVE_CONFIG_H
! #include "config.h"
! #include "compat_pwd.h"
! #else
  #include <sys/cdefs.h>
  #if defined(LIBC_SCCS) && !defined(lint)
  __RCSID("$NetBSD: pw_scan.c,v 1.11 2002/01/29 10:20:30 tv Exp $");
--- 34,58 ----
   */
  
  #if HAVE_CONFIG_H
! 
! /*
!  * XXX including the source tree's sys/syslimits.h is a very bad hack that will
!  * fail on non-*BSD systems where config.h will then include <limits.h> and/or
!  * <sys/syslimits.h> from the host system and those includes won't be protected
!  * from multiple inclusion, causing clashes between host definitions and those
!  * from the source tree's sys/syslimits.h.  It works on *BSD because the host's
!  * <sys/syslimits.h> uses the very same multiple inclusion protection trick
!  * that the source tree's variant does and so this allows our source tree's
!  * definitions to take precedence.  For SunOS-5 it may suffice to pre-define
!  * _LIMITS_H though... (but I haven't tested for lurking clashing/misssing defs)
!  */
! # include "../../sys/sys/syslimits.h"
! # define _LIMITS_H
! # include "config.h"
! # include "compat_pwd.h"
! 
! #else  /* !HAVE_CONFIG_H */
! 
  #include <sys/cdefs.h>
  #if defined(LIBC_SCCS) && !defined(lint)
  __RCSID("$NetBSD: pw_scan.c,v 1.11 2002/01/29 10:20:30 tv Exp $");


The rest of these changes are what I use to allow full use of the 32-bit
integer range for user and group IDs (along with the <sys/syslimits.h>
changes as well of course):

***************
*** 71,81 ****
  	struct passwd *pw;
  	int *flags;
  {
! 	unsigned long id;
  	int root, inflags;
  	char *ep;
  	const char *p, *sh;
  
  	_DIAGASSERT(bp != NULL);
  	_DIAGASSERT(pw != NULL);
  
--- 87,103 ----
  	struct passwd *pw;
  	int *flags;
  {
! 	u_quad_t id;
  	int root, inflags;
  	char *ep;
  	const char *p, *sh;
  
+ #if 0
+ 	assert(sizeof(u_quad_t) == sizeof(unsigned long long int));
+ 	assert(UID_MAX < ULLONG_MAX);
+ 	assert(GID_MAX < ULLONG_MAX);
+ #endif
+ 
  	_DIAGASSERT(bp != NULL);
  	_DIAGASSERT(pw != NULL);
  
***************
*** 94,100 ****
  
  	if (!(p = strsep(&bp, ":")))			/* uid */
  		goto fmt;
! 	id = strtoul(p, &ep, 10);
  	if (root && id) {
  		if (!(inflags & _PASSWORD_NOWARN))
  			warnx("root uid should be 0");
--- 116,122 ----
  
  	if (!(p = strsep(&bp, ":")))			/* uid */
  		goto fmt;
! 	id = strtoull(p, &ep, 10);
  	if (root && id) {
  		if (!(inflags & _PASSWORD_NOWARN))
  			warnx("root uid should be 0");
***************
*** 111,117 ****
  
  	if (!(p = strsep(&bp, ":")))			/* gid */
  		goto fmt;
! 	id = strtoul(p, &ep, 10);
  	if (id > GID_MAX || *ep != '\0') {
  		if (!(inflags & _PASSWORD_NOWARN))
  			warnx("invalid gid '%s'", p);
--- 133,139 ----
  
  	if (!(p = strsep(&bp, ":")))			/* gid */
  		goto fmt;
! 	id = strtoull(p, &ep, 10);
  	if (id > GID_MAX || *ep != '\0') {
  		if (!(inflags & _PASSWORD_NOWARN))
  			warnx("invalid gid '%s'", p);


-- 
								Greg A. Woods

+1 416 218-0098;            <g.a.woods@ieee.org>;           <woods@robohack.ca>
Planix, Inc. <woods@planix.com>; VE3TCP; Secrets of the Weird <woods@weird.com>