it's understandable why programmers have opinions about aesthetics regarding their IDE, language, or framework of choice, but what is there to be opinionated about with a build system?
it's understandable why programmers have opinions about aesthetics regarding their IDE, language, or framework of choice, but what is there to be opinionated about with a build system?
I think you're saying this because your idea of a "build system" is a very simple set of sequential steps from known source code input files to an output binary.
The differing opinions come in when the "build system" includes various contradictory philosophies of how to configure and specify the building of complex software.
Different opinions on:
- syntax : should build config be XML, or JSON, or YAML, or custom syntax? E.g. Ant and Maven used XML but Gradle does not
- dependencies search: should build system implicitly find and add relevant dependencies? Or should programmer explicitly specify each one?
- reproducible builds (version pinning) vs auto-updated dependencies.
- should the build system be "smart" about cross-platform differences? If yes, you end up with complicated build tools like GNU Autoconf "configure" bash script, or CMake's complex syntax.
- should build system do optimization and bundling tasks that's not strictly limited to "compile" steps? Some Javascript build tools try to eliminate redundant or unused js code to make downloads smaller.
- etc, etc.
I also recommend reading the blog post "So you want to write a package manager"[1] to get an idea of how complicated a build system can get. The title says "package manager" but much of the material is also about build systems.
The bottom line is that reasonable people can disagree on the priorities and therefore, you can't create The One & Only Build System to End All Other Build Systems.
[1] https://medium.com/@sdboyer/so-you-want-to-write-a-package-m...
It’s great that Timmy thinks an obscure extension of YAML is the best way to define build configs, but all the rest of the engineers use JSON, so that is what we use.
Perhaps because the incumbent/popular build systems are far from being the best solution for the job, particularly when compared with build systems available for other technologies.
For instance, in C and C++ land the incumbents are still hand-written Makefiles, autotools, or cmake, which leave much to be desired.
- system requirements
- convention vs configuration
- flexibility vs predefined paths
- tradeoff features vs their complexity (parallelism, caching, ...)
- level of integration with specific other tooling (VCS, languages, package managers, ...)
Consider this makefile rule:
foo.a: $(patsubst %.c,%.o,$(wildcard *.c))
Now, the foo.a target will be considered as stale if any of timestamps of it's dependencies is newer than foo.a
But what if you remove a .c file?
As build systems like make don't capture a fingerprint of the names of the inputs of a built (let alone the hash of their contents) it's very hard for them to deal with that case correctly.
Correctness is important otherwise your trust in the incremental builds quicky erodes and you start doing clean builds all the times you get an error, just in case.
The blog post [0] also contains arguments against checksums: Sometimes building a target has side effects. Checksumming every output after building it is somewhat slow. Checksumming every input file before building is very slow.
What matters is keeping track of the actual dependencies and Redo does indeed save that knowledge in a database that gets consulted between runs.
Last year I learned about .PRECIOUS and it was awful