The problem with `make` (and <i>all</i> build systems that generate `Makefiles` for `make`) is both flexibility and correctness.  Correctness problems:<p>* Make cannot correctly specify file system state dependencies (like inexistence of files, such as include files in include paths prior to the found location).<p>* Make doesn&#x27;t protect against accidental edits of source code while it is being built, poisoning the result files. When you try to run &quot;make&quot; again, it will say nothing is to be done, but the result file [with its newer mtime] can actually be based the pre-save source file.<p>* Make uses &lt; and &gt; for mtime checks (not just ==) and that is incorrect on some operating systems (e.g: Windows).<p>* Make offers no practical way to track or enforce system-level dependency changes.<p>* Easily miss stderr printouts from compilers&#x2F;etc, if you missed them at the first time around (losing mainly gcc&#x2F;clang warnings)<p>The &quot;solution&quot; is almost always to &quot;make clean&quot; whenever voodoo bugs are encountered, anything system-level is changed, etc. This is terrible if you expect correctness from your tools.<p>Flexibility-wise, make is also awful, due to one <i>huge</i> problem:<p>Make requires the dependency graph to be fully specified, including all transitive dependencies. This makes code generation a near impossibility -- since you often need to scan the generated code to figure out its dependencies.<p>IOW: Make is a &quot;two-phase&quot; build system, where we really want an &quot;N-phase&quot; build system that interleaves building with dependency scanning&#x2F;discovery.<p>Also, this is taken for granted, but it is major: Make requires error-prone specification of all file dependencies.  This is impractical <i>to do correctly</i> in large, complex projects. Every script being run may have tons of transitive dependencies that are very hard to specify. Any mistake will usually go unnoticed, until you hit a &quot;voodoo bug&quot; and just &quot;make clean&quot;.<p>Additionally, make doesn&#x27;t support any form of advanced caching of previous build results.<p>---<p>All these problems, and more, made me decide to create my own build system for our complex C project: buildsome[1].<p>It uses file system hooking to provide both correctness (no more missed input dependencies!) and simplicity (no need to specify each and every transitive dependency, they can be automatically discovered).<p>It checks input files for changes after the build commands (to avoid output file poisoning). It remembers stderr and re-prints it. It supports N-phase builds. And more.<p>[1] <a href="https:&#x2F;&#x2F;github.com&#x2F;ElastiLotem&#x2F;buildsome" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;ElastiLotem&#x2F;buildsome</a>