In GNU Make, how do I convert a variable to lower case?

Viewed 49202

This is a silly question, but.... with GNU Make:

VAR = MixedCaseText
LOWER_VAR = $(VAR,lc)

default:
        @echo $(VAR)
        @echo $(LOWER_VAR)

In the above example, what's the correct syntax for converting VAR's contents to lower case? The syntax shown (and everything else I've run across) result in LOWER_VAR being an empty string.

7 Answers

you can always spawn off tr

LOWER_VAR = `echo $(VAR) | tr A-Z a-z`

or

LOWER_VAR  = $(shell echo $(VAR) | tr A-Z a-z)

The 'lc' functions you trying to call is from GNU Make Standard Library

Assuming that is installed , the proper syntax would be

LOWER_VAR  = $(call lc,$(VAR))

You can do this directly in gmake, without using the GNU Make Standard Library:

lc = $(subst A,a,$(subst B,b,$(subst C,c,$(subst D,d,$(subst E,e,$(subst F,f,$(subst G,g,$(subst H,h,$(subst I,i,$(subst J,j,$(subst K,k,$(subst L,l,$(subst M,m,$(subst N,n,$(subst O,o,$(subst P,p,$(subst Q,q,$(subst R,r,$(subst S,s,$(subst T,t,$(subst U,u,$(subst V,v,$(subst W,w,$(subst X,x,$(subst Y,y,$(subst Z,z,$1))))))))))))))))))))))))))

VAR = MixedCaseText
LOWER_VAR = $(call lc,$(VAR))

all:
        @echo $(VAR)
        @echo $(LOWER_VAR)

It looks a little clunky, but it gets the job done.

If you do go with the $(shell) variety, please do use := instead of just =, as in LOWER_VAR := $(shell echo $VAR | tr A-Z a-z). That way, you only invoke the shell one time, when the variable is declared, instead of every time the variable is referenced!

Hope that helps.

If Python is installed this runs even on Windows:

$(shell python -c "print('$(VAR)'.lower())")

GNU make doesn't include string functions for case conversion. Thus, there is no lc function defined, by default.

But GNU Make usually comes with GNU Guile support enabled (e.g. this is the case on Fedora 33).

Thus, you can just call a Guile function for converting the case:

VAR = MixedCaseText
LOWER_VAR = $(guile (string-downcase "$(VAR)"))

default:
        @echo $(VAR)
        @echo $(LOWER_VAR)

Or if you want to encapsulate the Guile call:

VAR = MixedCaseText
LOWER_VAR = $(call to_lower,$(VAR))


define to_lower
$(guile (string-downcase "$(1)"))
endef


default:
        @echo $(VAR)
        @echo $(LOWER_VAR)

I wrote this while looking for a solution. It is a bit verbose but believe it explains the steps and keeps really long lines out on the Makefile.

You can easily be modify it to perform any substitution you may want.

Hope it helps someone.

# set the separator for the *_TABLE variables, needed as otherwise `$(addprefix ...)` fails
luc_JOIN ::= ,

# define the upper and lower cased characters
lc_CHARS ::= 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
uc_CHARS ::= 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

# join the above to create the *_TABLE variables (i.e `a,A b,B ...`, `A,a B,b ...`)
lc_TABLE ::= $(join $(uc_CHARS),$(addprefix $(luc_JOIN),$(lc_CHARS)))
uc_TABLE ::= $(join $(lc_CHARS),$(addprefix $(luc_JOIN),$(uc_CHARS)))

# an internal macro to recursively create `$(subst ...)` from provided *_TABLE and string, (e.g. `$(subst a,A,$(subst b,B,...))`)
luc_internal = $(if $1,$$(subst $(firstword $1),$(call luc_internal,$(wordlist 2,$(words $1),$1),$2)),$2)

# the actual macros to $(call ...), which calls the luc_internal with the correct *_TABLE
lc = $(eval lc_RESULT ::= $(call luc_internal,$(lc_TABLE),$1))$(lc_RESULT)
uc = $(eval uc_RESULT ::= $(call luc_internal,$(uc_TABLE),$1))$(uc_RESULT)

# a mixed case value
VAR = SOME text

default:
    @echo $(call lc,$(VAR))
    @echo $(call uc,$(VAR))
Related