All of them. They all do.
Build systems and CI pipelines are two sides of the same coin. Both define crappy/broken DLSs for creating artifacts and do it wrong.
[insert gripings about gitlab and github CI]
Each result can be defined as a function that takes Environment and Context as an input and outputs a reproducible artifact. The generalization of tihs approach results in constructing a forest of roots that result in a DAG. However, sometimes the Acyclic bit is too strong of a constraint, so I think we can relax that to a bounded level of cyclic behavior, keeping in mind the principle of Automation With a Human Touch - Jidoka. That all said, something that I think is even more important than being able to specify the fully generalized DAG is being able to specify efficiently and ergonomically the caching behavior and artifacts that are dependencies of steps. You would think this would be implied by the DAG. DAGs are, after all, fully composable and the representation of a build system in a DAG would contain, for each node, the full closure of everything required to reproducibly create the artifact. But nooo, this has to pointed out. So here’s my ranty rant pointing out that if your CI/build system doesn’t have a way to performantly deal with artifacts, dependencies, and environmental closures, its automatically got a lot of flaws and limitations that didn’t need to be there.. (looking at you in particular, github; you had a lot of time to learn from the mistakes of others)
More thoughts go here. Nix has it mostly right but it’s terrible at incrementalism and still pretty awful at composition. Particularly, it lacks a way to easily and ergonomically mix versions of things and modify package sets. This ends up resulting in the entire nix ecosystem touting an infinite amount of flexibility and ability to deploy multiple versions of anything anywhere when in reality it only really ships with, for the msot part, a single version of every piece of software. Crucially, this makes it almost impossible to integrate other build systems and other language ecosystems (eg programming language packages) into Nix without relying on ad-hoc x2nix tooling to generate on-the-fly all of the appropriate derivations. It’s not sufficient to have created a natural transformation mapping from the ecosystem into nix and make such a mapping available in a flake or something.
Shake is nice, it has all the best properties of a build system except the culture bit. It’s very difficult to reshare build rules with shake and to create organized libraries of build rules to integrate other things with shake. Again, like nix, it ends up being a very whole-sale propsition but without even the benefit of having a meger community behind it focused on rewriting the entire world in Shake. For bespoke systems that require very complex logic to be tied together, or for writing a new build sytem from scratch, Shake is excellent. But for just getting a monorepo compiling together seamlessly, it seems to be just too much work for too little benefit, unfortunately.
Bazel. Screw bazel. It’s the most popular out there but that doesn’t mean it’s the best. It’s just the least worst, and trading developer time for CPU cycles is never a good idea, culture wise. Bazel also really needs x2bazel tools in order to be effective; particularly for retrofitting bazel into an existing repository. However, the main difference is that Bazel is used by a lot of corporations that can just print money, and so it ends up that there are a lot of nice x2bazel tools out there for many languages and systems. This is the only reason its even sane to use.
One thing that’s very interesting is there’s some work on “no code” build systems, where you merely give it a small text file of commands you ran locally on your computer and it traces the entire state of your computer to the best of its abilities in order to derive the optimal build graph for your program rather than requiring you to explicitly build it. I suspect it won’t scale for anything complex, but considering that there’s an absolutely huge amount of code out there that does trivial stuff badly, there’s a lot of potential in this idea. Pareto Principle and all that. 80% of the bugs with 20% of the effort. wewlad. we #webscale now.