Makefiles are too brittle and allow all kinds of user errors. Targets with too many dependencies, too few dependencies, race conditions. The default doesn’t even handle transitive #include dependencies without you yourself plugging in complex .d-file generation using the compiler.