MonoGitのソースからビルドしてインストールする手順。 本文の内容は2018年05月04日時点のバージョンに基づく。

また、ビルドに使用した環境はUbuntu 18.04 LTS 64bit、本文中に掲載している所要時間はIntel Core i5-6402Pを積んだマシンで計測したもの。

ここで紹介する手順はMono本体といくつかのアセンブリをインストールするためのもの。 ディストリビューションが提供しているバージョンのMonoと共存できるようにするため、/opt/mono/masterにインストールする。

1つの環境に複数のMonoをインストールする方法についてはParallel Mono Environments - Monoで詳しく解説されている。

ビルドにはgcc、libtool、autotools、gettext、pkg-config等が必要になるので、あらかじめインストールしておく必要がある。

libgdiplus

System.Drawing.dllなど、GDI+の機能を使用する場合のみ。 不要な場合はインストールを省略できる。

依存するパッケージのインストール

sudo apt install \
libcairo2-dev libexif-dev libfreetype6-dev libfontconfig1-dev libglib2.0-dev libjpeg-dev libpng-dev \
libtiff-dev libgif-dev libx11-dev libxrender-dev

ソースのチェックアウトとautogen、configure

git clone git://github.com/mono/libgdiplus.git
cd ./libgdiplus
./autogen.sh --prefix=/opt/mono/master/

configureの結果例。

---
Configuration summary

   * Installation prefix = /opt/mono/master
   * Cairo = 1.15.10 (system)
   * Text = cairo
   * EXIF tags = yes
   * X11 = yes
   * Codecs supported:

      - TIFF: yes
      - JPEG: yes
      - GIF: yes
      - PNG: yes

      NOTE: if any of the above say 'no' you may install the
            corresponding development packages for them, rerun
            autogen.sh to include them in the build.

---
Now type `make' to compile

ビルド、インストール

configureした結果に問題が無ければmake, make installする。

make
sudo make install

正しくインストールできたか確認する。

$ PKG_CONFIG_PATH=/opt/mono/master/lib/pkgconfig pkg-config libgdiplus --modversion
5.6

$ PKG_CONFIG_PATH=/opt/mono/master/lib/pkgconfig pkg-config libgdiplus --libs
-L/opt/mono/master/lib -L/opt/mono/master -lgdiplus -lglib-2.0 -lcairo -lfontconfig -lfreetype -ljpeg -ltiff -lgif -lpng16 -lz -lX11 -lexif -Wl,--export-dynamic -lgmodule-2.0 -pthread -lgthread-2.0 -pthread -lglib-2.0

LLVM

LLVMバックエンドを有効にする場合のみ。 不要な場合はインストールを省略できる。

ソースのチェックアウトとautogen、configure

git clone git://github.com/mono/llvm.git
cd llvm/
./configure --prefix=/opt/mono/master/ --enable-optimized

ビルド、インストール

configureした結果に問題が無ければmake, make installする。

make
sudo make install

所要時間は以下のとおり。

$ time make -j4

real	5m45.884s
user	19m49.404s
sys	0m49.328s

Mono本体(コンパイラ、クラスライブラリ)

依存するパッケージのインストール

sudo apt install \
cmake libncurses-dev

ソースのチェックアウトとautogen、configure

ここでは--with-llvmを指定することでLLVMバックエンドを有効にしてビルドする。 LLVMをインストールしていない場合、あるいはLLVMを無効にする場合は、--with-llvmを指定しない。

git clone git://github.com/mono/mono.git
cd mono
export MONO_USE_LLVM=1
./autogen.sh --prefix=/opt/mono/master/ --with-llvm=/opt/mono/master --with-libgdiplus=/opt/mono/master --with-ikvm-native=no --with-mcs-docs=no --with-x

configureの結果例。

        mcs source:    mcs
	C# Compiler:   roslyn

   Engine:
	Host:	       x86_64-pc-linux-gnu
	Target:	       x86_64-pc-linux-gnu
	GC:	       sgen (concurrent by default) and Included Boehm GC with typed GC and parallel mark
	TLS:           __thread
	SIGALTSTACK:   yes
	Engine:        Building and using the JIT
	BigArrays:     no
	DTrace:        no
	LLVM Back End: yes (dynamically loaded: no)
	Spectre:       no mitigation

   Libraries:
	.NET 4.x:        yes
	Xamarin.Android: no
	Xamarin.iOS:     no
	Xamarin.WatchOS: no
	Xamarin.TVOS:    no
	Xamarin.Mac:     no
	Windows AOT:     no
	Orbis:           no
	Unreal:          no
	WebAssembly:     no
	Test profiles:   AOT Full (no), AOT Hybrid (no)
	JNI support:     
	libgdiplus:      /opt/mono/master
	zlib:            system zlib
	BTLS:            yes (x86_64)
	jemalloc:        no (always use: no)

ビルド、インストール

準備が整ったら、make, make installする。

make
sudo make install

所要時間は以下のとおり。

$ time make -j4

real	7m49.248s
user	19m47.910s
sys	1m13.535s

Monoのビルドにはmcs(C#コンパイラ)が必要になる。 コンパイルする環境にmcsが場合は、以下のコマンドで最新のMonoLite(最小構成のmcsパッケージ)を取得することでビルドできるようになる。 ただし、通常は自動でダウンロードされるため手動で行う必要はない。

MonoLiteの取得
make get-monolite-latest

MonoLiteが入手できない場合は、以下の5つのバイナリを別の環境からコピーするなどして手動で../mcs/class/lib/monolite/に配置する。 (過去のバージョンでは有効だった手段。 現在のバージョンでも有効かどうかは未検証。)

  • mscorlib.dll
  • System.dll
  • System.Xml.dll
  • Mono.Security.dll
  • mcs.exe

動作確認

新しくMonoをインストールした場合

mono -Vでmonoが動作することを確認する。

$ mono -V
Mono JIT compiler version 5.15.0 (master/40d1ac33710 2018年  5月  4日 金曜日 16:39:48 JST)
Copyright (C) 2002-2014 Novell, Inc, Xamarin Inc and Contributors. www.mono-project.com
	TLS:           __thread
	SIGSEGV:       altstack
	Notifications: epoll
	Architecture:  amd64
	Disabled:      none
	Misc:          softdebug 
	Interpreter:   yes
	LLVM:          yes(3.6.0svn-mono-master/0b3cb8ac12c)
	GC:            sgen (concurrent by default)

既に別のバージョンのMonoが存在する環境にインストールした場合

新しく/opt/mono/masterにインストールしたMonoを参照できるように、環境変数を設定するスクリプトを用意しておく。

mono-master-env
#!/bin/bash
MONO_PREFIX=/opt/mono/master
GNOME_PREFIX=/usr
export DYLD_FALLBACK_LIBRARY_PATH=$MONO_PREFIX/lib:$DYLD_LIBRARY_FALLBACK_PATH
export LD_LIBRARY_PATH=$MONO_PREFIX/lib:$LD_LIBRARY_PATH
export C_INCLUDE_PATH=$MONO_PREFIX/include:$GNOME_PREFIX/include
export ACLOCAL_PATH=$MONO_PREFIX/share/aclocal
export PKG_CONFIG_PATH=$MONO_PREFIX/lib/pkgconfig:$GNOME_PREFIX/lib/pkgconfig
export PATH=$MONO_PREFIX/bin:$PATH

まずmono -Vで既にインストールされているmonoが動作することを確認する。

$ which mono
/usr/bin/mono

$ mono -V
Mono JIT compiler version 4.6.2 (Debian 4.6.2.7+dfsg-1ubuntu1)
Copyright (C) 2002-2014 Novell, Inc, Xamarin Inc and Contributors. www.mono-project.com
	TLS:           __thread
	SIGSEGV:       altstack
	Notifications: epoll
	Architecture:  amd64
	Disabled:      none
	Misc:          softdebug 
	LLVM:          supported, not enabled.
	GC:            sgen

続いて、先ほど用意したスクリプトを読み込んだあとでmono -Vを実行し、新しくインストールしたmonoが動作することを確認する。

$ source mono-master-env

$ which mono
/opt/mono/master/bin/mono

$ mono -V
Mono JIT compiler version 5.15.0 (master/40d1ac33710 2018年  5月  4日 金曜日 16:39:48 JST)
Copyright (C) 2002-2014 Novell, Inc, Xamarin Inc and Contributors. www.mono-project.com
	TLS:           __thread
	SIGSEGV:       altstack
	Notifications: epoll
	Architecture:  amd64
	Disabled:      none
	Misc:          softdebug 
	Interpreter:   yes
	LLVM:          yes(3.6.0svn-mono-master/0b3cb8ac12c)
	GC:            sgen (concurrent by default)

GAC

gacutil2 -lでアセンブリがGACに登録されていることを確認する。

$ gacutil2 -l 
The following assemblies are installed into the GAC:
  :
System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
System.ComponentModel.Composition, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
System.ComponentModel.DataAnnotations, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35
System.Configuration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
System.Configuration.Install, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
  :

GACのパスを明示的に指定する場合は-rootオプションで指定する。 例えばgacutil2 -l -root /opt/mono/master/lib/など)

mcs(C#コンパイラ)・mono(Monoランタイム)

mcs(C#コンパイラ)およびmono(Monoランタイム)の動作を確認する。

test.cs
using System;

class Test {
  static void Main()
  {
    Console.WriteLine(Environment.Version);
  }
}
$ mcs test.cs && mono test.exe
4.0.30319.42000

MonoのC#コンパイラであるmcsは、.NET Frameworkのcscコンパイラと同じコンパイルオプションを指定してコンパイルすることができる。 コンパイルして作成した実行可能ファイルは直接実行する代わりにmono test.exeのようにmonoコマンドを使って実行する。


LLVMバックエンドを有効にした場合の動作を確認する。 mono --llvmとすることでLLVMバックエンドを有効にした状態でmonoランタイムを実行させることができる。

$ mono -v --llvm test.exe | grep "Main"
converting llvm method void Test:Main ()
LLVM Method Test:Main () emitted at 0x400ce320 to 0x400ce33e (code length 30) [test.exe]
$ mono -v test.exe | grep "Main"
converting method void Test:Main ()
Method void Test:Main () emitted at 0x41201ee0 to 0x41201f08 (code length 40) [test.exe]

csharp(C#シェル)

csharpシェルが動作するか確認する。

$ csharp -e 'Environment.Version;'
4.0.30319.42000

$ csharp -e 'Environment.OSVersion;'
Unix 4.15.0.20

$ csharp
Mono C# Shell, type "help;" for help

Enter statements below.
csharp> Enumerable.Range(0, 10).Sum();
45
csharp> quit; 

csharpシェルでは、TABキーを押すことにより入力補間を行うことができる。 また型名などに続けてピリオドを入力すればメンバの一覧が表示される。

その他のアセンブリ・ライブラリ

mono-basic

VB.NETコンパイラやMicrosoft.VisualBasic.dllを使用する場合は、mono-basicをインストールする。

ソースのチェックアウトとautogen、configure。

git clone git://github.com/mono/mono-basic.git
cd mono-basic/
./configure --prefix=/opt/mono/master/

configureの結果例。

mono-basic 4.7 module configured to use prefix=/opt/mono/master/

問題が無ければ、make, make installする。

make
sudo make install

vbnc2(VB.NETコンパイラ)の動作を確認する。

test.vb
Imports System

Module Test
  Sub Main()
    Console.WriteLine("Hello, world!")
  End Sub
End Module
$ vbnc2 test.vb && mono test.exe
Visual Basic.Net Compiler version 0.0.0.5943 (Mono 4.7 - master/cb83ba59)
Copyright (C) 2004-2010 Rolf Bjarne Kvinge. All rights reserved.

Assembly 'test, Version=0.0, Culture=neutral, PublicKeyToken=null' saved successfully to '/home/smdn/test.exe'.
Compilation successful
Compilation took 00:00:00.5617000
WARNING: The runtime version supported by this application is unavailable.
Using default runtime: v4.0.30319
Hello, world!

MSBuild (mono/msbuild)

ビルドツールにMSBuildを使用する場合は、mono/msbuildをインストールする。

現時点ではMonoに同梱されるMSBuild互換のxbuildを使うこともできるが、将来的にはMSBuildに置き換えられる予定となっている。

ソースのチェックアウト。

git clone git://github.com/mono/msbuild.git
cd msbuild/

現在のブランチがxplat-masterになっていることを確認する。 (デフォルトでxplat-masterとなっているはず)

$ git branch
* xplat-master

makeする。 インストールパスの設定等はこの後の手順で行うことができる。

$ make
./build.sh -host mono -configuration Release -skipTests
Executed from ./build.sh with arguments: -build -host mono -configuration Release -skipTests
** Downloading MSBUILD from https://github.com/mono/msbuild/releases/download/0.06/mono_msbuild_xplat-master-3c930fa8.zip
  :
  :

ビルド中に適宜NuGetパッケージなどのダウンロードが行われるため、時間がかかる場合がある。

ビルド中にLibGit2SharpがTypeInitializationExceptionをスローしてビルドに失敗する場合の対処法について: §.LibGit2SharpがTypeInitializationExceptionをスローする


インストールするにはmake installではなく、インストール用のスクリプトinstall-mono-prefix.shを用いる。 引数でインストール先のパスを指定することができる。 (ここでは/opt/mono/master/にインストールしている)

$ sudo ./install-mono-prefix.sh /opt/mono/master/
Microsoft (R) Build Engine version 15.6.0.0 ( Thu May 10 14:00:26 UTC 2018) for Mono
Copyright (C) Microsoft Corporation. All rights reserved.

  :
  :
  (中略)
  :
  :

Build succeeded.

Time Elapsed 00:00:01.25

動作を確認する。

$ msbuild /version
Mono 向け Microsoft (R) Build Engine バージョン 15.8.47.42569 ( Thu Jun 21 21:36:02 JST 2018)
Copyright (C) Microsoft Corporation.All rights reserved.

15.8.47.42569


$ cat hello.msbuild.xml 
<Project DefaultTargets="Build">
  <Target Name="Build">
    <Message Text="Hello, world!"/>
  </Target>
</Project>


$ msbuild hello.msbuild.xml 
Mono 向け Microsoft (R) Build Engine バージョン 15.8.47.42569 ( Thu Jun 21 21:36:02 JST 2018)
Copyright (C) Microsoft Corporation.All rights reserved.

2018/06/22 20:40:17 にビルドを開始しました。
ノード 1 上のプロジェクト "/home/smdn/hello.msbuild.xml" (既定のターゲット)。
Build:
  Hello, world!
プロジェクト "/home/smdn/hello.msbuild.xml" (既定のターゲット) のビルドが完了しました。

ビルドに成功しました。
    0 個の警告
    0 エラー

経過時間 00:00:00.26

トラブルシューティング

System.Drawing.dllがTypeInitializationExceptionをスローする

以下のようにSystem.Drawing.dllのメンバを参照しようとした際にTypeInitializationExceptionがスローされる場合の対処について。

$ cat test.cs
using System;

class Test {
  static void Main()
  {
    (new System.Drawing.Bitmap(1, 1)).Dispose();
  }
}

$ mcs test.cs -r:System.Drawing.dll && mono test.exe

Unhandled Exception:
System.TypeInitializationException: The type initializer for 'System.Drawing.GDIPlus' threw an exception. ---> System.DllNotFoundException: /opt/mono/master/
  at (wrapper managed-to-native) System.Drawing.GDIPlus:GdiplusStartup (ulong&,System.Drawing.GdiplusStartupInput&,System.Drawing.GdiplusStartupOutput&)
  at System.Drawing.GDIPlus..cctor () [0x000cc] in <1917aa1c39d94b1a91807b8cd9f03350>:0 
   --- End of inner exception stack trace ---
  at System.Drawing.Bitmap..ctor (System.String filename, System.Boolean useIcm) [0x0002b] in <1917aa1c39d94b1a91807b8cd9f03350>:0 
  at System.Drawing.Bitmap..ctor (System.String filename) [0x00000] in <1917aa1c39d94b1a91807b8cd9f03350>:0 
  at (wrapper remoting-invoke-with-check) System.Drawing.Bitmap:.ctor (string)
  at Test.Main () [0x00000] in <8d1ccbab6ffd4bc3b78e43e6e0f0b3a5>:0 

上記のようにTypeInitializationExceptionがスローされ、さらにその原因として<prefix>が見つからずにDllNotFoundExceptionがスローされている場合は、libgdiplus.soのパス解決に失敗している。

この場合、<prefix>/etc/mono/configを以下のように修正する。 (ここで、<prefix>configure--prefixオプションで指定したインストール先のパス。 ここでは/opt/mono/master。)

<prefix>/etc/mono/config
@@ -29,8 +29,8 @@
 		<dllentry dll="__Internal" name="MoveMemory" target="mono_win32_compat_MoveMemory"/>
 		<dllentry dll="__Internal" name="ZeroMemory" target="mono_win32_compat_ZeroMemory"/>
 	</dllmap>
-	<dllmap dll="gdiplus" target="/opt/mono/master/" os="!windows"/>
-	<dllmap dll="gdiplus.dll" target="/opt/mono/master/"  os="!windows"/>
-	<dllmap dll="gdi32" target="/opt/mono/master/" os="!windows"/>
-	<dllmap dll="gdi32.dll" target="/opt/mono/master/" os="!windows"/>
+	<dllmap dll="gdiplus" target="/opt/mono/master/lib/libgdiplus.so" os="!windows"/>
+	<dllmap dll="gdiplus.dll" target="/opt/mono/master/lib/libgdiplus.so"  os="!windows"/>
+	<dllmap dll="gdi32" target="/opt/mono/master/lib/libgdiplus.so" os="!windows"/>
+	<dllmap dll="gdi32.dll" target="/opt/mono/master/lib/libgdiplus.so" os="!windows"/>
 </configuration>

インストール先の<prefix>/etc/mono/configを編集できない場合は、/home/user/.mono/configに同様のファイルを配置してそこに記述することもできる。

LibGit2SharpがTypeInitializationExceptionをスローする

MSBuildのインストール中などにおいて、以下のようにLibGit2SharpTypeInitializationExceptionをスローして実行で失敗する場合の対処について。

LibGit2SharpがTypeInitializationExceptionをスローする
[ERROR] FATAL UNHANDLED EXCEPTION: System.TypeInitializationException: The type initializer for 'LibGit2Sharp.Core.NativeMethods' threw an exception. ---> System.DllNotFoundException: lib/linux/x86_64/libgit2-1196807.so
  at (wrapper managed-to-native) LibGit2Sharp.Core.NativeMethods.git_libgit2_init()
  at LibGit2Sharp.Core.NativeMethods+LibraryLifetimeObject..ctor () [0x00006] in <48079e5da5364f5db01fd1de5fb12b0d>:0 
  at LibGit2Sharp.Core.NativeMethods..cctor () [0x00054] in <48079e5da5364f5db01fd1de5fb12b0d>:0 
   --- End of inner exception stack trace ---
  at LibGit2Sharp.Core.NativeMethods+LibraryLifetimeObject.Finalize () [0x00000] in <48079e5da5364f5db01fd1de5fb12b0d>:0 
Failed to run MSBuild: /srv/export/volatile/build/mono/master/msbuild/build/../artifacts/mono-msbuild/msbuild "/home/smdn/.nuget/packages/roslyntools.repotoolset/1.0.0-beta-62705-01/tools/Build.proj" /m /clp:Summary /v:minimal /p:Configuration=Release-MONO /p:SolutionPath="/srv/export/volatile/build/mono/master/msbuild/build/../MSBuild.sln" /p:CIBuild=false /p:DisableNerdbankVersioning=false /bl:"/srv/export/volatile/build/mono/master/msbuild/build/../artifacts/Release-MONO/log/Build.binlog" /p:Restore=true /p:Build=true /p:Rebuild=false /p:Test=false /p:Sign=false /p:Pack=false /p:CreateBootstrap=true

この場合ではlib/linux/x86_64/libgit2-1196807.soが見つからずにDllNotFoundExceptionが発生している。 バージョン1.0.210のLibGit2Sharp.NativeBinariesのNuGetパッケージにはこのファイルが含まれているが、相対パスの解決に失敗する(?)ためにDllNotFoundExceptionとなっている模様。

対処として、libgit2を別途インストールし、それに含まれる.soファイルをフルパスで参照するように変更する。


まず、libgit2をインストールする。

sudo apt install libgit2

次に、LibGit2Sharp.dllの構成ファイルを探す。

find ~/.nuget/ -name "LibGit2Sharp.dll.config"

見つかった構成ファイルを編集し、dllmaptargetをインストールしたlibgit2のものに書き換える。

LibGit2Sharp.dll.config
 <configuration>
-    <dllmap os="linux" cpu="x86-64" wordsize="64" dll="git2-1196807" target="lib/linux/x86_64/libgit2-1196807.so" />
+    <dllmap os="linux" cpu="x86-64" wordsize="64" dll="git2-1196807" target="/usr/lib/x86_64-linux-gnu/libgit2.so.26" />
     <dllmap os="osx" cpu="x86,x86-64" dll="git2-1196807" target="lib/osx/libgit2-1196807.dylib" />
 </configuration>

/usr/libではなく~/.nuget/配下にインストールされている.soファイルのフルパスに変更しても動作すると思われるが、未検証。