Bundled up
I wonder if there’s a market for a new type of bundle.
See, bundles have some distinct advantages over standalone executables: notably, you can stow frameworks within them and tell the load-time dynamic linker to use a path relative to the dependent binary (or alternatively, a path relative to the ultimate executable) in order to find frameworks. This is a very handy thing indeed, because it makes everything neatly relocatable. If you don’t care about shared frameworks (and most people have no reason to), you can drag and drop most applications anywhere you like.
So I was thinking about command-line tools. Or, more accurately, suites of tools. Things like the GNU utilities, for example: quite often there are lots of interdependencies and required shared libraries and things, and all you want to do is get the things installed without messing around.
Generally, this relies upon things like MacPorts and Fink, which, to be perfectly honest, are often akin to using a sledgehammer to crack a nut. Why can command-line junkies not have the same ease of installation (and more importantly deinstallation) as the rest of the Mac world?
So, I propose this: a new bundle, laid out exactly as an application bundle would be, but with a “.tools” suffix in place of “.app”. In the Contents/MacOS directory, you put everything that would ordinarily be placed in ${prefix}/bin. .dylibs could conceivably go anywhere within the bundle, but it makes a certain degree of sense to keep them inside Contents/MacOS (possibly in a subdirectory). Some install_name_tool magic, and you can run executables with no hassle, wherever you put it all (the only wrinkle might be binaries which call one another directly—not a huge amount which can be done about that without patching them to detect their own locations).
Now, there’s the problem of the path. Or rather, the $PATH. If you had just a couple of .tools bundles, you could just add their respective paths to $PATH in your .profile. But, with the aid of a simple script included in the bundle, you could have the bundle create symbolic links for itself.
All that would be needed would be a convention for there to be a script named install-tools inside the bundle (preferably within the root of the bundle itself, rather than in the Contents directory). This script would accept an optional -u (uninstall) argument, and an optional destination path, defaulting to /usr/local/bin if unspecified.
Thus, installation is as easy as dropping the bundle where you want (for example, /Users/me/Library/Tools) and running install-tools. If you want to install the symbolic links to /Users/me/bin (perhaps because you’re not an administrator), that’s absolutely fine. The only constraint upon the uninstallation part of the script is that it should check that files are symbolic links as it would create before removing them, rather than being indiscriminate.
And, because these are bundles, an application (“Tools Installer”, anyone?) could register as a handler for LaunchServices, for trivial drag-drop-double-click installation.
Thoughts?