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 (tm), 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:
all: @export FOO=1 @echo FOO is -$$FOO-
Without .ONESHELL , gmake will invoke the shell twice, as follows:
sh -c 'export FOO=1' sh -c 'echo FOO is -$FOO-'
Naturally, that will not produce the output you actually want (ie, "FOO is -1-"). With .ONESHELL , gmake instead invokes the shell just once:
sh -c 'export FOO=1 echo FOO is -$FOO-'
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:
SHELL=perl .SHELLFLAGS=-e .ONESHELL: all: @my $$foo = "1"; print "FOO is -$$foo-n";
(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:
all: sub/foo.x .x: @echo "Prefer first match (stem is $*)." sub/.x: @echo "Prefer most specific match (stem is $*)."
Compare the output from gmake 3.81 and 3.82:
<span style="font-family: 'Courier New';">Prefer first match (stem is sub/foo).</span>
<span style="font-family: 'Courier New';">Prefer most specific match (stem is foo).</span>
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.
The inverse of the familiar define directive, undefine lets you completely remove a variable definition.
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!
Build Acceleration and Continuous Delivery
Continuous Delivery isn’t continuous if builds and tests take too long to complete. Learn more on how CloudBees Accelerator speeds up builds and tests by up to 20X, improving software time to market, infrastructure utilization and developer productivity.