Switching Finks
One of the open-source projects I contribute to is
Fink, a package manager for OS X; if you've
used apt-get
or yum
on Linux, it provides a similar facility,
allowing you to install, say, GnuPG by running fink install gnupg
.
It installs things into its own directory tree, rooted at /sw
by
default, to avoid interfering with things shipped by Apple (/
,
/usr
) or manually installed by the user (/usr/local
.) That is, if
you have Fink installed, your system will have /sw/bin
, /sw/lib
,
/sw/etc
, /sw/share/man
, &c.
So that you can run things installed in these nonstandard locations,
Fink provides some shell commands in /sw/bin/init.sh
which edit
environment variables like PATH
and MANPATH
to include the /sw/*
directories. Most Fink users have . /sw/bin/init.sh
in their
~/.profile
, so these commands will be invoked when their shell
starts.
Having my shell automatically pull in Fink at startup doesn't work for me, though. It's important to me to have a clean environment available. For instance, when I'm contributing to non-Fink open-source projects, trying to help someone who doesn't have Fink installed troubleshoot something, or submitting a bug report for a program that interacts with other programs where I have the Fink version installed, but Apple ships a different version with the system. (Note that this is only an issue if program A interacts with program B by invoking it as a standalone process without using an absolute path.)
Also, as a Fink developer, I actually have multiple Fink
installations at different paths, and I only want one loaded at a
time; I don't want to activate /Volumes/SandBox/fink/dev-sw
in an
environment where /Volumes/SandBox/fink/sw
has already been pulled
in!
It's much easier to pull Fink stuff in later when I
need it than to undo the changes that /sw/bin/init.sh
makes to my
environment. My solution for making it easy to activate a particular Fink installation was to add the following to ~/.bashrc
:
if [ -n "$SW" ]
then export CFLAGS="-I$SW/include"
export LDFLAGS="-L$SW/lib"
export CXXFLAGS="$CFLAGS"
export CPPFLAGS="$CXXFLAGS"
export ACLOCAL_FLAGS="-I \"$SW/share/aclocal\""
export PKG_CONFIG_PATH="$SW/lib/pkgconfig"
export PS1="[$SW_DISPNAME \\W@$(hostname -s)]\\\$ "
. "$SW/bin/init.sh"
export PATH=~/bin:"$PATH"
fi
What this does is arranges it so that if I start a new shell with SW
and SW_DISPNAME
set, it'll pull in the Fink installation rooted at
the directory $SW
and put $SW_DISPNAME
in my shell prompt so that
I can see which environment I'm using. The extra environment
variables before . $SW/bin/init.sh
set things up so that if I
compile things by hand, they'll find and link against Fink-installed
libraries; the PATH
setting at the end is because init.sh
places
the Fink bin directory at the front of the PATH
, and I want my
personal bin directory to come before it.
I run the following script (saved as ~/bin/finkinit
) when I want to
pull in Fink:
#!/bin/bash FINK=${1:-main} case "$FINK" in main) SW=/Volumes/SandBox/fink/sw SW_DISPNAME="fink" ;; dev) SW=/Volumes/SandBox/fink/dev-sw SW_DISPNAME="fink-dev" ;; *) echo "Unknown fink install '$FINK'" >&2 ; exit 1 esac export SW SW_DISPNAME exec /bin/bash
This gives me a subshell with Fink turned on, which I can exit out of
when I want to return to a clean environment. If I run it as finkinit
, I get my main Fink installation, or I can run finkinit dev
to get an alternate Fink.