Apart from the fact that bmake is an BSD equivalent of GNU make, I could not clearly understand it's advantages over GNU make. Can anyone help me? I was able to find only one resource that was bit helpful. More help or pointers are appreciated.
BSD make and GNU make are both free replacements for the original AT&T make. The major difference is having different syntax for the advanced features. Here is how to put the output of a shell command in a variable in BSD make:
# BSD make
TODAY != date +%Y-%m-%d
And in GNU make:
# GNU make
TODAY = $(shell date +%Y-%m-%d)
As soon as someone writes $(shell ...)
in a Makefile, it requries GNU make. Because of the different syntax, some packages require GNU make for the build, and some require BSD make.
BSD make began its life as PMake, short for parallel make. Its author, Adam de Boor, described PMake in PMake -- A Tutorial. Its merit was the new ability to run jobs in parallel, as in make -j 3
. This parallel mode broke compatibility by running all commands for each target in a single shell, not in one shell per line. GNU make has a parallel mode, also -j
, that keeps one shell per line. NetBSD make(1) now has make -B -j 3
to do parallel mode with one shell per line. OpenBSD make(1) now always does parallel mode with one shell per line.
4.3BSD-Reno included PMake as make
and the bsd.*.mk include files. These include files are the best feature of BSD make. src/bin/sed/Makefile in 4.3BSD-Tahoe (the release before 4.3BSD-Reno) defines several targets like clean, depend, install, and so on. src/usr.bin/sed/Makefile in 4.3BSD-Reno has only four non-empty lines:
# @(#)Makefile 4.6 (Berkeley) 5/11/90
PROG= sed
SRCS= sed0.c sed1.c
.include <bsd.prog.mk>
Here bsd.prog.mk automatically sets OBJS
to sed0.o sed1.o
, defines a sed target to link sed from those objects, defines other targets like clean, depend, install, and causes make install
to install both sed and its manual page sed.1. There is also bsd.lib.mk for building libraries.
When using bsd.*.mk, each Makefile can build only one program or library. To build another one, there must be a second Makefile in another directory. So src/usr.sbin/smtpd/ in OpenBSD has six subdirectories, where each subdirectory only contains a Makefile, because smtpd builds six programs.
It is also rare to use bsd.*.mk to build anything except BSD itself. Many portable packages from BSD developers, like OpenSSH (from OpenBSD) or mksh (from MirBSD), do not require BSD make and do not use bsd.*.mk files.
The file bsd.port.mk is at the center of FreeBSD Ports, the system that builds software packages for FreeBSD. (NetBSD pkgsrc calls this file bsd.pkg.mk.) This system has rivals in other scripting languages. Homebrew uses Ruby. MacPorts use Tcl.
In the past, GNU make was more portable than BSD make. Because BSD make was part of BSD, it is rare to find BSD make on other systems. Now there is portable bmake for other systems. This is a portable version of NetBSD make. The most common use for portable bmake is to run pkgsrc on non-NetBSD systems. I run pkgsrc on OS X, with bmake bootstrapped by pkgsrc.
I am writing BSD Owl, a portable build system based on BSD Make. I started to write Makefiles in 2000 with GNU Make and quickly switched to BSD Make. Let me outline the reasons which guided my choice.
This is the main point, really. While the GNU project provided awesome and important piece of software to the free software world, documentation does not cleanly distinguish between user manual and reference manual, a consistent characteristic of GNU documentation. As a result, GNU Make documentation is a huge (well over 200 pages) document interleaving careful description of each aspect of the system with toy-examples. When I used it, I never found these examples useful, because they are nowhere near of actual use cases, and always needed several minutes to locate or relocate information I had to look up. The literature corpus available for GNU Make is really huge, however it very hard to find interesting examples to guide oneself in the writing of a comprehensive portable build system like BSD Owl. Maybe it is because projects rely on automake instead of writing the Makefiles directly. Maybe it is because I did not search hard enough.
The state of things was much better on the FreeBSD side. Indeed,
Of course the manual page of BSD Make is not as detailed as the manual of GNU Make, but it is much more dense and easier to use. The FreeBSD build systems are at the same time (a) a proof of concept that BSD Make can orchestrate the build of large complex projects and (b) a show-case of advanced techniques in the art of Makefile writing.
A very funny thing is that programming features of GNU Make seem much more powerful than what BSD Make provide. Nevertheless, I found them incredibly hard to use, mostly because of expansion order, and because of the lack of useful examples. BSD Make has much less constructs and function, but they are very solid and easy to use: most of the code I need to write are conditionals and for-loops to define lists of targets and BSD Make does this very easily and reliably.
BSD Make has an advanced feature that GNU Make does not have — as far as I know — it is called the meta mode. The most difficult part of writing Makefiles is to correctly specify prerequisite lists in a package. Some software like mkdep(1)
tries to automate the process by analysing sources. BSD Make takes a different approach: we write a Makefile with possibly buggy (incomplete) dependencies, but precise enough to successfully build the package. During the process, BSD Make monitors I/O using filemon(4)
to determine the actual list of prerequisites.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With