For everything else, it is absolutely horrible.
What I typically do is use make only for what it is good: as a dependency resolution back-end.
All the build logic for my projects is written in Python, in an executable file stored in the project root directory and called "make" (I have "." in my PATH).
The Python script, when it runs, generates on the fly a clean, lean, readable, unrolled, Makefile and feeds it directly to /usr/bin/make via a pipe.
Works like a charm:
Python (a sane and expressive programing language) to express the high-level logic needed to build the project.
Make as a solid back-end to solve the "what needs to be rebuilt" problem (especially the parallel version with -jXX)