在 Windows 上编译 Mono 3.8/3.10
1、安装预编译的Mono
下载一个稳定的,并且编译完成的 Mono 3.2.3 的版本。安装它:http://download.mono-project.com/archive/3.2.3/windows-installer/mono-3.2.3-gtksharp-2.12.11-win32-0.exe
从开始栏打开 Mono 命令提示,之后用一下命令检查它是否正常运行着:
mono --version
你将会看到以下信息出现,3.2.3版本出现:
C:\Program Files (x86)\Mono-3.2.3>mono --version
Mono JIT compiler version 2.10.9 (tarball)
Copyright (C) 2002-2011 Novell, Inc, Xamarin, Inc and Contributors. www.mono-project.com
TLS: normal
SIGSEGV: normal
Notification: Thread + polling
Architecture: x86
Disabled: none
Misc: softdebug
LLVM: supported, not enabled.
GC: Included Boehm (with typed GC and Parallel Mark)
C:\Program Files (x86)\Mono-3.2.3>
2、安装 Cygwin
下载并按照32位的 Cygwin, 它可以在 Windows 下运行 UNIX 命令行的工具集。我们要使用它来构建 Mono。我们从这里下载:http://cygwin.com/setup-x86.exe
在安装过程中,你将会提示到用到必须的包,你必须手动指定。我们创建Mono所需要的包并没有在默认安装设置里,所以我们要手动选择他们。
在 Mono on Windows 教程里提到了很多关于包的细节,这些包应该是:
autoconf
automake
bison
gcc-core
gcc-g++
libtoolmakemingw-runtime
python
vim
在 Final Battle Instructions 说提到了这些包,我们最好要安装:
gettext-devel
gettext
intltool
libiconv
pkg-config
还有,这些包我们最好也要安装:
wget
zip patch
openssh
vim
3、配置 Cygwin 的 noacl 选项
有人通过 mono-dev 的邮件列表向我建议说,Cygwin 应该可以通过配置 "noacl" 选项来挂载系统的宿主系统的磁盘驱动器,否则的话,进行文件访问的时候可能会出问题。你可以看这里了解详情:http://lists.ximian.com/pipermail/mono-devel-list/2014-May/041458.html
从开始菜单中打开 Cygwin 命令行,编辑 /etc/fstab 文件,并按照下面的指示操作:
# For a description of the file format, see the Users Guide
# http://cygwin.com/cygwin-ug-net/using.html#mount-table
# This is default anyway:
none /cygdrive cygdrive binary,posix=0,user 0 0
把 noacl 选项添加进去,如下所示:
# For a description of the file format, see the Users Guide
# http://cygwin.com/cygwin-ug-net/using.html#mount-table
# This is default anyway:
none /cygdrive cygdrive binary,noacl,posix=0,user 0 0
你可能需要关掉 Cygwin 命令行 ,重新打开它来确保使刚才的修改生效。你可以通过运行 mount 命令看一下 noacl 是否在其输出的内容里面,以便检查配置是否生效。
1、获取 Mono 发行包
当我写这篇文章的时候,Mono的最新发布版本是3.8.0。在Windows下,还没有该版本的安装包,最新的安装包是3.2.3。我们要在这里构建一个3.8.0版本的二进制包。
你可以从 Mono 的官网获取 3.8.0 的源代码,并把它解压到你的磁盘上。
你需要使用 Cygwin 程序来下载和解压源码。你也可以不在 Cygwin 里做,但是,这样会出现换行符(CRLF)被修改掉了,这会导致编译失败。
所以打开 Cygwin 命令行。
$ cd /cygdrive/c $ mkdir monosources$ cd monosources
$ wget http://download.mono-project.com/sources/mono/mono-3.8.0.tar.bz2
$ tar xjvf mono-3.4.0.tar.bz2
注意:将你的源码放到一个相关的短路径,否则你就会因为 Windows 的 MAX_PATH 限制出问题(感谢 mpderbec)。同样,有人反馈说在 Windows 的用户文件夹中包含一个空格也会出错。
2、修复一个 Mono 3.10 的已知问题
Mono 3.10.0 版本,发布于2014年10月17日,会发生这个错误:
libtool: compile: i686-pc-mingw32-gcc -DHAVE_CONFIG_H -I. -I../..
-I../.. -I../../mono -I../../libgc/include -I../../eglib/src
-I../../eglib/src -DWINVER=0x0502 -D_WIN32_WINNT=0x0502
-D_WIN32_IE=0x0501 -D_UNICODE -DUNICODE -DWIN32_THREADS
-DFD_SETSIZE=1024 -g -O2 -fno-strict-aliasing -fwrapv
-Wdeclaration-after-statement -Wno-unused-but-set-variable -g -Wall
-Wunused -Wmissing-prototypes -Wmissing-declarations -Wstrict-prototypes
-Wmissing-prototypes -Wnested-externs -Wpointer-arith -Wno-cast-qual
-Wwrite-strings -Wno-switch -Wno-switch-enum -Wno-unused-value
-mno-tls-direct-seg-refs -Werror-implicit-function-declaration -MT
sha1.lo -MD -MP -MF .deps/sha1.Tpo -c sha1.c -DDLL_EXPORT -DPIC -o
.libs/sha1.o
In file included from sha1.c:20:0:
./sha1.h:25:1: error: expected '=', ',', ';', 'asm' or '__attribute__'
我们需要修改 mono/utils/sha1.h 来修复这个问题。
Edit the file to change __BEGIN_DECLS to G_BEGIN_DECLS and _END_DECLS to G_END_DECLS
这个文件的 __BEGIN_DECLS 改为 G_BEGIN_DECLS
还有 _END_DECLS 改为 G_END_DECLS
更改后的这一部分为:
G_BEGIN_DECLS
void SHA1Init(SHA1_CTX *);
void SHA1Pad(SHA1_CTX *);
void SHA1Transform(guint32 [5], const guint8 [SHA1_BLOCK_LENGTH]);
void SHA1Update(SHA1_CTX *, const guint8 *, size_t);
void SHA1Final(guint8 [SHA1_DIGEST_LENGTH], SHA1_CTX *);
char *SHA1End(SHA1_CTX *, char *);
char *SHA1File(const char *, char *);
char *SHA1FileChunk(const char *, char *, off_t, off_t);
char *SHA1Data(const guint8 *, size_t, char *);
G_END_DECLS
3、从Mono发布的压缩包中编译
注意:这些步骤适用于 3.8.0,同样适用于 3.10.0,即使 3.10.0 发布时带有一个编译出错的 Windows 编译。
构建Mono的时候可能会出现一些错误,如文件丢失,或者和 Cygwin 的头文件冲突等。如果出现错误,我们可以按照说明来修正错误,但是我们现在要做的是开始构建Mono,看看我们能走到哪一步。
$ cd /cygdrive/c
$ mkdir monoinstall
$ cd monosources/mono-3.8.0
$ ./autogen.sh --prefix="C:\monoinstall" --with-preview=yes
注意:我们给 --prefix 指定的是 Win32 样式的路径,而不是 Cygwin 或 Unix 样式的路径。
Autogen应该顺利的完成,接下来我们就要配置编译命令了,如 autogen 推荐的那样:
$ ./configure --host=i686-pc-mingw32
在配置进程结束的时候,我们能够看到这样的一些输出:
mcs source: mcs
Engine:
Host: i686-pc-mingw32
Target: i686-pc-mingw32
GC: sgen and Included Boehm GC with typed GC and parallel mark
TLS: pthread
SIGALTSTACK: no
Engine: Building and using the JIT
oprofile: no
BigArrays: no
DTrace: no
LLVM Back End: no (dynamically loaded: no)
Libraries:
.NET 2.0/3.5: yes
.NET 4.0: yes
.NET 4.5: yes
MonoDroid: no
MonoTouch: no
Xamarin.Mac: no
JNI support: no
libgdiplus: assumed to be installed
zlib:
一旦设置成功,我们可以开始用这个命令编译:
$ make
4、安装 Mono 文件
等到编译成功,你就可以将它安装到指定的目录了。
首先,我们需要先在 Cygwin 中挂载目标文件夹:
$ mount "C:\monoinstall" /usr/local
注意:我注意到如果在编译之前就挂载目标文件夹,会得到一个和 libiconv 相关的错误。这可能和 'noacl' 有关系。所以,我建议等到编译结束并且准备去安装的时候再去挂载目标文件夹。
5、修复:安装错误 - mono.exe
某种原因,安装时文件 mono.exe 并不会复制为一个 Win32 程序。
这似乎是一个保留功能,可通过当前Mono安装被复制,
copy C:\Program Files (x86)\Mono-3.2.3\bin\mono.exe to C:\monoinstall\bin
用此修复替代,你可以在 Windows 下执行 Mono。
检查你安装了正确版本。打开 Windows 命令提示符:
cd c:\monoinstall\bin
mono --version
你应该会看到和下面相似的输出:
Mono JIT compiler version 3.8.0 (tarball)
Copyright (C) 2002-2014 Novell, Inc, Xamarin Inc and Contributors. www.mono-project.com
TLS: normal
SIGSEGV: normal
Notification: Thread + polling
Architecture: x86
Disabled: none
Misc: softdebug
LLVM: supported, not enabled.
GC: sgen
6、修复:Xamarin Studio - 防止运行时的无关符号连接
如果你尝试使用 Tools->Options,Projects->.NET Runtime 添加这个 Mono 3.8.0 运行环境到 Xamarin Studio,将会弹出一个错误信息 "Mono Mono runtime not found".
这是因为安装时有额外的符号连接文件被复制。
你可能并不希望在资源管理器或者命令提示符的 dir 命令中看到这些,尽管 dir /a 应该显示它。
如果你不能在 Windows 下删除这些文件,可以使用 Cygwin 命令行删除:
$ cd /cygdrive/monoinstall/bin
$ rm mono
现在就可以为 Xamarin Studio 添加这个 Mono 了。
7、工作区:在 Xamarin Studio 下构建项目出错
(1) 你在编译过程中可能会得到 mcs.bat 遗失的错误,例如:
Build failed. The specified executable is not a valid application for this OS platform.
你需要删在安装文件夹的 mcs 文件,从你安装的 Mono 中复制 mcs.bat 文件
$ cd /cygdrive/monoinstall/bin
$ rm mcs
$ cp /cygdrive/c/Program Files (x86)/Mono-3.2.3/bin/mcs.bat /cygdrive/c/monoinstall/bin
(2) 你可能随后得到一个关于 UNC 路径错误的错误:
error : Error building target GetReferenceAssemblyPaths: UNC paths should be of the form \\server\share
这种情况的出现与配置文件中额外的\\'s有关,请在这里参与讨论:http://stackoverflow.com/questions/19933266/error-building-c-sharp-solution-using-xbuild-mono
解决方法是取消勾选工作区中项目选项中的 Use MSBuild engine ,此时你就可以编译和调试程序。
1、更新
我现在将 Mono 的编译自动化在 Appveyor CI Platform. 为了完成它,我创建了一个设置脚本让 Appeyor 用户更方便地安装依赖环境,自动生成,配置生成,编译和安装 Mono。生成的二进制文件都被打包作为历史版本提供给以后的测试和使用。更多的信息,请看 Appveyor 项目(https://ci.appveyor.com/project/ajlennon/mono-817)和设置脚本(https://github.com/DynamicDevices/mono/blob/ajl/appveyor/appveyor.yml)
2、反馈问题
我写这篇文章的意图是当 Mono 更新时我可以及时地更新和维护这篇文档。
请反馈修正,有什么问题和评论请到这里:http://www.codeproject.com/Articles/815565/How-to-build-Mono-on-Windows
3、版本历史
11/05/2014 第一个版本发表 (编译 Mono 3.4)
10/06/2014 使用 Git 源时,使用最新的源码,添加 get-monolite-latest 步骤
05/09/2014 基于 Mono 3.4 的文档,发布 Mono 3.8 的编译步骤
17/10/2014 添加编译 Mono 3.10 的修复
27/10/2014 添加 Appveyor 编译的信息
4、协议
本文章,包括任何与之关联的源码和文件,授权发表在
The Code Project Open License (CPOL)
5、关于作者
Founded Dynamic Devices in 2004 to deliver high quality embedded solutions.
Alex is an experienced engineer with a deep knowledge and wide experience of both software development and project management. He has provided cutting edge hardware and software design solutions to industry in the United States and Europe and has successfully brought a wide range of products to market.
His technical expertise includes the architectural design and development of embedded systems software, deployment of large scale assured data delivery systems and the creation of low-level device drivers in a number of languages.
During the past decade Alex has worked predominantly with Linux and Windows CE based embedded and wireless devices, customizing O.S builds, developing device drivers, and creating internet-aware mobile applications with accessible user interfaces.
Specialties:Embedded Linux and Windows CE platform ports, device driver development, application development, C#, C, Java, GSM GPRS/UMTS, Wireless, Mesh