makefile: find a position of word in a variable

It's a little kludgey, but if there's a symbol you know won't be in any of the values (such as "_") you could do this:

var_1_values = a b c d
var_2_values = A B C D

# This will be a_A b_B c_C d_D
LIST1 = $(join $(addsuffix _,$(var_1_values)),$(var_2_values))

var_1 := a

# The filter gives a_A, the subst turns it into A
var_2 = $(subst $(var_1)_,,$(filter $(var_1)_%, $(LIST1)))

There's a smooth way to do this using recursion as follows. First define a function called pos that finds the position of an element in a list and then use $(word) to extract the corresponding element in another list.

Here's pos:

_pos = $(if $(findstring $1,$2),$(call _pos,$1,\
       $(wordlist 2,$(words $2),$2),x $3),$3)
pos = $(words $(call _pos,$1,$2))

Read this answer to understand how it works: Makefile: find function which returns position

Now it's easy to define a function that finds an element in a list and the finds the corresponding element in another list.

lookup = $(word $(call pos,$1,$2),$3)

And then try if out like this:

ALPHA := a b c d e f g h i j k l m n o p q r s t u v w x y z
NATO := alpha beta charlie delta echo foxtrot gamma hotel india\
        juliet kilo lima mike november oscar papa quebec romeo\
        sierra tango uniform victor whisky yankee zulu
to-nato = $(call lookup,$1,$(ALPHA),$(NATO))

To make a to-nato function that converts from a letter of the alphabet to the NATO alphabet.


One way simulate associative containers in make is to use computed variables. E.g.:

var_2.a := A
var_2.b := B
# ...

# lookup
var_2 = ${var_2.${var_1}}
# or, lookup and assign a default value if lookup fails
var_2_or_default = $(or ${var_2.${var_1}},<default-value>)

Tags:

Makefile