bmake

Introduction

In the past when building large software projects, I've had to ensure that GNU make (if not my own patched version of it), was installed and had developed a set of macros to greatly simplify delveloping complex build trees.

My main development machine for the last several years, runs 4.4BSD (NetBSD to be precise), and the BSD source tree is an excellent example of managing a large software project. In following NetBSD's -current delevlopment, I learned to use the new BSD Makefiles and make(1), I did an autoconf version of it that I'll refer to as bmake(1) from here on. Since then all my new projects and many of my old ones use bmake. Since bmake.tar.gz uses GNU's autoconf and is quite portable, I've skipped the effort of making the rest of my distributions support GNU make.

Bmake is derrived from NetBSD's make(1), its goal is to be a portable version of same, so new features are added via imports of NetBSD's make (I'm one of the contributors to NetBSD). Thus bmake is pretty well kept in sync with NetBSD's make.

It may be insteresting to note that much of my tree uses the same simple Makefile, it is:

# a totally generic makefile suits 90% of projects

PROG=	${.CURDIR:T}

SRCS=	${PROG}.c

.include "prog.mk"

macros

The example Makefile above, perhaps suggests why I like bmake(1). The important magic is in the line:
.include "prog.mk";
Makefiles for libraries inlcude lib.mk btw. Anyway, apart from reading a bunch of rules from the system macros (/usr/share/mk/* by default) it reads "../Makefile.inc" thus provinding a hook for much magic. My Makefile.inc files typically look for Makefile.${MACHINE}.inc as well. Though I'm converting to using Makefile.${HOST_TARGET}.inc and having HOST_TARGET set in sys.mk, as being more flexible.

Note that I used to use the bsd.*.mk macros (intended for building /usr/src), but attempts to get simple portability improvments committed into these, usually failed, so the only viable solution was to maintain a parallel set.

obj

Another cool feature of bmake(1) is that if the directory obj exists in the same directory as the Makefile, then bmake will chdir into it before doing anything else. This helps keep the build tree clean, and if the obj directories are symlinks off to a separate file system, eg.
/usr/src/bin/cat/obj -> /usr/obj/bin/cat
then suddenly building for multiple architectures is very easy.

Even better if MAKEOBJDIRPREFIX is set in the environment (see below) then it is trival to export a source tree read-only.

MAKEOBJDIRPREFIX

If MAKEOBJDIRPREFIX is set in the environment and the directory $MAKEOBJDIRPREFIX${.CURDIR} (.CURDIR is set by getcwd()) exists, make(1) will chdir into it rather than look for ./obj as described above. This simple feature allows true read-only source trees. This entire build tree has been built using MAKEOBJDIRPREFIX. Note that MAKEOBJDIRPREFIX is actioned before any Makefiles are read which is why it must be an environment variable.

Note that the latest versions of bmake can use the target .OBJDIR: to avoid having to have MAKEOBJDIRPREFIX in the environment, but I like to tightly control the build environment anyway so setting MAKEOBJDIRPREFIX is not an issue (for me).

While bmake normally overrides getcwd() with getenv("PWD") so that parallel makes work correctly with an automounter, this is dissabled (in bmake 3.x) when MAKEOBJDIRPREFIX is set to prevent $MAKEOBJDIRPREFIX${.CURDIR} having different values depending on how bmake is invoked. Recent versions of bmake, also allow variable substitutions on MAKEOBJDIR so for a neater result you can use something like:

export MAKEOBJDIR="\${.CURDIR:S,$SRCTOP,$OBJTOP,}"

MACHINE and MACHINE_ARCH

The variables MACHINE and MACHINE_ARCH are built into bmake. The script bmake/machine.sh is used to set it it from the output of uname(1). You can override this value via configure's --with-machine=MACHINE. Do configure --help for a list.

Building bmake

As of bmake-3.1.6 the recommended way to build bmake is simply:
$ $srcdir/configure
$ make -f makefile.boot bootstrap
# ./bmake -f Makefile install
Where srcdir is the path to where configure is, or '.'.

Note that in earlier releases bmake/mk contained copies of bsd.*.mk too which should only be installed on non-4.4BSD systems as well as my own macro set. The macros are now in a separate archive which can be unpacked anywhere but the default assumes it was unpacked under bmake's src directory.

The install step above will only install the bsd.*.mk files if bsd.own.mk does not exists in the target directory.

AIX

The differences in VPATH handling in various make utilities is one of the prime motives for compiling GNU make or bmake on a system. Because of the way AIX's make(1) handles VPATH, bootstraping bmake is a bit more painful than usual.

Bootstraping bmake in /usr/local/src/sjg/bmake should not present any difficulties though I've not tried it. In anycase the following does work (the need for the sed(1) command suggests a bug in make(1)).

$ mkdir /tmp/bmake
$ cd /tmp/bmake
$ /usr/local/src/sjg/bmake/configure
$ make -f makefile.boot depend MKDEP_OPTS=-N
$ sed 's,/usr/local/src.*/\([^/]*\.c\),\1,' .depend >> makefile.boot
$ cd lst.lib
$ sed 's,/usr/local/src.*/\([^/]*\.c\),\1,' .depend >> makefile.boot
$ make -f makefile.boot
# make -f makefile.boot install
Note: AIX.sys.mk is still probably full of errors, updates appreciated.


$Id: bmake.html,v 1.14 2002/11/27 06:23:22 sjg Exp $
Copyright © 1997-2001 CRUFTY.NET