Managing Projects with GNU make by Robert Mecklenburg This errata page lists errors outstanding in the most recent printing. If you have technical questions or error reports, you can send them to booktech@oreilly.com. Please specify the printing date of your copy. This page was updated February 02, 2006. Here's a key to the markup: [page-number]: serious technical mistake {page-number}: minor technical mistake : important language/formatting problem (page-number): language change or minor formatting problem ?page-number?: reader question or request for clarification Confirmed errors: (5)The page contains three code examples that are not labeled: * The first code sample should be labeled "count_words.c" * The second code sample should be labeled "lexer.l" * The third code sample should be labeled "Makefile" The examples.tar.gz download contains the files with these names. (5) Twice: on the second line in example 'makefile' and on the last line of the page; first two lines of the make file should read: count_words: count_words.o lexer.o -lfl gcc count_words.o lexer.o -lfl -o count_words and last line on the page should be: gcc count_words.o lexer.o -lfl -o count_words {12} Last paragraph; Before the last paragraph starting "Finally," add this paragraph: When mp_make expands a wildcard (or indeed when mp_make looks for any file), it reads and caches the directory contents. This caching improves mp_make's performance considerably. However, once mp_make has read and cached the directory contents, mp_make will not "see" any changes made to the directory. This can be a mysterious source of errors in a mp_makefile. The issue can sometimes be resolved by using a sub-shell and globbing (e.g., shell wildcards) rather than mp_make's own wildcards, but occasionally, this is not possible and we must resort to bizarre hacks. (16) "Variables" section.; In general, a variable name must be surrounded by $() to be recognized by make. should be: In general, a variable name must be surrounded by $() or ${} to be recognized by make. (16) fifth line from bottom; "There are six core automatic variables:" should be: "There are seven core automatic variables:" [18] 2nd code snippet; #ifdef COUNTER_H_ should be: #ifndef COUNTER_H_ (19) middle of page; "... Unless you direct it otherwise, make will look in the current directory for its targets and prerequisites." should be: "... Unless you direct it otherwise, make will look only in the current directory for its targets and prerequisites." [20] 3; Immediately after "CPPFLAGS = -I include" add "and changing occurrences of gcc to gcc$(CPPFLAGS). Now the build succeeds:" {20} 1/2 way down page, "vpath statements"; vpath %.c src vpath %.h include Should be: vpath %.c src vpath %.l src vpath %.h include Also, the next sentence needs to be updated to say: Now we've told make that it should search for .c and .l files in the src directory... {21} line 6 and 7 from bottom; The third implicit rule used: %: %.c $(LINK.c) ... should be: %: %.o $(LINK.o) ... [21] Second from bottom: "When we ..."; "two line makefile" should be: "seven line makefile" (23) Static Pattern Rules; $(OBJECTS): %.o: %c should be $(OBJECTS): %.o: %.c ^ (25) line 6; "An implicit rule is either a pattern rule or a suffix rule (which we will discuss briefly later)." should be: "An implicit rule is either a pattern rule or a suffix rule. [25] Section "The Implicit Rules Database"; Add the following to the end of the section in the middle of page 27: The implicit rules database contains a lot of rules and even very large projects rarely use most of it. Because it contains such a wide variety, rules you didn't expect to fire may be used by make in unexpected ways. As a preventative measure, some large projects choose to discard the implicit rules entirely in favor of their own hand-crafted rules. You can do this easily with the --no-builtin-rules (or -r) option. (I have never had to use this option even on the largest projects.) If you use this option, you may also want to consider using --no-builtin-variables (or -R). {29} Section "A Simple Help Command"; text should be changed to: # help - The default goal .PHONY: help help: $(MAKE) --print-data-base --question no-such-target | \ $(GREP) -v -e '^no-such-target' -e '^makefile' | \ $(AWK) '/^[^.%][-A-Za-z0-9_]*:/ \ { print substr($$1, 1, length($$1)-1) }' | \ $(SORT) | \ $(PR) --omit-pagination --width=80 --columns=4 The command script consists of a single pipeline. The make rule database is dumped using the --print-data-base command. Using the --question option prevents make from running any actual commands. Specifying a target of no-such-target (instead of the default target) ensures that running the makefile recursively does not trigger infinite recursion. The grep command filters out the bogus target and the makefile itself (which appears as a rule in the database dump). ... (29) "help:" rule; add a "@" to the $(MAKE) command (36) second code excerpt; "ARFLGS" should read: "ARFLAGS" (46) The last sentence before the code in middle of page explains why and how this books uses the term "macro". But immediately after the code "variable" is used as an interchangeable term for "macro". If we understood the author correctly, the first 3 occurences of "variable" (on the 1st, 2nd and 3rd line after the code) should be replaced by "macro". (The fourth occurence of "variable" (on line 3-4) would not be changed.) (50) Section "Target- and Pattern-Specific Variables"; Add to the bottom of page 50: When the gui.o target is finished, CPPFLAGS will revert to its original value. Pattern-specific variables are similar, only they are specified in a pattern rule (see page 21). [51] 1/2 way down; "Each variable assignment on the command line must be a single-shell argument." should be: "Each variable assignment on the command line must be a single shell argument." {52} near bottom; "The export and unexport directives work the same way their counterparts in sh work." should be: "The mp_export and mp_unexport directives work the same way the mp_sh commands mp_export and mp_unset work. (53), last line before last code "using the $? form" -> "using the ?= form" (55) 2/3 of the way down, "ifeq" example; ifeq "$(strip $(OPTIONS)) "-d" should be: ifeq "$(strip $(OPTIONS))" "-d" (57) Insert this paragraph just before "Standard Make Variables" It is worth noting that using an include directive before the first target in a makefile might change the default goal. That is, if the include file contains any targets at all the first of those targets will become the default goal for the makefile. This can be avoided by simply placing the desired default goal before the include (even without prerequisites or targets): # Ensure all is the default goal. all: include support.mk # Now that we have our variables defined, complete the all target. all: $(programs) (70), last line One closing parantheses too much. (72), first function "$wildcard pattern...)" -> "$(wildcard pattern...)" [opening parantheses is missing) (72) line 4; missing left parenthesis (72), last line (of code) One closing parantheses too much. (73) the example $(filter 1 $(words is missing a comma after the "1" (98), mid of page The tags for the format "Replaceable" shouldn't be printed. --directory=directory should be: --directory=directory (2nd directory should be in italics) (113) 1st code example on the page; $(MAKE) --directory=$$f clean; \ Should be changed to: $(MAKE) --directory=$$d clean; \ (127) para 5; "...is up your site." should read: "...is up to your site." {127} Figure 6.2; Please update the figure so the second folder containing "1.0" reads "1.1". (161) 3rd paragraph; Suffice to say that the prerequisite all.javas contains a list of all java files to be compiled. to: Suffice to say that the prerequisite all.javas, which is the value of the variable all_javas, contains a list of all java files to be compiled. {165} middle of page; The macro labeled "define file-exists-eval" should be terminated with "endif" like all the other macros. (178) 3rd paragraph; "The compile-bean function comaccepts..." that last word should be just "accepts" {179} example middle of page; The second definition of bean_files omits the two xml files included in the first definition. [181] last example; All the files listed as ".jar" should be ".class" (237) Makefile snippet after 1st paragraph, 4th line; shopt -s nullglob && should have a trailing backslash: shopt -s nullglob && \ (240), code in mid of page "$ make debug PATH SHELL" should be: "$ make debug USERNAME SHELL" (253), about 16 lines up from bottom The and tags shouldn't be printed.