GNU make 3.82 hit the streets last week, the first new release of the workhouse build tool in over four years. Why so long between releases? To me the answer is obvious: the tool Just Works ™, so there’s no need to churn out new releases chasing the latest development fad. But as this release shows, there is still room to innovate, without compromising on the points that make the tool so great. The two improvements I find most interesting are .ONESHELL, and changes to pattern-search behavior:
Normally, gmake executes each line of a rule body or recipe using a separate invocation of the shell. With gmake 3.82, you can add the special target .ONESHELL to the makefile, which will tell gmake to run the entire recipe using a single shell invocation. For example, if your makefile contains the following:
Without .ONESHELL, gmake will invoke the shell twice, as follows:
Naturally, that will not produce the output you actually want (ie, “FOO is -1-“). With .ONESHELL, gmake instead invokes the shell just once:
In addition to making it easier to write multi-line rule bodies, this feature makes it much more palatable to use alternative shells. For example, you could imagine using Perl as the shell:
(Note the use of another 3.82 feature, .SHELLFLAGS, which allows us to control the command-line flags used with the shell; in this case I’ve set those to “-e”, the Perl flag for executing a script from the command-line).
Pattern search changes
Prior to version 3.82, when gmake finds multiple matches during a pattern search, it prefers patterns declared earlier in the makefile over patterns declared later. As of 3.82, gmake instead prefers the pattern that results in the shortest stem. That sounds a bit confusing thanks to the jargon, but I think this will actually cause gmake to better adhere to the principle of least astonishment. Here’s an example:
Compare the output from gmake 3.81 and 3.82:
gmake 3.82 prefers the second pattern because it is a more specific match than the first. Note that this is a significant backwards-incompatibility compared with previous versions of gmake!
Besides those big changes, there are several smaller features, such as:
- This special variable allows you to change the character used to mark the beginning of a command in a recipe from the default TAB character. I can only assume that the developers added this feature to quell the semi-regular complaints about make’s sensitivity to whitespace.
- private variable modifier
- Normally, gmake propagates target-specific variable assignments to the prereqs of the target. With the private modifier, you can restrict the scope of a target-specific variable assignment, so that it is not inherited by the prereqs.
- undefine directive
- The inverse of the familiar define directive, undefine lets you completely remove a variable definition.
- define improvements
- The define directive now supports the same assignment operators that regular variable assignment alows: :=, ?= and +=, for simple, conditional and appending assignments.
If you want to see the full list, you can find it in the NEWS file in the gmake source tree.
“Rumors of my death have been greatly exaggerated…”
Some naysayers claim make is outdated, but it’s clear that make is still alive and kicking (and if a new gmake release isn’t proof enough, take a look at some of the innovations we’ve put into Electric Make). A hearty congratulations to everybody who contributed, and especially to Paul Smith for driving the development and release effort. Keep up the good work!