cross-posted from: https://sh.itjust.works/post/64685863
Lots of programming languages have their own package manager, separate from the distribution or OS package manager.
Going loosely from the TIOBE index:
- Python has Pip
- C# has NuGet
- Javascript has
npmfor Node.js- Visual Basic also uses NuGet
- R has a repository of packages that can be installed by running
install.packages("something")in R- Rust has Cargo/Crates
- Go has the
go getcommand- Swift has its own package manager
swift package- Ruby has RubyGems
- Java has Maven and Gradle (not sure if they are full package managers, or build automation tools with dependency resolution)
- PHP has Composer for managing libraries and dependencies
- C and C++ are the only exceptions I can think of, off the top of my head; libraries are managed by, and coupled to, the operating system
It’s because every ecosystem wants its own GovOS.
You want some way to define package versions in your repository, so that you can check out an earlier commit or a different branch and still have a working build. Because you do often need to adjust the code in your repo when dependencies get updated.
And going upwards from there, I think that languages are just a point where it’s quite natural for this to be solved, since the language creators care to build up an ecosystem and it does help when you can make language-specific assumptions.
I do think, it’s possible to create a package manager that spans across programming languages, like Nix is starting to be viable for.
But you need that to be ready when a new programming language is starting to take off. For all the languages you listed, that choice was made many years ago and you can’t easily reverse it.As people grow up, they stop believing in magic

It’s because it’s the greatest thing since compilers. Having a clear “this is how packages interact” rules and “autodownload dependencies” solves a massive headache. C/C++ packages are basically the wild west.
If you’ve ever tried using bazel, you might understand why writing a single package manager for multiple languages is a bad idea (at least, that’s why I assume bazel is so god-awful)
It’s not that it’s a bad idea, it’s more that it’s basically impossible at this point.
Bazel can’t use Cargo, CMake and so on for downloading & building packages because it is trying to do cross-language builds the right way - a single build graph that includes everything. No other third party package managers/build tools actually exposed their build graphs - only commands to perform builds, which are too coarse for Bazel.
To put it simply, its necessary if you are doing things at the scale of Bazel.
Care to elaborate?
It’s been a while since I used it in earnest, so my memory is hazy enough that I can’t be specific. One of the largest pieces of work I’ve done in C++ was not writing C++, but working out how to ask bazel to build a single shared library that imports other bazel libraries. I’ve never used such a confusing and frustrating package manager. It was frequently unclear how to do things, despite the project having quite a lot of documentation.
When I read it supports multiple languages, I had two thoughts:
- Why? That feels like trying to write a single style sheet for both English and Mandarin.
- That might explain why it’s so confusing. I surmised: I has to bend over backwards to support all these different languages and their different module and packages architectures. And it doesn’t manage to hide that complexity from the user.
Thank you. I didn’t expect that because I assume that packages are basically the same everywhere you go (at least in my experience). And managing them is basically solving dependency trees, then downloading files and putting them in the right place for the import system to find them.
But my experience with programming languages is limited. I haven’t found a language that doesn’t work this way.
I thought Bazel was just a build system, not a package manager.
Hmmm, you might be right. It’s definitely a build system. I’m trying to think if it’s a package manager, and if it’s not, what is playing the role of the package manager.
EDIT seems to be both, which admittedly makes my point less relevant.
https://moderncppdevops.com/pkg-mngr-roundup/#build-systems-and-environment-managers
Because professionals have standards.
i dont understand why you are confused. are you suggesting they should be in the OS? so each library has to be managed at least 6 times and then the ides and language tools have to support all these different stores? i bet ci/cd would just be awesome
or are you suggesting that all language maintainers work together in harmony and support one another?
C and C++ dont have package managers because they are older than the concept.
And I prefer C/C++ and Python due to that.
Eg. JS devs need to version pin in NPM to not expose users to compromised packages. That means that, from now on, they need to be active at least every week and update the pinning to not expose users to vulnerable packages. Meanwhile, the users need to be on-edge about the dev actually being active, and, still, for every vulnerability and compromised package, need to scan their whole system for files relating to that package. And of course, that means a very long fix path of Vuln discovered -> Vuln fixed -> Dev knows that one of the dozen packages they use needs updating -> Dev updates -> Package managers updates -> User updates.
It’s a horrible experience for sysadmins. I’m actively switching to alternatives and rewriting smaller things in C++, because everything I’ve written in the latter has never broken in years, without recompilation, because the ABI stayed the same for all libraries, while the libraries get carefully curated by a dedicated team. And as soon as a vulnerability/backdoor is found and fixed? sudo pacman -Syu. nothing more, nothing less. Fix path: Vuln discovered -> Vuln fixed -> Package managers updates -> User updates.
Looking at more than just binary files in repos: I’m also actively rewriting PKGBUILDs to use the native python packages instead of building a venv, because that just works better in my experience. I’ve never had issues with incompatibility between python-* packages, simply because they are build for each other. And I mean, it took 30 minutes to build a component that converts a requirements.txt, which requires you to trust the dev (to be active) and pypi (which you can’t trust), to a collection of pacman packages. Universally applicable to all requirements.txt and uncomplicated. So yeah, idiots can continues using pip, I laugh with a list of packages neatly curated by a dedicated team.
I don’t know why you think Python is fine but Typescript isn’t. With modern Python best practice (project.toml and uv) they have basically the same behaviour and caveats. Python is actually a little worse because most Python packages don’t use semver.





