Mono

Mono

Mono is an open-source and cross-platform implementation of the .NET Framework. Wine can use a Windows build of Mono to run .NET applications.

For Wine releases 1.5.3 and later, the Wine Mono package is recommended. For earlier versions, an official Windows release of Mono 2.10 is recommended.

I'm expecting that Wine 1.5.6 will install Wine Mono automatically as needed. It will search for the MSI in the following locations:

  • The Unix directory stored in the "MonoCabDir" value at HKCU\Software\Wine\Dotnet.

  • /usr/share/wine/mono, or possibly some substitution for /usr if Wine was installed to a different location.
  • wine_build_directory/../mono, if Wine is being run from a build tree.
  • Download from http://source.winehq.org/winemono.php?v=0.0.4

Unlike gecko, there is only one package containing the code for both x86 and x86_64, as most of the code does not depend on the architecture.

The Mono package should always be removed before installing native .NET. This can be done with the following command-line:

$ wine uninstaller --remove '{E45D8920-A758-4088-B6C6-31DBB276992E}'

For build instructions, see the readme at https://github.com/madewokherd/wine-mono

Debugging

As of version 1.1.42 and Mono 2.6, the WINE_MONO_TRACE environment variable may be set as follows to trace calls within Mono:

    all                  All assemblies
    none                 No assemblies
    program              Entry point assembly
    assembly             Specifies an assembly
    M:Type:Method        Specifies a method
    N:Namespace          Specifies a namespace
    T:Type               Specifies a type
    EXPR                 Includes expression
    -EXPR                Excludes expression
    EXPR,EXPR            Multiple expressions
    disabled             Don't print any output until toggled via SIGUSR2

This option is the same as the --trace option in mono, and you can see it by running "mono --help-trace".

Note that "All assemblies" includes the program itself and all libraries shipped with it. Mono is capable of tracing any .NET code. You probably should avoid the "all" trace if there might be proprietary code running in the process.

Activating any trace at all, even a bogus assembly name, will cause Mono to print out all exceptions as they occur. This can be useful, but it can also be misleading as some exceptions are perfectly normal.

In earlier versions of Wine, the "MONO_TRACE" environment variable may work.

If you see "Stacktrace:" in the console, this means that Mono has crashed. To debug, set MONO_DEBUG=suspend-on-sigsegv. You will then see "Received SIGSEGV, suspending..." after the crash, and you can attach winedbg to the process.

Documentation

Standard .NET namespaces and classes are documented at MSDN here: http://msdn.microsoft.com/en-us/library/w0x726c2.aspx

Runtime detection

As of 1.3.7, Wine will search for a Windows install of Mono in the following locations:

  • c:\windows\mono\mono-1.0 or mono-2.0
  • If Wine is installed, <prefix>/share/wine/mono/mono-1.0 or mono-2.0, where <prefix> is usually /usr or /usr/local.

  • If Wine is run from a build tree, wine/../mono/mono-1.0 or mono-2.0
  • The path specified in the registry, if Mono was installed via the official Windows installer.

The Wine Mono package installs its files in c:\windows\mono\mono-2.0. In modern Wine (>= 1.5.6), without Wine Mono installed it will appear to Windows applications that .NET is not installed, so the only real option is to use that package.

It's possible that Mono 2.6 will still work for .NET 1.x applications, but in the long term we should try to remove the need for this.

Cross-Compiling Mono 2.10 and earlier for Wine

For modern (2.11 and later) Mono versions, you should be using the Wine Mono package instead. The only reason to use older Mono is if you are using Wine older than 1.5.3 or want to use Mono 2.6 for .NET 1.x code.

See also http://www.mono-project.com/Compiling_Mono, especially http://www.mono-project.com/Cross-compiling_Mono_for_Windows

You will need the mono source code for this. You should use mono from the mono-2-8 branch on git. You'll probably want build-essential, and at least these packages (on Debian/Ubuntu, other distributions may have different package names):

autoconf automake mono-mcs

To get the needed dependencies, use:

#!/bin/sh
# Copyright 2010 Austin English
# LGPL 2.1
# Sets up dependencies needed to cross compile mono.
# See http://www.mono-project.com/Cross-compiling_Mono_for_Windows
# and http://wiki.winehq.org/Mono
# You'll need to run it as root/sudo, since you likely don't have write access to /usr
# If you're not on Ubuntu, you may need to change the MONOCROSS variable below.
set -ex
if [ ! -w /usr/ ]
then
    echo "You must run $0 as root/sudo"
    exit 1
fi

MONOCACHE="$HOME/.monocache"
MONOCROSS="/usr/i586-mingw32msvc"
olddir="`pwd`"
download() {
    file=`basename "$1"`
    mkdir -p "$MONOCACHE"
    if [ ! -f "$MONOCACHE/$file" ]
    then
        cd "$MONOCACHE"
        wget -O "$file" "$1"
        cd "$olddir"
    fi
}
download http://heanet.dl.sourceforge.net/sourceforge/gnuwin32/libjpeg-6b-bin.zip
download http://heanet.dl.sourceforge.net/sourceforge/gnuwin32/libjpeg-6b-lib.zip
download http://heanet.dl.sourceforge.net/sourceforge/gnuwin32/giflib-4.1.4-bin.zip
download http://heanet.dl.sourceforge.net/sourceforge/gnuwin32/giflib-4.1.4-lib.zip
download http://heanet.dl.sourceforge.net/sourceforge/gnuwin32/libiconv-1.9.2-1-bin.zip
download http://heanet.dl.sourceforge.net/sourceforge/gnuwin32/libiconv-1.9.2-1-lib.zip
download http://ftp.gnome.org/pub/gnome/binaries/win32/dependencies/expat-2.0.0.zip
download http://ftp.gnome.org/pub/gnome/binaries/win32/dependencies/fontconfig_2.8.0-2_win32.zip
download http://ftp.gnome.org/pub/gnome/binaries/win32/dependencies/fontconfig-dev_2.8.0-2_win32.zip
download http://ftp.gnome.org/pub/gnome/binaries/win32/dependencies/freetype_2.3.11-2_win32.zip
download http://ftp.gnome.org/pub/gnome/binaries/win32/dependencies/freetype-dev_2.3.11-2_win32.zip
download http://ftp.gnome.org/pub/gnome/binaries/win32/dependencies/gettext-runtime-0.17-1.zip
download http://ftp.gnome.org/pub/gnome/binaries/win32/dependencies/gettext-runtime-dev-0.17-1.zip
download http://ftp.gnome.org/pub/gnome/binaries/win32/dependencies/libpng_1.2.40-1_win32.zip
download http://ftp.gnome.org/pub/gnome/binaries/win32/dependencies/libpng-dev_1.2.40-1_win32.zip
download http://ftp.gnome.org/pub/gnome/binaries/win32/dependencies/libtiff-dev-3.8.2.zip
download http://ftp.gnome.org/pub/gnome/binaries/win32/dependencies/pkg-config_0.23-3_win32.zip
download http://ftp.gnome.org/pub/gnome/binaries/win32/dependencies/proxy-libintl_20100902_win32.zip
download http://ftp.gnome.org/pub/gnome/binaries/win32/glib/2.16/glib-2.16.5.zip
download http://ftp.gnome.org/pub/gnome/binaries/win32/glib/2.16/glib-dev-2.16.5.zip
# Setup the dependencies
cd $MONOCROSS
for pkg in $MONOCACHE/*.zip
do
    unzip -o $pkg
done

# Fix dos line endings
sed 's/.$//' -i lib/libiconv.la

To keep the process consistent, we're storing a build script in winezeug (build-winemono.sh), rather than using the included build-mingw32.sh, which is broken on some versions. It should build any version >= 2.6, from either git or a source tarball. Start by using the above script to install the needed dependencies, then do:

$ git clone git://github.com/mono/mono.git
$ cd mono
$ git checkout origin/mono-2-8
# adjust the mingw values if they are different on your distribution
$ wget http://winezeug.googlecode.com/svn/trunk/mono/build-winemono.sh
$ chmod +x build-winemono.sh
$ ./build-winemono.sh -d /usr/i586-mingw32msvc -m i586-mingw32msvc

Warning: If you have $CC set in your environment, unset it, since it will conflict.

This produces a .tar.gz file containing a build of mono and its dependencies.

To update later:

$ cd mono
$ git fetch
$ git checkout origin/mono-2-8

Cross-compiling on fedora

To build on fedora, edit ./build-mingw32.sh to make CROSS_DLL_DIR="$CROSS_DIR/bin" and CROSS_PKG_CONFIG_DIR=$CROSS_DIR/lib/pkgconfig and run it as:

./build-mingw32.sh -d /usr/i686-pc-mingw32/sys-root/mingw -m i686-pc-mingw32

Many of the build dependencies are available as rpm mingw32-* packages. Here is a partial list of what's is available/necessary:

mingw32-binutils
mingw32-cpp
mingw32-expat
mingw32-filesystem
mingw32-fontconfig
mingw32-freetype
mingw32-gcc
mingw32-gettext
mingw32-glib2
mingw32-glib2-static
mingw32-libjpeg
mingw32-libjpeg-static
mingw32-libpng
mingw32-runtime
mingw32-w32api

Be warned that cross-compiling under fedora by default linked dynamically to the mingw32 dll's, so one may need to copy some dlls such as libgcc_s_sjlj-1.dll from under /usr/i686-pc-mingw32/sys-root/mingw for the resulting binary to run.

Using Custom Mono Builds in old Wine

To use a custom build of Mono in Wine version 1.3.3 or earlier, you must set the following registry values:

HKEY_LOCAL_MACHINE\Software\Novell\Mono\DefaultCLR = "custom"
HKEY_LOCAL_MACHINE\Software\Novell\Mono\custom\SdkInstallRoot = "z:\path\to\mono\root"

The "root" directory contains bin, lib, and etc directories.

Test Suite

See http://www.mono-project.com/Testing first.

Running the Mono test suite on Wine is very important for fixing bugs (in Mono and in Wine), and I suspect that MS .NET hosted in Wine will also benefit from some of the fixes made for the Mono tests.

You would normally run 'make run-test' to run the tests. You can force the test suite to run with a different mono binary by setting the RUNTIME variable. To do this properly with a cross-built mono.exe, I had to write a wrapper script:

   1 #!/usr/bin/env python
   2 import os
   3 import sys
   4 import subprocess
   5 unix_mono_prefix = os.environ['MONO_WINE_DIR']
   6 def unix_to_windows_path(path):
   7     popen = subprocess.Popen(['wine', 'winepath', '--windows', path], stdout=subprocess.PIPE)
   8     stdout, stderr = popen.communicate()
   9     popen.wait()
  10     return stdout.rstrip('\n')
  11 windows_mono_prefix = unix_to_windows_path(unix_mono_prefix)
  12 #work-around for http://bugs.winehq.org/show_bug.cgi?id=22168
  13 if 'GNOME_DESKTOP_SESSION_ID' in os.environ: del os.environ['GNOME_DESKTOP_SESSION_ID']
  14 if 'DESKTOP_SESSION' in os.environ: del os.environ['DESKTOP_SESSION']
  15 os.environ['MONO_PREFIX'] = windows_mono_prefix
  16 mono_paths = []
  17 for path in os.environ.get('MONO_PATH', '').split(':'):
  18     mono_paths.append(unix_to_windows_path(path))
  19 os.environ['MONO_PATH'] = ';'.join(mono_paths)
  20 popen = subprocess.Popen(['wine', windows_mono_prefix+'\\bin\\mono.exe'] + sys.argv[1:])
  21 sys.exit(popen.wait())

To invoke the tests with this wrapper, I ran them this way:

$ MONO_WINE_DIR=path/to/mono/mono-win32/mono-2.6.3-branches-2-6-r154484/ make -k RUNTIME=path/to/wine-mono-wrapper run-test &>test-summary.txt

The tests hang at the end when invoked this way for some reason.

Mono (last edited 2012-05-21 14:20:35 by VincentPovirk)