You might like tup[1]. Its killer feature is that it automatically determines file-based dependencies by tracking reads and writes (using a FUSE filesystem). It has an extreme emphasis on correct, repeatable builds, and is very fast. Other stuff:
- does work in parallel, and will let you know if your build isn't parallel safe. (note it is NOT relying on your specification of dependencies: even if you manually specify dependencies, it will tell you if something's wrong based on what it actually observes your dependencies to be)
- tracks changes to the build script and reruns if the commands change.
- cleans up old output files automatically if build rules are removed.
- lets you maintain multiple build variants (say for different architectures, configurations, etc)
- autogenerates .gitignore files for your build output
- very easy to get started, and "Just Works".
- for advanced usage, it is scriptable in Lua.
I've tried every build system out there. For Unix-y file-based build tasks, tup is, by far, the best. I don't know why it isn't more well known.