Protip: parallel-installing Mono versions in an APT-happy way

If you’ve ever gotten tired of waiting for a new Mono release to appear, and taken matters into your own hands by compiling your own copy of Mono, you’ve likely faced the problem of “missing” libraries. “That’s weird, it says it can’t find gtk-sharp, but I have that package!”

This happens because every version of Mono on your system has what’s called a Global Assembly Cache – a location where all system-wide assemblies lives. So when you run an app like Tomboy, it loads its libraries such as GTK# from the GAC belonging to the Mono runtime being used. Ordinarily, this is in /usr/lib/mono/gac on a Debian/Ubuntu system.

When you have your parallel Mono, it doesn’t share a GAC – as a result, libraries in your main distro GAC are not available in your DIY GAC, as they were never registered in there.

Typically, the advice is to either start compiling every lib you need into a non-standard place too – however, here’s a better idea. Why not make Apt take care of not only your system’s GAC – but additional GACs too? We actually have structures in place to handle this, so it’s not as hard as you think (merely relatively unknown). This guide does NOT take startup scripts into account – it’s your problem to ensure you’re using the correct “mono” command to run your copy of MonoDevelop or Tomboy or whatever. You should probably learn about update-alternatives and $PATH for this. Oh, and this guide will BREAK HORRIBLY if you try to uninstall system mono completely. Don’t try it.

Setup step 1: preparation

Don’t install parallel Mono into /usr/local. I don’t care what happens to you if you do. Use some random folder in /opt, usually a per-build prefix like /opt/mono-2.10

Setup step 2: duplicating existing magic

Open a terminal, and copy /usr/share/cli-common/runtimes.d/mono to a new filename, e.g. /usr/share/cli-common/runtimes.d/mono-2.10

Setup step 3: tweak duplicate magic

Open your copied file in an editor, and change the name value on line 27ish (e.g. from “Monon” to “Mono (parallel 2.10 install)n”). Then change the two places in the file, on lines 64ish and 120ish, from “/usr/bin/gacutil” to “/opt/mono-2.8.2/bin/gacutil” or equivalent.

Setup step 4: apply magic to existing packages

Run “/usr/share/cli-common/gac-install mono-2.10” (or whatever filename you picked for your runtimes.d entry) as root. This will instantiate your parallel GAC(s).

From now on, every GAC library you install or uninstall will happen to every single runtime in runtimes.d.

To go back to how things were before, with only a single Mono runtime:

Uninstall step 1: empty out parallel GAC

Run “/usr/share/cli-common/gac-remove mono-2.10” (or whatever filename you picked for your runtimes.d entry) as root. This will remove all packaged entried from your parallel GAC(s).

Uninstall step 2: remove magic

Delete your file from runtimes.d

4 Responses to “Protip: parallel-installing Mono versions in an APT-happy way”

  1. Silly question, but why not just use MONO_GAC_PREFIX?

    export MONO_GAC_PREFIX=/opt/mono-2-10:/usr

    This will cause mono to look in /opt/mono-2-10/lib/mono/gac, and if the assembly can’t be found, fallback to using /usr/lib/mono/gac.

    I use this for my parallel installs, and it’s been working for years.

  2. I’m generally uneasy about using MONO_GAC_PREFIX for this, since there are bits of Mono itself in there. THis method only touches things like GTK#, not mscorlib

  3. @directhex, mscorlib.dll isn’t in the GAC, it’s in the per-profile directory, e.g. /opt/mono-2-10/lib/mono/2.0/mscorlib.dll. It’s not a problem. Other assemblies included with Mono (e.g. System.dll) will be in the GAC, but since we place the “parallel” mono first in $MONO_GAC_PREFIX, they should be found first, and thus there shouldn’t be a problem.

    Again, I’ve been using MONO_GAC_PREFIX for years, and don’t recall having any issues with it.

  4. Have you considered proposing this or a likely implementation for the GAC runtime to the Mono maintainers? We (Debian) did something similar to emacs(en) with emacs23/22 and the other ones.
    u.-alt. is awesome for this o/

Leave a Reply