bglenden@mandrill.cv.nrao.edu (Brian Glendenning) (09/12/90)
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. -- Brian Glendenning - National Radio Astronomy Observatory bglenden@nrao.edu bglenden@nrao.bitnet (804) 296-0286
aglew@crhc.uiuc.edu (Andy Glew) (09/12/90)
If you don't want to be able to prepare all the binaries simultaneously, use SCCS or RCS and version names, with a different name (or set of names) for each different binary version. In general, version names can be divided into two classes: historical names, which once put in place never change, and current names, like 'Latest-Greatest-Version-For-Foo', which change every time an update or bugfix is made. If you want to be able to prepare all the binaries simultaneously, try using link farms - whether symlinks or hardlinks depends on your situation. Create a single, central, RCS tree. Create several "views" of the source tree, containing the current source for a particular version. Share files common to more than one view using links. Let every developer have her own view. In the paper "Boxes, Links, and Parallel Trees: Elements of a Configuration Management System", USENIX Workshop Proceedings, Software Management. USENIX Association, April 3-4, 1989, New Orleans, Louisiana, I describe such a CM system I devised for UNIX system development at Gould. IMHO it was pretty good - developers who got used to it recreated it on their own when we moved from BSD to System V. As I recall at the workshop, half of the audience thought it was a really neat idea, and the other half though it was all old hat. "Doesn't everybody do things that way". It featured, in particular, RCS wrappers to move between several overlaid RCS trees, hardlink cloning (saved space and permitted chroot), and chroot "boxes" to totally isolate one developer from another developers changes which might happen to get installed on the development system by accident... (reducing problems like "I didn't think my compiler bugfix would cause you to spend a week chasing down a bug in the OS"...) There are a number of commercial systems out there, but rolling your own (1) isn't hard, and (2) gets you more features than most commercial systems I've seen. -- Andy Glew, a-glew@uiuc.edu [get ph nameserver from uxc.cso.uiuc.edu:net/qi]
chris@mimsy.umd.edu (Chris Torek) (09/12/90)
In article <BGLENDEN.90Sep11155146@mandrill.cv.nrao.edu> bglenden@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@cs.umd.edu Path: uunet!mimsy!chris
chris@mimsy.umd.edu (Chris Torek) (09/13/90)
In article <26504@mimsy.umd.edu> I wrote: > [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 Only the `mkdir' part of the sed need be done on every machine. The symlinks should only be made on the master source machine: Change the last two lines to > sed 's,/usr/src/\(.*\),mkdir /usr/obj/\1' | sh (Incidentally, this will make more `obj' symlinks, and sometimes more directories, than actually necessary. <bsd.prog.mk> now has a `make obj' that makes the symlinks. The extra directories in /usr/obj are probably not worth worrying about.) -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 405 2750) Domain: chris@cs.umd.edu Path: uunet!mimsy!chris