One of GNU make's many features allows you to shorten build times by running more than one command at a time. If your dependencies are all correct, or nearly correct, this can give you a significant improvement, and since it's built into the tool you get it "for free." But GNU make's parallel build feature—often called "dash j mode," after the command-line option that is used to enable it—is not without drawbacks. The worst of these is that GNU make parallel builds can produce incorrect results if the build dependencies are not sufficiently correct.
GNU Make has no built-in arithmetic capability. In this article, I present a collection of GNU Make macros that implement functions for addition, subtraction, multiplication, and division of integers. Functions are also provided for integer comparisons such as “greater than” and “not equal.” These macros are implemented entirely using GNU Make's built-in string manipulation functions.
Make's dependency syntax is flawed because it incorporates both foo.o must be updated if header.h, system.h or foo.c are changed and foo.o is the result of compiling foo.c. Thus, anything to the right of the : is a prerequisite, but the first prerequisite where there's a rule body (i.e. commands) is special: it's the prerequisite that will be passed to the compiler (or other command) to actually generate the target.
Make programs are very good at keeping track of targets, files that need to be built, and the dependencies between targets. But the Make program is only as good as its inputs. If you don't tell Make about a relationship between two files, it wont discover it on its own and it'll make mistakes because it assumes it has perfect knowledge about the files and their relationships.