Merits of bmake
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 point开发者_Go百科ers 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.
Documentation and available literature
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,
- There is a canonical tutorial or user manual by Adam de Boor.
- The manual page serves well as a reference manual and is well under 30 pages.
- The FreeBSD build system and the FreeBSD ports system are a corpus of hand-written makefiles.
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.
Programming features
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.
Advanced features
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.
The BSD make can generate targets, based on conditionals or within loops. This comes quite handy sometimes.
Whenever comparing GNU utilities to BSD utilities, keep in mind that most people making comparisons will treat licensing as a feature or a bug in of itself -- and that something like half the developers making a comparison favor a permissive license and half favor a GPL-like viral license. This is not to say that there aren't real differences (sometimes there are, but often it's a wash).
bmake isn't quite as bloated as GNU make, and both are compatible with most hand-written makefiles (and if you generate makefiles with autotools, autotools is capable of generating makefiles compatible with either or both).
The only clear benefit to bmake so far as I can tell is that using it will please people who are pathologically afraid of GPLs. But, bmake's author claims that it is the result of trying to patch pmake (the normal BSD make) to accept the output of autotools. Given the trouble I've had trying to get it to understand autotools-generated makefiles, I am suspicious of how successful this was. Other people make other claims, some of which aren't meaningful.
In the end, if you stick to the standard elements of makefiles and don't stray too far from POSIX, it shouldn't matter too much which make you use.
I'm not using it, but my understanding is that the BSD make is a make program + a standard library of templates (i.e. more or less the equivalent of GNU make + automake and perhaps autoconf).
精彩评论