Or, a short treatise on silent failure. The makefile, as powerful as it is pervasive, is much like any other power tool in that you can spend all day mashing yourself in the thumb with it if you don't know how to use it properly. The problem with them is that the syntax is so permissive that almost everything is valid, but it's so specific that a single misplaced character will produce a completely different result from what you wanted. Common mistakes:
- Misplaced spaces
- Inconsistent use of trailing slashes in paths
- Pattern rules in the wrong order
You have to be careful with leading and trailing whitespace, because it will cause two seemingly identical paths to not match. The same goes for trailing slashes on pathnames. /a/b/c will not match /a/b/c/. No, it isn't obvious, because you might assume that the makefile operates primarily on files rather than strings. But it does matter.
Finally, as for rule order. The order of execution on dependencies, laterally, is undefined. That is, given "a: b c d" the order in which b,c and d are completed is undefined, especially in multi-threaded builds. Vertically, given "a:" "b:" and "c:", the order of execution is based on the dependency relationships between those targets. So what does rule order matter? Because the order in which rules are evaluated is from top to bottom. Although the build system is great at automatically navigating dependency trees and generating hundreds of shell commands, it is up to you to enter build rules in the correct order of specificity, not so that they run in any particular order, but so that they are tested with the correct priority. For example, I've been working on a makefile to automatically patch the lastest Radeon driver to build for the latest stable kernel on Debian. The first thing my script needs to do is unpack the archive into a directory I've named "oem", so the rule for this is "oem/%: oem". But even though it's the first task to execute, the rule belongs at the bottom of the script because it is the catch-all for any target which did not match any preceding rule. It basically says "If after everything else, you couldn't find a file, then make sure you unpacked the archive". I'm going to throw in a shell command at the end that tests to make sure that the target is on the filesystem, because otherwise, make will not spit out an error message because the rule matches irrespectively of whether it succeeds at outputting the target sought.
