What's new in GNU Make 3.81


In this article, Ask Mr. Make covers what's new in GNU Make 3.81.


GNU Make has supported SysV Make's $$@ syntax in the prerequisite list of a rule. For example, it was possible to say foo: $$@.c and it was equivalent to foo: foo.c (i.e. $$@ had the value that $@ has in the rule's commands). That's changed in GNU Make 3.81. To get that functionality you must defined .SECONDEXPANSION in the Makefile. As a bonus GNU Make supports all the standard automatic variables (that make sense---$$? will always be blank). This happens because GNU Make will expand the prerequisite list of a rule twice: once when it reads the Makefile and once again when searching for what to make. For example, you can do the following:

.SECONDEXPANSION: FOO = foo all: $$(FOO) @echo Making $@ from $? bar: @echo Making $@ FOO = bar

and get the output

Making bar Making all from bar

That's because when the Makefile was read all: $$(FOO) was expanded to all: $(FOO) and then later when figuring out how to build all $(FOO) was expanded to the value FOO had when Makefile parsing ended (in this case bar). Note that this means that if you enabled second expansion and have file names with $'s in them (e.g. you have foo: foo$bar) then the $'s will need to be escaped by writing $$.


GNU Make now supports non-nested else branches by having the conditional on the same line as the else. For example, it's now possible to write:

ifdef FOO $(info FOO defined) else ifdef BAR $(info BAR defined) else $(info BAR not defined) endif

which would previously have been:

ifdef FOO $(info FOO defined) else ifdef BAR $(info BAR defined) else $(info BAR not defined) endif endif

Command-line option: 

-LThe new command-line option -L (and its equivalent --check-symlink-times) causes GNU Make to consider the modification time of the symlink and not the file pointed to by the symlink as GNU Make decides which files need to be remade.


.INCLUDE_DIRS: the list of directories that GNU Make will search when looking for Makefiles to be included. This variable is set by the standard list of directories built into GNU Make and modified by the -I command-line option. Although it's possible to change the value of .INCLUDE_DIRS this has no affect on how GNU Make searches for Makefiles. For example, running make -I /usr/foo on Linux with this Makefile outputs /usr/foo /usr/local/include /usr/local/include /usr/include:

$(info $(.INCLUDE_DIRS)) all: ; @true

.FEATURES: this variable expands to a list of features that GNU Make supports and can be used to determine if a specific feature is available. With GNU Make 3.81 on Linux .FEATURES is target-specific order-only second-expansion else-if archives jobserver check-symlink. This means that GNU Make 3.81 supports target- and pattern-specific variables, has order-only prerequisites, supports second-expansion (.SECONDEXPANSION), supports else if non-nested conditionals, supports ar files, has support for parallel making using the jobserver and supported the new -L command-line option for checking symlinks. To test if a specific feature is available you can use $(filter...). For example, has-order-only := $(filter order-only,$(.FEATURES)) sets has-order-only to true if the GNU Make running has order-only prerequisite support. However, this is not backwards compatible (for example, checking .FEATURES for target-specific under GNU Make 3.80 would indicate that target-specific variables are not available, which they are); a backwards compatible check needs to first determine whether .FEATURES is present by seeing if it is non-blank.

.DEFAULT_GOAL. Normally if no goal is specific on the GNU Make command-line GNU Make will build the first target it sees in the first Makefile it parses. It's a

About the author

AgileConnection is a TechWell community.

Through conferences, training, consulting, and online resources, TechWell helps you develop and deliver great software every day.