How I install personal versions of programs (on Unix)

April 11, 2025

These days, Unixes are quite generous in what they make available through their packaging systems, so you can often get everything you want through packages that someone else worries about building, updating, managing, and so on. However, not everything is available that way; sometimes I want something that isn't packaged, and sometimes (especially on 'long term support' distributions) I want something that's more recent that the system provides (for example, Ubuntu 22.04 only has Emacs 27.1). Over time, I've evolved my own approach for managing my personal versions of such things, which is somewhat derived from the traditional approach for multi-architecture Unixes here.

The starting point is that I have a ~/lib/<architecture> directory tree. When I build something personally, I tell it that its install prefix is a per-program directory within this tree, for example, '/u/cks/lib/<arch>/emacs-30.1'. These days I only have one active architecture inside ~/lib, but old habits die hard, and someday we may start using ARM machines or FreeBSD. If I install a new version of the program, it goes in a different (versioned) subdirectory, so I have 'emacs-29.4' and 'emacs-30.1' directory trees.

I also have both a general ~/bin directory, for general scripts and other architecture independent things, and a ~/bin/bin.<arch> subdirectory, for architecture dependent things. When I install a program into ~/lib/<arch>/<whatever> and want to use it, I will make either a symbolic link or a cover script in ~/bin/bin.<arch> for it, such as '~/bin/bin.<arch>/emacs'. This symbolic link or cover script always points to what I want to use as the current version of the program, and I update it when I want to switch.

(If I'm building and installing something from the latest development tree, I'll often call the subdirectory something like 'fvwm3-git' and then rename it to have multiple versions around. This is not as good as real versioned subdirectories, but I tend to do this for things that I won't ever run two versions of at the same time; at most I'll switch back and forth.)

Some things I use, such as pipx, normally install programs (or symbolic links to them) into places like ~/.local/bin or ~/.cargo/bin. Because it's not worth fighting city hall on this one, I pretty much let them do so, but I don't add either directory to my $PATH. If I want to use a specific tool that they install and manage, I put in a symbolic link or a cover script in my ~/bin/bin.<arch>. The one exception to this is Go, where I do have ~/go/bin in my $PATH because I use enough Go based programs that it's the path of least resistance.

This setup isn't perfect, because right now I don't have a good general approach for things that depend on the Ubuntu version (where an Emacs 30.1 built on 22.04 doesn't run on 24.04). If I ran into this a lot I'd probably make an addition ~/bin/bin.<something> directory for the Ubuntu version and then put version specific things there. And in general, Go and Cargo are not ready for my home directory to be shared between different binary architectures. For Go, I would probably wind up setting $GOPATH to something like ~/lib/<arch>/go. Cargo has a similar system for deciding where it puts stuff but I haven't looked into it in detail.

(From a quick skim of 'cargo help install' and my ~/.cargo, I suspect that I'd point $CARGO_INSTALL_ROOT into my ~/lib/<arch> but leave $CARGO_HOME unset, so that various bits of Cargo's own data remain shared between architectures.)

(This elaborates a bit on a Fediverse conversation.)

PS: In theory I have a system for keeping track of the command lines used to build things (also, which I'd forgotten when I wrote the more recent entry on this system). In practice I've fallen out of the habit of using it when I build things for my ~/lib, although I should probably get back into it. For GNU Emacs, I put the ./configure command line into a file in ~/lib/<arch>, since I expected to build enough versions of Emacs over time.


Comments on this page:

By Todd at 2025-04-11 23:38:20:

Ugh. That sounds like a lot of work that I decided a long time ago to not do. But I'm not as old school as you, cks.

Written on 11 April 2025.
« One way to set up local programs in a multi-architecture Unix environment
Mandatory short duration TLS certificates are probably coming soon »

Page tools: View Source, View Normal.
Search:
Login: Password:

Last modified: Fri Apr 11 23:03:34 2025
This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.