Hacker News new | ask | show | jobs
by rtpg 1 day ago
there's a wonderful blog post about this that I wish I could find and can't. I feel like it was a github gist.

The gist of it is something like:

- Bazel community hits a problem with something like how npm behaves around paths

- Bazel's solution is to create a patching system around paths to resolve them

- rinse and repeat for every piece of tooling us "normies" are using

The end result is that instead of Bazel's efforts showing up in the base tooling, they build up a bunch of their own tooling and patches, and the underlying tools don't get really much if any benefit. Moving to Bazel still is a PITA, and there's a lack of improving onramps

In an alternate universe when people in Bazel land hit issues they would show up with patches and recommendations _to the underlying tools_ to get things merged in so that the workflows can be better supported across the board.

I don't think anyone working on Bazel is against upstreaming, but I think they discount the value of it because, hey, _they_ can get patches and hacks working for their flow

1 comments

Ah interesting, thanks.

My intuition is that npm, cargo, zig build etc are all “wrong”. And that Bazel/Buck are architecturally correct. Build systems should be polyglot by default! All these build systems and package managers that are per language are wrong.

But unfortunately Bazel and Buck have a decade plus of tech debt and baggage from their corporate overlords. Internal buck is actually mostly nice. I don’t know why anyone ever use it externally.

> My intuition is that npm, cargo, zig build etc are all “wrong”. And that Bazel/Buck are architecturally correct.

Arguably yes. The fundamental issue is that Bazel etc. are "hermetic" build systems - every build step they run is in a sandbox with only the inputs (source files and tools) that you have explicitly specified - nothing implicit everything explicit. And relies on the output you get from those inputs being the same every time.

This gives a wonderful property of knowing exactly which steps need performing and being able to cache everything - your whole build DAG is a merkle tree.

The downside is that many build steps do not fit into that mould - they make arbitrary network calls, or want to be able to access corners of your filesystem, or produce slightly different outputs each time due to multithreading etc. So you need to work around this in some way to make the larger system work.

(FYI, this is exactly the same as the Nix and Guix build systems except that for them the granularity of a step is "build one package" rather than "build one C file")

It's not about the package managers not being polyglot. It's about, for example, witnessing that `pip install` installs binaries with absolute paths and then writing a patch _for pip_ that Bazel uses, instead of figuring out how to change upstream pip to make that a configuration bit that Bazel uses.

Bazel uses npm/cargo/pip in most people's usage of these tools! People still use these packages managers, with random patches and tweaks (because the overall ecosystem assumes you're using them). But Bazel often includes random fixups in their own tools.

For example [0] is some patches Bazel does to node to get it to play nicely witH Bazel. In an (IMO) better world Bazel people figure out what they need, and figure out what they can get upstreamed into node to get things working.

Instead we have patches that (if you jump through the history) have been around for 6+ years

[0]: https://github.com/aspect-build/rules_js/tree/main/js/privat...

This comment gives off the impression that bazel just wraps cargo/pip/npm invocations, which is incorrect (at least in the commonly used scenarios)

First of all, bazel does not handle any of these languages/ecosystems itself. Such logic is delegated to language-specific rulesets, of which there are multiple implementations with different tradeoffs.

For python - https://github.com/aspect-build/rules_py parses a UV lockfile and does not use either UV or pip at build time.

For rust - https://github.com/hermeticbuild/rules_rs parses the cargo lockfiles but does not invoke cargo for compilation.

For js, https://github.com/aspect-build/rules_js parses the pnpm lockfile but does not invoke npm or pnpm at build time in the commonly used configurations.

While it's true that bazel allows to patch all dependencies on the fly, in my experience many Bazel users do try to contribute back, because managing stacks of hundreds of patches across all your dependencies isn't particularly fun.

sorry, you're right and I didn't express my idea well

> For python - https://github.com/aspect-build/rules_py parses a UV lockfile and does not use either UV or pip at build time.

rules_python does for example call into piptools to do installation

https://github.com/bazel-contrib/rules_python/blob/main/pyth...

To be honest this stuff feels like it's gotten soooo much better in the years since I've used Bazel. (one can easily argue that it's been thanks to language ecosystems getting their things better) compared to when I've last had to use Bazel back in 2021-2022 (I had initially set up Bazel in ... 2018 for an existing Python project). So this might be a bit like relitigating Python 3.0. The lessons are learned perhaps!

If I want to be very cynical... I think there is a universe where uv could have existed 5 years earlier if Google had decided "we're going to extract our Bazel learnings to get Python packaging to be better".

You might say "well they have blaze they don't need this" and that's kind of the point. In the world of setup.py you still need some language-specific infrastructure. Google and friends could have pushed things along in interesting ways, IMO!

But given their general sort of "we just vendor everything in" attitude they don't need to do that. So language ecosystems don't get the right kind of pushes and it takes us a decade for someone in the Python community to write "lockfiles that work + a package installer that works". Feels like a missed opportunity, mainly.

> Bazel uses npm/cargo/pip in most people's usage of these tools!

Oh interesting. Buck totally replaces cargo / pip. I think the JS story is a little messier. Not sure as I try my best to not touch JS.

See my comment above - the common language rulesets work in similar ways as Buck(2), AIUI. (Except bazel has features to consume external dependencies without vendoring, as opposed to Reindeer approach for example). Another difference is that since Bazel has much more adoption across the OSS world, there are more viable choices in language implementation rulesets, as opposed to Buck's prelude.
The problem has less to do with the fact that they are language specific build systems and more to do with the fact that build systems in general have refused to standardize.

If every build system came with sandboxing and programmable APIs that are all mostly the same, someone could have built a wrapper on top that exposes a standardized interface.