Another challenge in my quest to not have any programming languages installed directly on my computer is installing programs that need to be built from source. I’ve been using
jj in place of Git for the last few months1. To install it you can either download the pre-build binaries, or build from source using
cargo. When I first started using it there was a minor bug that was fixed on main but not the latest release, so I needed to build and install it myself instead of just downloading the binary.
Naturally the solution is to hack around it with containers. The basic idea is to use an base image that matches the host OS (Ubuntu images for most languages are not hard to come by) and build in that, and only copy the executable out into the host system.
scm-diff-editor I make a
Containerfile like this:
RUN apt install libssl-dev openssl pkg-config
RUN cargo install --git https://github.com/martinvonz/jj.git --locked --bin jj jj-cli
RUN cargo install --git https://github.com/arxanas/git-branchless scm-record --features scm-diff-editor
COPY install.sh .
This just runs the necessary
cargo commands to install the two executables in the image. The
install.sh script is super simple, it just copies the executables from the image into a bind-mounted folder:
for bin in jj scm-diff-editor; do
cp "$(which "$bin")" "/output/$bin"
So the last part is just putting it all together with a
pod config file:
I can then run
pod build to create a new image and build new executables with
pod run the container to copy them out of the image and into the
$PATH on my host system.
This is the same approach I used for the automatic install script for
pod itself—except using
podman commands directly rather than a
pod config. I’ve done the same thing to install
rubyfmt since that is only packaged with Brew, or requires Cargo to build from source.
I’m sure at some point an incompatibility between libraries inside and outside of the container will create a whole host of bizarre issues, but until then I will continue using this approach to install things.
Short review, it’s good but has a long way to go. Global undo is excellent, and I like the “only edit commits that aren’t in main yet” workflow. ↩