Converting Strings to Uppercase in GNUmake

GNUmake doesn’t have a feature to convert Strings to uppercase. But hey, UNIX world is all easy. Just use a good shell, like bash :)

The demo use case is to pass a define to the C compiler that contains the filename stem converted to uppercase.

 1 override CPPFLAGS+=-DFILE=FID_$${MODULE^^}
 2 
 3 SHELL:=bash
 4 export SHELLOPTS:=errexit:pipefail
 5 sources:=$(shell find -name "*.c")
 6 
 7 %.o: export MODULE=$*
 8 
 9 .PHONY: all
10 all: foo
11 
12 foo: foo.o $(sources:.c=.o)
13 
14 .PHONY: clean
15 clean:
16         rm -f foo $(sources:.c=.o)

This simple Makefile compiles and links a binary named foo from all C source files. The rule-specific variable MODULE is defined for %.o rules and contains the stem of the implicit rule match %.o: %.c. The variable MODULE is exported to make it available to the bash subshells. The variable CPPFLAGS which is used by the shell scripts for the implicit rule %.o: %.c contains the expression ${MODULE^^}. The bash shell will expand this to the value of the variable MODULE and because of ^^ convert it to uppercase. Btw. this Makefile is complete and will work for a lot of simple C projects.

You can also easily extend this Makefile to support an incremental build:

 1 override CPPFLAGS+=-MMD -DFILE=FID_$${MODULE^^}
 2 
 3 SHELL:=bash
 4 export SHELLOPTS:=errexit:pipefail
 5 sources:=$(shell find -name "*.c")
 6 
 7 %.o: export MODULE=$*
 8 
 9 .PHONY: all
10 all: foo
11 
12 foo: foo.o $(sources:.c=.o)
13 
14 -include $(sources:.c=.d)
15 
16 .PHONY: clean
17 clean:
18         rm -f foo $(sources:.c=.o) $(sources:.c=.d)
Written on November 28, 2011