At the highest level you want a purely functional DSL with no side effects. Preferably one that catches dependency cycles so it halts provably.
On the lowest level, however, all your primitives are unix commands that are all about side effects. Yet, you want them to be reproducible, or at least idempotent so you can wrap them in the high level DSL.
So you really need to separate those two worlds, and create some sort of "runtime" for the low level 'actions' to curb the side effects.
* Even in the case of bazel, you have separate .bzl and BUILD files.
* In the case of nix, you have nix files and you have the final derivation (a giant S expression)
* In the case of CI systems and github actions, you have the "actions" and the "gui".
Re: CI vs build system, I guess the difference is that build systems focus on artifacts, while CI systems also focus on side effects. That said, there are bazel packages to push docker images, so it's certainly a very blurry line.
> Re: CI vs build system, I guess the difference is that build systems focus on artifacts, while CI systems also focus on side effects. That said, there are bazel packages to push docker images, so it's certainly a very blurry line.
I think the CI and build system have basically the same goals, but they're approaching the problem from different directions, or perhaps it's more accurate to say that "CI" is more imperative while build systems are more declarative. I really want a world with a better Nix or Bazel. I think purely functional builds are always going to be more difficult than throwing everything in a big side-effect-y container, but I don't think they have to be Bazel/Nix-hard.
From my experience the main issue is interoperability with third party build systems. i.e. using a cmake library that was not manually bazeled by someone.
It’s been a few years since I tried to use it, but at the time the documentation was sparse and misleading. I couldn’t tell the right way to write my own rules and there were several concepts which were muddled. Some of the docs suggested I could extend it by implementing my own rules or macros and other docs suggested I had to delve into the extension interface which was a mess of convoluted Java (the kind of OOP that OOP advocates swear is Not True OOP). It certainly seemed like Bazel supports certain kinds of projects roughly aligned to languages, and if you needed to do anything interesting like codegen the answer was not at all obvious. The worst was that the docs all said that Bazel supported Python 3, but there were half a dozen different flags pertaining to Python 3, and after trying every permutation and asking for help, I discovered that the docs were simply wrong and Python 3 support had never actually been implemented due to various issues. It seems you need deep familiarity with Bazel in order to use it in even a basic capacity.
All fair points actually, a lot of babel rules were originally implemented internally in the starlark interpreter itself (written in java). I think nowadays a lot of the language support is implemented in skylark, and "toolchains" are first class concepts.
I definitely had entire days occupied by bazel when I used it, but when I figured something out, it generally "just worked" for the rest of the team.
Yeah, I think my experience might have been different if I had access to someone who was familiar with Bazel or Blaze or perhaps even if I were trying to build Java instead of Python. Hopefully things are better now and next time I take a stab at it I’ll have more success.
At the highest level you want a purely functional DSL with no side effects. Preferably one that catches dependency cycles so it halts provably.
On the lowest level, however, all your primitives are unix commands that are all about side effects. Yet, you want them to be reproducible, or at least idempotent so you can wrap them in the high level DSL.
So you really need to separate those two worlds, and create some sort of "runtime" for the low level 'actions' to curb the side effects.
* Even in the case of bazel, you have separate .bzl and BUILD files. * In the case of nix, you have nix files and you have the final derivation (a giant S expression) * In the case of CI systems and github actions, you have the "actions" and the "gui".
Re: CI vs build system, I guess the difference is that build systems focus on artifacts, while CI systems also focus on side effects. That said, there are bazel packages to push docker images, so it's certainly a very blurry line.