Learning GNU Make Functions with Arithmetic

[article]
Summary:

GNU Make has no built-in arithmetic capability. In this article, I present a collection of GNU Make macros that implement functions for addition, subtraction, multiplication, and division of integers. Functions are also provided for integer comparisons such as “greater than” and “not equal.” These macros are implemented entirely using GNU Make's built-in string manipulation functions.

GNU Make has no built-in arithmetic capability. In this article, I present a collection of GNU Make macros that implement functions for addition, subtraction, multiplication, and division of integers. Functions are also provided for integer comparisons such as “greater than” and “not equal.” These macros are implemented entirely using GNU Make's built-in string manipulation functions.

GNU Make provides good functionality for manipulating strings and through this article you will learn about the following: $(subst), $(filter), $(filter-out), $(words), $(wordlist), $(call), $(foreach), and $(if). You'll learn how GNU Make represents lists, and how to define and call your own functions.

In GNU Make a list is a string separated into list elements with spaces. For example, the following string:

    foo “bar baz” bam

is a GNU Make list with four elements: foo, “bar, baz” and bam. Notice how GNU Make doesn't care about the quotation marks and splits the string simply on spaces. Because of this representation it is very hard to work with GNU Make functions that might be passed a path name containing spaces.

An example of a GNU Make function is $(words). In this example Makefile the variable LIST contains the four element list shown above and $(words) is used to find the number of elements in the list:

    LIST := foo “bar baz” bam    
all: ; @echo $(words $(LIST))

When run with GNU Make this Makefile outputs the number 4. There are two things to note here: firstly a function is called in GNU Make in a similar manner to a variable reference. GNU Make recognizes the function name because it is followed by a space. Secondly the arguments to the function, in this case $(LIST), are, in most cases, expanded before the function is called. So $(words $(LIST)) is the same as $(words foo “bar baz” bam). The $(words) function only has a single argument; other functions have multiple arguments separated by commas.

For example, the $(wordlist) function returns a sublist by specifying the start and end elements in the list. GNU Make lists are indexed with the first element being 1, so this example Makefile will print “bar baz” bam when run:

    LIST := foo “bar baz” bam
all: ; @echo $(wordlist 2,4,$(LIST))

It asks for elements 2 through 4 of $(LIST). Here you can see that $(wordlist) has three arguments: the starting index, the ending index and the list itself. The arguments are separated by commas.

To create an arithmetic library in GNU Make we first need a representation of numbers. A simple way to represent a number is a list with the same number of items as the number being represented. For example, for the arithmetic library a number is a list of letter x's. So the number 5 is represented by

    x x x x x

Given this representation we can use the $(words) function to convert from the internal form (all x's) to a human readable form. For example,

    five := x x x x x
all: ; @echo $(words $(five))

will output 5. So the first user-defined function is decode which translates from the x's representation to a number. User-defined functions look like variable declarations. Here's decode:

    decode = $(words $1)

To use decode in a Makefile we need the GNU Make function $(call) which can be used to call a user-defined function with a set of arguments. The arguments will be stored in temporary variables called $1, $2, $3, etc. In decode, which only takes a single argument, the number to decode, we just use $1:

    five := x x x x x
all: ; @echo $(call decode,$(five))

Pages

About the author

AgileConnection is one of the growing communities of the TechWell network.

Featuring fresh, insightful stories, TechWell.com is the place to go for what is happening in software development and delivery.  Join the conversation now!