How I stopped worrying and loved Makefiles

Scope of Make: Simple vs Complex Builds

  • Many see make as great for simple projects: file-based builds, basic configuration, and lightweight orchestration.
  • Once you need feature detection, tool probing, or multi-platform support, the ecosystem tends to push toward GNU make, autotools, CMake, or other heavier systems.
  • Several argue that when a Makefile no longer fits on one screen or becomes “clever,” it’s a smell that the build is too complex.

Dependency Management and Cross‑Platform Concerns

  • A recurring theme: C/C++ lack a standardized package manager, pushing complexity into build systems.
  • Some advocate shipping all dependencies or using language-style package managers; others note that cross-platform libraries and end-user apps often can’t just “ship everything.”
  • Containerization (especially Docker) is cited both as a pragmatic workaround for dependency hell and as an unfortunate proliferation of duplicated environments.
  • Cross-platform targets (Linux, *BSD, macOS, Windows) complicate matters; make is seen as universal on Unix-like systems but still awkward on Windows.

Make as General Task Runner

  • Many use make as a high-level task runner: managing dotfiles, deployments, data processing pipelines, even system startup.
  • Defenders say this leverages make’s dependency graph, incremental rebuilds, and parallelism; critics call it an “abuse” and prefer plain shell or custom CLIs.
  • There’s agreement that PHONY targets and self-documenting help patterns can turn Makefiles into a useful project command menu.

Alternatives to Make

  • Popular alternatives for task running include Just, Taskfile, makesure, Rake, and Earthly; Ninja is admired for speed but is intentionally low-level.
  • Some feel there’s a niche between make’s complexity and ninja’s minimalism; others see generators (e.g., CMake) as filling that gap, though CMake itself is criticized as slow, opaque, and overfeatured.
  • Resistance to new tools often centers on adding yet another dependency versus make’s ubiquity.

Syntax, Ergonomics, and Learning Curve

  • Common pain points: tab sensitivity, cryptic automatic variables, legacy built-in rules, tricky variable and environment semantics, and quoting/escaping in recipes.
  • Multiple commenters say make became acceptable or even pleasant only after reading the manual or structured tutorials.
  • Some prefer CI YAML or dedicated CLIs; others find Makefiles clearer than large YAML pipelines and value decades of battle-tested behavior.

Caching, Correctness, and Security

  • There is interest in hash-based caching and better dependency tracking for things like CPPFLAGS, but consensus that it’s hard to bolt onto make cleanly.
  • Some argue that language-level package ecosystems are highly exposed to supply-chain attacks; using make with vendored dependencies is viewed as comparatively safer by a few participants.