top | item 43765346

(no title)

alexykn | 10 months ago

Hey, so I built this thing, most of it at so far at least. And yeah, right now it isn't doing many things better than Homebrew.

Setting of relative paths for bottle installs is still not perfect, well it works for every bottle I have tested except rust. Getting bottles working 100% is very doable though imo.

Build from source formulae is still pretty f*ed + I do not know if it is really feasible given that the json API lacks information there and a full on Ruby -> Rust transpiler is way out of scope. Will probably settle for automatic build system detection based on archive structure there. + Maybe do my own version of the .rb scripts but in a more general machine readable format, not .rs lol

Casks seem to work but I have only tested some .dmg -> .app ones and .pkg installers so far though. As with bottles 100% doable.

Given that almost all formulae are available as bottles for modern ARM mac this could become a fully featured package manager. Actually didn't think so many people would look at it, started building it for myself because Homebrew just isn't cutting it for what I want.

Started working on a declarative package + system manager for mac because I feel ansible is overkill for one machine and not really made for that and nix-darwin worms itself into the system so deep. Wrapping Brew commands was abysmally slow though so I started working on this and by now I am deep enough in I won't stop xD

Anyway I am grateful for every bug report, Issue and well meaning pull request.

discuss

order

godelski|10 months ago

This is awesome!

Is there uv support?[0]

One of my biggest gripes about brew is how they manage dependencies. The devs have a conflicting philosophy that creates bloat. Package maintainers must define settings, settings should always use the latest Python version. It makes no sense. Maintainers won't update unless things break so you got a bunch of Python versions running around. And it won't use system Python!

Uv seems to provide an elegant solution for this. You can build a venv for each package and rust version will only have the specified deps. Since uv finds all your Python instances (and packages) and soft links them you have way less bloat and venvs become really useful. You can also use run and other tools to handle executables

Plus is also rust so good synergy ;)

[0] https://astral.sh/blog/uv

Kwpolska|10 months ago

You should only be using Homebrew for installing software that happens to be written in Python, not dependencies for your own Python projects. If you do that, the Python version does not matter, it's just whatever version is required to make the package work.

alexykn|10 months ago

love uv <3 I will look into integrating that. Have not decided if and how to implement my own packaging / source build dsl though and will probably open a git poll for that the coming days

samhclark|10 months ago

You mentioned a declarative package manager for Mac. I've really liked using Homebrew Bundle [1] over the last couple years. It's about the level of declarative that I've wanted and has made it really easy to bootstrap new laptop or VM (since it also works on Linux). The format for a Brewfile was pretty easy to figure out.

The way I ended up using it was that `brew install` would temporarily install something, without adding it to my Brewfile. And a little `brew add` wrapper would add the package to my Brewfile to keep it on the system permanently. That part with the wrapper could have used some love and would be a nice fit for a new brew-compatible frontend IMO. Maybe you could expand on that for Sapphire, if that also scratches your declarative itch?

[1] https://docs.brew.sh/Brew-Bundle-and-Brewfile

JimDabell|10 months ago

That would be fantastic. My bootstrap scripts already use bundle but it’s easy to fall into config drift.

jrochkind1|10 months ago

What makes you interested in a rust implementation of brew?

I'm guessing it's that you hoping that it is eventually more performant -- are there specific areas of current brew you have identified as performance bottlenecks likely to eventually benefit from a rust implementation?

Or any more info to share about assumptions/hopes that motivated this or any other motivations?

alexykn|10 months ago

Building from source, obviously, will never be really that much more performant as it mainly relies on the underlying build systems and things like ninja, cmake, cargo etc. are usually optimized very very well.

Thanks to rust just being (slightly, significantly? no idea about ruby's speed) faster + concurrent downloading & pouring of bottles, most "regular" formula installs feel a good bit faster than brew already. Mainly noticeable when installing multiple formulae at once.

Casks, especially those with pkg installers, seem to profit a bit less here.

Performance was a reason, not the main one though, like I said I wanted and still want, to build a declarative package + system managing solution on top. The idea was to get into rust with that. Imo having the base written in the same language instead of wrapping commands also gives more flexibility there.

Another reason is that I never liked the way brew looks and feels. Right now the ui/ux for Sapphire is far from finished, more like a clusterf*k and only the search command really looks the way I want it. Aiming for something modern, clean and information rich without beeing overly verbose. I really like dnf5 and what AerynOS is doing and will probably take some inspiration there.

Like mentioned, Bottles and Casks should be 100% doable and that would cover most package needs on macOS, I do not see why I should also define a new repo and packaging ecosystem when such a big and popular one exists.

Source build capability will probably stay(for easy integration of source building in the system management part later) but not be focused on brew formulae as the ruby dsl would be a horror to parse.

Well and sh*t I am not trying to compete really. This is the first time building something with rust and I really really had no idea what a giant never ending rabbit hole macOS package management is and how massive and complex Brew is.

This went from should I to can I pretty quick for me xD

dijit|10 months ago

I say this from ignorance, but coming from a lineage of linux package managers; brew must be doing something wrong - and upon immediate introspection I doubt that its language specific.

The performance of apt/dnf in comparison is surreal; but dnf (or at least yum, its predecessor) is written in Python; which has even worse performance characteristics than Ruby.

Clearly something is wrong, I wonder how different they are architecturally.

fnord123|10 months ago

`brew search python` takes 3 seconds from a cold start.

NewJazz|10 months ago

Just FYI you are describing a ports system, of which there are many. From macports, to alpine packages, to nixpkgs... Tons of research and automation in this area already. Would encourage looking at Nix and distri in particular. Many Nix packages can be built on/for macOS!

https://nixos.org/manual/nixpkgs/stable/#preface

https://michael.stapelberg.ch/posts/tags/distri/

alexykn|10 months ago

I know nix, did use nix-darwin for a while and actually integrated my own scripts called from the flake into setting up my system xD

Scramblejams|10 months ago

Cool project, good luck with it!

If I may surface one use case: Several years ago I had to manage a bunch of Macs for CI jobs. The build process (Unreal's UAT) didn't support running more than one build process at a time, and Docker was really slow, so I'd hoped to use different user accounts to bypass that and get some parallelization gains. Homebrew made that very difficult with its penchant for system-wide installs. So a feature request: I'd love to see a competitive package manager that limits itself to operating somewhere (overridable) in the user's home directory.

alexykn|10 months ago

Initial idea for this really came from my dayjob too, we have macs but no way to centrally manage them. The client / server part for the declarative system manager I want to build on top of this is quite far out yet though. At least several months

watermelon0|10 months ago

IIRC the main reason here is that brew path is hardcoded during the build process of packages, which means that you wouldn't be able to use bottles.

I didn't check, but there is a chance that path is also hardcoded in (some) formulae, so even building from the source might not help here.

amarshall|10 months ago

Nix effectively has per-user packages, but it’s hard to read into your full use case from your comment.

benwaffle|10 months ago

oh, I guess this is why the nix installer creates 32 macOS users called _nixbld$N

3np|10 months ago

> probably settle for automatic build system detection based on archive structure there

Please add knobs for the end user to manually configure this per package and global default before adding autodetection. As a user to is very frustrating to have to patch the package manager to override some well-intentioned automagic which didn't consider my setup or dig through sources to uncover some undocumented assumption. yarn is a cautionary example.

alexykn|10 months ago

I'll add manual override flags and also let users not only build from source from formulae but any dir on their machine they want, only makes sense

miki123211|10 months ago

> Build from source formulae is still pretty f*ed + I do not know if it is really feasible given that the json API lacks information there and a full on Ruby -> Rust transpiler is way out of scope. Will probably settle for automatic build system detection based on archive structure there. + Maybe do my own version of the .rb scripts but in a more general machine readable format, not .rs lol

Last I checked (which was about a year ago), Homebrew had ~7000 formulas (not including casks).

I think it would be feasible to transcribe most of them to your format of choice with AI, run the build in a loop and ask the LLM to fix errors, and reserve manual intervention for the few cases that the LLM can't fix.

alexykn|10 months ago

Yeah, this would 100% be feasible. Great idea. It's during the week now so I don't have much time besides work.

I'll probably open a Poll on git within the next couple days about what to do about a real from source packaging system with it's own dsl, maybe just yaml/toml or something a bit more powerful like lua with mlua. No matter the choice of packaging apporach I would like to keep the generated packages "bottle compliant" -> at least with the json api spec, since this also installs from there.

There seems to be at least some in my project so even though I am very opinionated on a lot of things I don't think I should decide on that completely alone, especially given that this is the first time I play with packaging.

nicoburns|10 months ago

Perhaps you could embed something like https://github.com/artichoke/artichoke to run the Ruby scripts for compatibility.

alexykn|10 months ago

Looked at that. I do not really think implementing something like artichoke or rutie would be a good idea. I do not want my project to become overly bloated and to achieve my real goal of a declarative system management thing I think sticking to bottles (that cover almost all formulae thanks to the amazing homebrew community) and casks, getting those to work 100% is the better approach. Thank you for the suggestion though!

stevage|10 months ago

Does the "casks" and "bottles" language imply that it's intended be compatible with Homebrew? That isn't made explicit in the description.

MatthiasPortzel|10 months ago

Yes, this is only a replacement for the Homebrew CLI. It doesn’t have its own package repository and moreover it doesn’t have the ability to build packages (yet)—it’s just downloading and installing the binaries built by Homebrew.

AlphaSite|10 months ago

Can you just shell out to homebrew for unsupported cases? I don’t imagine the overhead of ruby will be that high compared to compiling the code.

internet2000|10 months ago

Good luck. Homebrew hasn't cut it since they started disallowing custom compile flags, and making the user jump through hoops if they want anything slightly different.