Similar Tools
Although this chapter's focus has been the GNU Make tool, several other tools conform to Make's original premise. Let's now look briefly at the Berkeley Software Distribution's version of Make, Microsoft's version of Make, and the more recent ElectricAccelerator and SparkBuild tools.
Berkeley Make
The Berkeley Software Distribution (BSD) is a version of the UNIX operating system first developed at the University of California in the mid-1970s. Although other UNIX-like systems, such as Linux and Solaris, tend to get more publicity, you've likely heard of the NetBSD, FreeBSD, and OpenBSD systems. In fact, the Apple Mac OS X operating system is based on BSD technology, making it a common version of UNIX.
In addition to an operating system kernel, the BSD systems include a number of user-space utilities, including a variant of the Make tool known as Berkeley Make (also known as bmake or bsdmake) [46]. If you find yourself modifying existing code in a BSD environment, you'll likely use Berkeley Make, even though GNU Make is also available on those platforms.
Much of Berkeley Make's syntax is identical to GNU Make's syntax, especially for basic features. This includes the definition of makefile rules, the list of shell commands, and the definition and usage of variables. In fact, a number of makefile features can be executed by either Berkeley Make or GNU Make.
One of the most noticeable syntax differences is the way variables are manipulated. The GNU Make system uses the concept of functions that manipulate string values. The Berkeley Make system instead uses modifiers. For example:
- $(MY_VAR:E): For each space-separated word in $(MY_VAR), returns the file name's suffix, such as .c or .h. This is similar to GNU Make's $(suffix) function.
- $(MY_VAR:H): For each word in $(MY_VAR), returns the pathname component of the word. This is similar to the $(dir) function in GNU Make.
- $(VAR:M<pattern>): Returns only the list of words that match the specified pattern. This is similar to GNU Make's $(filter) function.
In addition, the Berkeley Make language has syntax to support both conditional execution and looping. The following example demonstrates the use of a for loop (line 4) that traverses a list of subdirectories, and an if statement (line 6) to test whether a particular file exists.
1 SUBDIRS = application database libraries storage 2 ALLTARGS = 3 4 .for SUBDIR in $(SUBDIRS) 5 SUBMK = $(SUBDIR)/Sub.mk 6 .if exists($(SUBMK)) 7 .include "$(SUBMK)" 8 ALLTARGS += make-$(SUBDIR) 9 .endif 10 .endfor 11 12 all: $(ALLTARGS) 13 @echo All targets up to date
The net effect of this makefile is that all Sub.mk files residing within any of the subdirectories are included in the top-level makefile.
To effectively use Berkeley Make, you'll probably find yourself learning a few new syntax tricks. You might also find yourself limited by the number of features available, especially if you're used to GNU Make's wide range of built-in functions.
NMake
The NMake tool [47] is another variant of Make, typically used as part of Microsoft Visual Studio. Whereas developers use the Visual Studio graphical interface for their day-to-day development, NMake can be used more for batch-oriented tasks that are performed from a command line, such as in software packaging.
NMake provides the same basic syntax as GNU Make and Berkeley Make, particularly for the definition of rules and variables. However, any sequences of shell commands will obviously be targeted for the Windows command prompt and use the Visual Studio compilation tools.
Users of the GNU Make tool will find NMake's syntax limiting because it contains only a few advanced features. With the introduction of Microsoft's MSBuild tool (discussed briefly in Chapter 7, "Ant"), the use of NMake has become less common.
ElectricAccelerator and SparkBuild
ElectricAccelerator [48] and SparkBuild [49] are two products created by Electric Cloud, Inc. ElectricAccelerator is a commercially available tool that accelerates the software build process. It achieves this goal by dispatching jobs onto multiple CPUs in a networked cluster and coordinating access to disk files to make sure jobs are executed in the correct order. Given that ElectricAccelerator can parse GNU Make and NMake syntax, customers with legacy build systems see a dramatic increase in performance with little extra work.
SparkBuild is a feature-limited version of ElectricAccelerator that solves some of GNU Make's basic weaknesses, even though it doesn't support cluster-based builds. Earlier, this chapter identified problems with recursive Make in starting a compilation within a subdirectory of the source tree. Given that GNU Make doesn't have a global view of all the dependencies, it's likely to miss some of the important recompilation steps.
When using SparkBuild, you start by explicitly asking the tool to generate a database of dependency information. This knowledge remains even after the build completes.
$ emake --emake-gen-subbuild-db=1 [ ... output hidden ... ]
When the build is complete, the emake.subbuild.db file contains all the dependency information for the whole build tree.
$ ls emake.subbuild.db libmath libprint Makefile calc
If a developer rebuilt the software from within the calc subdirectory, SparkBuild would have enough intelligence to first rebuild the libmath and libprint subdirectories, even though the developer didn't explicitly request it.
$ cd calc $ emake --emake-subbuild-db=../emake.subbuild.db emake -C libmath make[1]: Entering directory '/home/psmith/sparkbuild/libmath' make[1]: 'libmath.a' is up to date. make[1]: Leaving directory '/home/psmith/sparkbuild/libmath' emake -C libprint make[1]: Entering directory '/home/psmith/sparkbuild/lib- print' make[1]: 'libprint.a' is up to date. make[1]: Leaving directory '/home/psmith/sparkbuild/libprint' make: 'calculator' is up to date.
Another nice feature of SparkBuild is that it records useful information for later analysis of the build process. For example, it records which commands were executed, which makefile each command was listed in, and how long it took to execute each of the steps. Feeding this information into the SparkBuild Insight graphical interface produced a comprehensive view of the entire build process (see Figure 6.4).
Figure 6.4 The SparkBuild Insight GUI, showing the analysis of the build process.
The SparkBuild Insight interface also provides the capability to query the build steps and to examine the underlying command and path information (see Figure 6.5).
Figure 6.5 The SparkBuild Insight GUI, showing the detail of an individual job.
Although SparkBuild and SparkBuild Insight are relatively new products, they'll likely become a value resource for makefile developers. They're particularly useful when trying to debug makefile problems such as missing dependencies or slow builds.