For those still using Makefiles, we all know there's no better place than computing to see that there is no problem simple enough that does not deserve a complex solution (--Dario Roccati), I thought I'd share something that Makefile artists know all too well, that might find trivial and misleading and full of traps... but something which might fit the Makefile YOU are writing. Computing, like many problems, is a set of problems which is best dealt with if you have an ever growing bag of tricks and tools to your disposal, so... one more will not hurt :).
Say, that someone just gave you a list of .cpp and .c files and you had to generate a simple static library to use in the rest of the makefile.
To make the makefile target simple and avoid a lot of unnecessary typing you might want to collect the C and C++ files and the .o files they generate once you compile them.
Let's see an example:
L_BASELIB := $(filter %.c,$(L_BASELIB_SOURCES))
L_BASELIB_OBJ := $(patsubst %.c,%.o,$(L_BASELIB))
L_BASELIB_SOURCES is defined as a list of .cpp and .c files earlier on in the makefile. In this example, we take a two steps solutions to get out list of object files only for the .c files (just to make a small example you can adapt to your needs).
The filter and patsubst commands are quite powerful and to use their regular expression powered syntax the best way possible you might want to read more on regular expressions, gnu make, etc...
The way I have used them in this example is to first filter the files with a .c extension out of the list of files I have been passed by this environment variable and then produce another list of files with the extension changed to .o from .c and so on.