MonoをGitのソースからビルドしてインストールする手順。 本文の内容は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パッケージ)を取得することでビルドできるようになる。 ただし、通常は自動でダウンロードされるため手動で行う必要はない。
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を参照できるように、環境変数を設定するスクリプトを用意しておく。
#!/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ランタイム)の動作を確認する。
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コンパイラ)の動作を確認する。
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
。)
@@ -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のインストール中などにおいて、以下のように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"
見つかった構成ファイルを編集し、dllmap
のtarget
をインストールしたlibgit2
のものに書き換える。
<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ファイルのフルパスに変更しても動作すると思われるが、未検証。