Subject: Re: Build identifier variable for obj dirs
To: NetBSD Toolchain Technical Discussion List <tech-toolchain@NetBSD.ORG>
From: Greg A. Woods <woods@weird.com>
List: tech-toolchain
Date: 03/06/2002 04:48:21
[ On Tuesday, March 5, 2002 at 14:17:58 (-0800), Jason R Thorpe wrote: ]
> Subject: Re: Build identifier variable for obj dirs
>
> On Tue, Mar 05, 2002 at 04:48:31PM -0500, Greg A. Woods wrote:
> 
>  > So are you implying that you really do keep your objects in the same
>  > place as your sources?  If so, why?
> 
> It really depends on what I'm doing.  Keeping objdirs "near" sources
> is handy when doing development, so that you don't have to cd to radically
> different places to look at the sources in one window and the binary with
> gdb in another.
> 
> Note, I generally use symlinks ... obj.i386 -> /u1/netbsd/obj/bin/cat.i386,
> etc. ... but I like being able to "cd bin/cat; gdb obj.i386/cat".

I think I might be slowly coming understand one possible reason why you
might want OBJMACHINE, and I think I see for certain now why (at least
for your purposes) BUILDID must work like OBJMACHINE currently does.
However I have an alternate proposal that might make things simpler
without having to support either BUILDID or OBJMACHINE (and indeed
without even having ".${MACHINE}" support built into 'make').

First of all please forget everything I said about USR_OBJMACHINE.  I
have been seriously confused about it from time to time and now after
putting things together more completely in my head have I have (I think
again for at least a second time) realised that it cannot do what I
thought it could without using it together with MAKEOBJDIRPREFIX, which
is not exactly what I had intended.  (This is because I, as I'm sure
several others, have been confused by the relationship between
MAKEOBJDIRPREFIX and MAKEOBJDIR vs. the settings of the variables that
affect what happens during "make obj" -- only in the fixes finally
introduced to share/mk/bsd.README on 07-May-00 has the documentation
matched reality closely enough to be meaningful.)

I think it is nice to have product files in a separate directory from
the source files, and you seem to be saying so too.  I agree it's also a
good idea to reference them with a local relative pathname and not to
have to type a fully qualified pathname, or even a variable name for the
prefix and relative pathame, on the command line when referencing them
from the source directory.  Indeed this does mean using "obj" symlinks
to re-direct product files to a different hierarchy if you don't want
them (or cannot have them) in the source hierarchy.

For me it has made little sense to create a separate symlink in every
source directory for every target architecture, and initially this lead
me to think it would make even less sense to create a separate symlink
for every BUILDID in every source directory.  One "obj" symlink pointing
to a "standardised" BSDOBJDIR (which is itself sometimes just another
symlink) has always given me the optimal results both for building and
for direct debugging and other such references to the product files from
within the source directory.  Different builds on the same machine and
from the same source tree can be worked on by just changing the one
single symlink located at the pathname given by BSDOBJDIR.  In this
sense "cross" builds and "build-ID" builds are logically the same thing
-- just two different reasons to have separate objdirs on the same build
host.

This idea has been re-enforced for me as I've built on more
architectures with the same NFS mounted source tree.  I don't want to
have a clutter of "obj.*" symlinks in every source directory -- one is
enough!  This is especially true when I've wanted the source tree to be
mounted read-only on the build machine.  (Though I will note that there
does yet seem to be a sure and easy way to ensure "make obj" descends
into all possible source directories and makes all the obj symlinks for
every possible target.)

As for direct manual use of the "obj" symlinks, well I suspect one would
not try to run gdb or do anything else similar on a different type of
machine other than that the objects were built for, so direct manual use
of the objdir symlink to refer to product files other than those which
are useful on the current machine seems unnecessary.  (Please correct me
if I'm wrong.)

Multiple "simultaneous" builds (cross and/or build-ID) on the same host
from the same source directory could be done without including $MACHINE
and/or $BUILDID in the "obj" symlink name, provided that 'make' were
modified to allow a prefix to be specified that would be stripped from
the full value of getcwd() before it is appended to MAKEOBJDIRPREFIX.
Perhaps this prefix could be supplied in a new variable called
MAKESRCDIRPREFIX, which would of course correspond to the setting of
BSDSRCDIR used during "make obj".  (This has actually been something
I've thought of for some time now, but here finally is a concrete
example of where it such a feature proves not just useful but
necessary!)

One could then just set MAKEOBJDIRPREFIX with the appropriate $MACHINE
and/or $BUILDID value(s) within it (and of course setting BSDOBJDIR and
USR_OBJMACHINE similarly when running "make obj").  On every target
machine where the objects and sources are available for testing the
intermediate symlink pointed to by a standardised BSDOBJDIR value would
be adjusted to point at the appropriate actual objdirs, making access to
the relevant build products possible through the single common "obj"
symlink.

If one always uses build.sh for cross-builds then it would hide any
complexity and always set MAKEOBJDIRPREFIX (and MAKESRCDIRPREFIX)
appropriately for a given build of any number of architectures (even all
run actualy simultaneously).

For example (using all the current mechanisms for illustration) to build
i386 and sparc on the same (presumably faster) build host (with its
presumably faster local disks):

on the cross-build host:

  first set in /etc/mk.conf (and of course put your source in /usr/src):

	BSDSRCDIR=		/usr/src
	BSDOBJDIR=		/var/NetBSD-obj

  then do these steps:

	mkdir /var/NetBSD-obj
	MACHINE=i386 "make obj"
	mv /var/NetBSD-obj /var/NetBSD-obj.i386

	mkdir /var/NetBSD-obj.sparc
	MACHINE=sparc "make obj"
	mv /var/NetBSD-obj /var/NetBSD-obj.sparc

  this gives us one symlink in every source directory and two sets of
  real object directories, one for each target architecture:

	/usr/src/bin/sh/obj -> /var/NetBSD-obj/bin/sh

	/var/NetBSD-obj.i386/bin/sh
	/var/NetBSD-obj.sparc/bin/sh

   during an i386 build "build.sh" would set for make:

	MAKESRCDIRPREFIX=/usr/src
	MAKEOBJDIRPREFIX=/var/NetBSD-obj.i386

   during a sparc build "build.sh" would set for make:

	MAKESRCDIRPREFIX=/usr/src
	MAKEOBJDIRPREFIX=/var/NetBSD-obj.i386

on the i386 test host:

   mount the products:

	build-host:/var/NetBSD-obj.i386 /build-host/var/NetBSD-obj.i386 nfs -b,rw,nodev,nosuid 0 0

   symlink to it for the "obj" link to work:

	/var/NetBSD-obj -> /build-host/var/NetBSD-obj.i386

on the sparc test host:

   mount the products:

	build-host:/var/NetBSD-obj.sparc /build-host/var/NetBSD-obj.sparc nfs -b,rw,nodev,nosuid 0 0

   symlink to it for the "obj" link to work:

	/var/NetBSD-obj -> /build-host/var/NetBSD-obj.sparc
 

(in reality the multiple "make obj" steps could be eliminated if it were
made to be completely architecture independent, which it probably should
be anyway....)

Note that for one shared source tree and many build hosts it's trivial
to simply adjust the /var/NetBSD-obj symlink as desired to point to
available space for build products (perhaps even for multiple builds)
and to not use MAKEOBJDIRPREFIX or MAKESRCDIRPREFIX -- just the default
MAKEOBJDIR support and one common simple "obj" symlink in the source
tree.  This is the logical way to set up a source tree that's
distributed with a release -- one simple "obj" symlink for all, and thus
even read-only media is directly usable for any builds on any architecture.

(Pmake's use of $MACHINE (or utsname.machine) in forming objdir has
never made any sense to me except perhaps for the very rare case where
one is forced to put objects in the source hierarchy and where the
source tree is shared with NFS or whatever on multiple architectures,
but even then such constraints seem extremely silly and contrived -- why
a single "obj" symlink pointing to a second NFS mount of space unique
for each host, or through an intermediate private per-host symlink that
points to another unique-per-host location on the same mount as the
sources, can't be always used is beyond me.  Even on a totally diskless
machine there must be at least some filesystem space that's private to
each client, such as /var, into which a unique intermediate symlink can
certainly be placed, if not all the objdirs directly.)

-- 
								Greg A. Woods

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