Read only Source trees?

Chris Torek chris at mimsy.umd.edu
Wed Sep 12 18:29:41 AEST 1990


In article <BGLENDEN.90Sep11155146 at mandrill.cv.nrao.edu>
bglenden at mandrill.cv.nrao.edu (Brian Glendenning) writes:
>Can anyone tell me what the usual tricks are when dealing with
>readonly source hierarchies (i.e. we have 5 different binary formats
>and we're tired of maintaining several versions of identical source
>trees (the sources are changing somewhat rapidly and the extra copies
>take not insignificant amounts of disk)). I'm not clear what the best,
>or even usual, solution to this (presumably) common problem is.

One solution, operating now at UC Berkeley and almost working here
at UMCP-CSD (there are still some programs that must be cleaned up):

 1. Obtain pmake (Adam de Boor's `parallel make') as modified for
    4.3BSD-reno (these mods may be optional; I have not looked at
    the unmodified version).

 2. Put symlinks in your kernel, or a hack into pmake for `pretend
    symlinks' of some sort (see step 4 below).

 3. Change all your makefiles.  This is the hard part.  In the process,
    you generally want to move each program's source into a separate
    subdirectory, and move the source version of the manual for that
    program to the same directory.  In some cases this requires thought
    and/or use of special pmake features.  In most cases, however, you
    wind up with a situation like one of these:

    a) program /usr/bin/foo is built from one C source file.  The
       Makefile in /usr/src/bin/foo reads, in its entirety:

	PROG=	foo
	.include <bsd.prog.mk>

       (you can of course add comments and blank lines if you like).

    b) program /usr/bin/foo is built from several C source files.  The
       Makefile in /usr/src/bin/foo reads:

	PROG=	foo
	SRCS=	foo.c bar.c baz.c
	.include <bsd.prog.mk>

    c) program /usr/sbin/foo is built from one C source file, but its
       manual goes in section 8:

	PROG=	foo
	MAN8=	foo.0
	.include <bsd.prog.mk>

    d) program foo has no manpage (e.g., the C preprocessor): add the
       line

	NOMAN=	noman

       (or `NOMAN=an_island' if you prefer :-) ).  <bsd.prog.mk> simply
       keys off the existence of this make-variable and avoids building
       and installing a man page.

    e) directory makefiles: /usr/src/bin/Makefile reads something like

	SUBDIR=	cat cp csh ed ls sh stty test
	.include <bsd.subdir.mk>

    f) library makefiles: these look something like

	LIB=	foo
	SRCS=	foofile.c fooio.c foosubr.c
	MAN3=	fooopen.0 fooread.0 foocompute.0
	MLINKS=	fooopen.0 fooclose.0 \
		fooread.0 foowrite.0
	.include <bsd.lib.mk>

    g) complicated makefiles: you will need to use ${.CURDIR} to give
       full path names for source files, because of step 4 below.  Read
       the pmake documentation for details.

    Machine-specific source files (such as the VAX `arff' console-media
    manipulation program) go in subdirectories as usual, and the parent
    directory's makefile gets a bit uglier:

	.if   ${MACHINE} == "sun4"
	SUBDIR+=installboot
	.elif ${MACHINE} == "tahoe"
	SUBDIR+=dlmpcc enpload
	.elif ${MACHINE} == "vax"
	SUBDIR+=arff rxformat
	.endif

    When you have completed this step, you can simply

	cd /usr/src; make depend; make; make install; make clean

    and everything will be recompiled and reinstalled.  (This takes
    a few hours or so....)

 4. This is the magic part.  All of the above is simply preliminary
    work.  Mount /usr/src read-only.  Make /usr/obj a symlink if
    necessary, or simply mount something on /usr/obj.

	[on the machine on which /usr/src is to be kept, where it
	 is mounted read/write:]
	$ cd /usr/src
	$ make cleandir		# remove any leftover stuff

	[on every machine that it to use /usr/src]
	$ mkdir /usr/obj; find /usr/src/* -type d -print |
	> sed 's,/usr/src/\(.*\),mkdir /usr/obj/\1\
	> ln -s /usr/obj/\1 /usr/src/\1/obj,' | sh

    This takes a while.  When it is done, run

	$ cd /usr/src; make depend; make; make install

    on all the machines sharing /usr/src.

Note that 4.3BSD-reno comes with a new manual page scheme, but it is
not necessary to buy into this.  A small modification to <bsd.man.mk>
allows using the old method without changing *any* makefiles.  (By
not sharing /usr/share/mk, or by putting ${MACHINE} tests in these
files, you can even split between new and old on different architectures.)

Although step 3 above is painful, it is worth it: it separates the
*specifications* for the sources for each program (which differ for
each program) from the *semantics* of how to make each program (which
are almost always identical; the few exceptions get bigger makefiles).
If the semantics change---e.g., if dependencies are to be maintained
by some other method than `mkdep'---virtually no changes to /usr/src
are necessary.  Only the `master' /usr/share/mk/*.mk files (and their
sources in /usr/src/share/mk) are affected, and, occasionally, those
exceptional makefiles.

Want to install with default owner `root' instead of `bin'?  Just
change <bsd.own.mk> and <bsd.lib.mk>.  Want to build libraries with
extra debugging information?  Just change <bsd.lib.mk>.  And so on....

This scheme may not be the best, but it works.  It solves two
problems:  shrinking the makefiles (moving common semantics to a
commmon place), and sharing the sources (one source tree suffices for
any number of architectures).  If you do cross-compilation you can even
handle that, if a bit grotesquely, by making /usr/obj itself a symlink
and pointing it to different object trees.  (What is really needed here
is Plan-9 style per-process mounts.)
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 405 2750)
Domain:	chris at cs.umd.edu	Path:	uunet!mimsy!chris



More information about the Comp.unix.questions mailing list