需求
编译自定义版本的 Mono 运行时,可以用来做 DLL 更新。考虑到跨平台编译,因此尝试使用虚拟机 + Linux 方式编译。
环境
- macOS 10.14.6
- Virtual Box 6.0.12
- Ubuntu 18.04.5 LTS Server
- Android NDK r13b
- Unity Mono 2018.4 mbe
准备
下载
Unity Mono
Unity Mono 分支 unity-2018.4-mbe 使用 GitHub Zip 方式下载
编译时使用的版本是 unity-2018.4-mbe 当前的最新版本 https://github.com/Unity-Technologies/mono/commit/7d3af3b2665639dbe0d4be714dbc66c93d419f17
Android NDK
Android NDK r13b
Ubuntu
Ubuntu 18.04 LTS
Ubuntu
安装 Ubuntu
创建一个新的虚拟机,使用专家模式
- 名字 Ubuntu 18.04 LTS,4096MB内存
- 2TB硬盘 VMDK(虚拟机磁盘)动态分配
设置 | 网络
- 网卡1 | 端口转发 添加宿主机 2222 到客户机 22 的映射
- 网卡2 | 启用网络连接 连接方式:桥接网卡
安装
全程默认设置
设置
- 名字 ubuntu
- 服务器名字 ubuntu-server
- 用户名 ubuntu
- 密码 123456
按空格键勾选 Install OpenSSH Server
,不安装其他任何组件,开始安装
安装完成后直接重启,提示推出光盘时忽略直接按回车即可。
SSH 连接虚拟机
1
|
ssh -p 2222 ubuntu@127.0.0.1
|
配置 SSH 密钥登录
如果觉得每次登录、传输文件时输入密码麻烦,可以添加一个公钥到虚拟机中
在宿主机中拷贝公钥:
1
|
pbcopy < ~/.ssh/id_rsa.pub
|
在虚拟机中执行
1
2
3
4
5
6
|
cd
mkdir .ssh
touch .ssh/authorized_keys
chmod 700 .ssh
chmod 600 .ssh/authorized_keys
vi .ssh/authorized_keys
|
把公钥保存到 authorized_keys
中,保存退出即可。
工程文件
传输文件
1
2
3
4
5
|
scp -P 2222 mono-unity-2018.4-mbe.zip ubuntu@127.0.0.1:~
scp -P 2222 bdwgc-50b55f29ee4783dd5cc01a975e5bcdf8703cb1ee.zip ubuntu@127.0.0.1:~
scp -P 2222 boringssl-3e0770e18835714708860ba9fe1af04a932971ff.zip ubuntu@127.0.0.1:~
scp -P 2222 libatomic_ops-268c37a63b3d77803c7cec6e5b318c015a9a157c.zip ubuntu@127.0.0.1:~
scp -P 2222 android-ndk-r13b-linux-x86_64.zip ubuntu@127.0.0.1:~
|
切换 root 账户
SSH 连接后切换账户
1
2
|
ssh -p 2222 ubuntu@127.0.0.1
sudo -i
|
从这儿开始所有的后续操作都是使用 root 账户进行的。
解压文件
切换当前目录到 root 用户目录 /root
,然后执行解压操作将文件解压到 /root
下。
1
2
3
4
5
6
|
cd
apt install unzip
unzip -q /home/ubuntu/mono-unity-2018.4-mbe.zip
unzip -q /home/ubuntu/bdwgc-50b55f29ee4783dd5cc01a975e5bcdf8703cb1ee.zip
unzip -q /home/ubuntu/boringssl-3e0770e18835714708860ba9fe1af04a932971ff.zip
unzip -q /home/ubuntu/libatomic_ops-268c37a63b3d77803c7cec6e5b318c015a9a157c.zip
|
移动文件
1
2
3
4
5
6
7
8
|
rmdir mono-unity-2018.4-mbe/external/bdwgc/
mv bdwgc-50b55f29ee4783dd5cc01a975e5bcdf8703cb1ee/ mono-unity-2018.4-mbe/external/bdwgc
rmdir mono-unity-2018.4-mbe/external/bdwgc/libatomic_ops
mv libatomic_ops-268c37a63b3d77803c7cec6e5b318c015a9a157c/ mono-unity-2018.4-mbe/external/bdwgc/libatomic_ops
rmdir mono-unity-2018.4-mbe/external/boringssl/
mv boringssl-3e0770e18835714708860ba9fe1af04a932971ff/ mono-unity-2018.4-mbe/external/boringssl
|
验证文件
输出目录内所有文件,确保内部都是正确的文件,而不是只有错误的目录或空目录。
1
2
3
4
5
6
7
8
9
10
11
12
13
|
# ls mono-unity-2018.4-mbe/external/bdwgc
allchblk.c BCC_MAKEFILE CMakeLists.txt doc gc_cpp.cpp ia64_save_regs_in_stack.s Makefile.direct new_hblk.c pthread_start.c reclaim.c tests windows-untested
alloc.c bdw-gc.pc.in configure.ac dyn_load.c gc_dlopen.c include malloc.c NT_MAKEFILE pthread_stop_world.c SMakefile.amiga thread_local_alloc.c
appveyor.yml blacklst.c cord extra gcj_mlc.c libatomic_ops mallocx.c obj_map.c pthread_support.c sparc_mach_dep.S tools
AUTHORS build darwin_stop_world.c finalize.c gc.mak m4 mark.c OS2_MAKEFILE ptr_chck.c sparc_netbsd_mach_dep.s typd_mlc.c
autogen.sh ChangeLog dbg_mlc.c fnlz_mlc.c headers.c mach_dep.c mark_rts.c os_dep.c README.md sparc_sunos4_mach_dep.s WCC_MAKEFILE
backgraph.c checksums.c digimars.mak gc_cpp.cc heapsections.c Makefile.am misc.c PCR-Makefile README.QUICK specific.c win32_threads.c
# ls mono-unity-2018.4-mbe/external/bdwgc/libatomic_ops
AUTHORS autogen.sh ChangeLog configure.ac COPYING doc m4 Makefile.am pkgconfig README.md src tests TODO
# ls mono-unity-2018.4-mbe/external/boringssl
BUILDING.md CMakeLists.txt codereview.settings CONTRIBUTING.md crypto decrepit fuzz FUZZING.md include INCORPORATING.md LICENSE PORTING.md README.md ssl STYLE.md third_party tool util
|
编译
官方文档
建议先参考官方文档了解编译流程,然后再参考下面的流程手动处理。
安装构建软件
直接执行命令会提示有依赖软件未安装
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
# ./autogen.sh --prefix=$PREFIX
**Error**: You must have `autoconf' installed to compile Mono.
Download the appropriate package for your distribution,
or get the source tarball at ftp://ftp.gnu.org/pub/gnu/
**Error**: You must have `libtoolize' installed to compile Mono.
Get ftp://ftp.gnu.org/gnu/libtool/libtool-1.2.tar.gz
(or a newer version if it is available)
**Error**: You must have `automake' installed to compile Mono.
Get ftp://ftp.gnu.org/pub/gnu/automake-1.3.tar.gz
(or a newer version if it is available)
configure: error: "cmake not found"
|
需要安装官方文档上指明的依赖软件
1
|
apt-get install git autoconf libtool automake build-essential gettext cmake python3 curl
|
初始化编译环境
所有的命令行输出中只截取了最后的一段输出,中间的省略了。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
|
# cd mono-unity-2018.4-mbe
# mkdir /opt/mono
# PREFIX=/opt/mono
# echo $PREFIX
/opt/mono
# ./autogen.sh --prefix=$PREFIX
=== configuring in external/bdwgc (/root/mono-unity-2018.4-mbe/external/bdwgc)
configure: WARNING: no configuration information is in external/bdwgc
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: no
Engine: Building and using the JIT
BigArrays: no
DTrace: no
LLVM Back End: no (dynamically loaded: no)
Libraries:
.NET 4.x: yes
Xamarin.Android: no
Xamarin.iOS: no
Xamarin.WatchOS: no
Xamarin.TVOS: no
Xamarin.Mac: no
Windows AOT: no
Unity JIT: default
Unity AOT: default
Orbis: no
Unreal: no
WebAssembly: no
Test profiles: AOT Full (no), AOT Hybrid (no)
JNI support: IKVM Native
libgdiplus: assumed to be installed
zlib:
BTLS: yes (x86_64)
Now type `make' to compile
|
说明大部分条件已准备好,但是缺失 bdwgc
配置文件,实际 bdwgc
目录是空的。
打开构建脚本,注释掉不用的平台 armv5 armv6_vfp,加快构建时间。
1
|
vi external/buildscripts/build_runtime_android.pl
|
1
2
3
4
5
|
# By default, build runtime for all the variants we need. But allow something to specify an individual variation to build
if ($androidArch eq "")
{
# system("perl", "$buildScriptsRoot/build.pl", "--build=1", "--clean=1", "--artifact=1", "--arch32=1", "--androidarch=armv5", "--forcedefaultbuilddeps=1", "--windowssubsystemforlinux=$windowsSubsystemForLinux", "--stevedorebuilddeps=$stevedoreBuildDeps") eq 0 or die ("Failed building mono for armv5\n");
# system("perl", "$buildScriptsRoot/build.pl", "--build=1", "--clean=1", "--artifact=1", "--arch32=1", "--androidarch=armv6_vfp", "--forcedefaultbuilddeps=1", "--windowssubsystemforlinux=$windowsSubsystemForLinux", "--stevedorebuilddeps=$stevedoreBuildDeps") eq 0 or die ("Failed building mono for armv6_vfp\n");
|
第一次编译
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
# sh external/buildscripts/build_runtime_android.sh
>>> PATH in Build All = /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin
>>> Build All Args = --build=1 --clean=1 --artifact=1 --arch32=1 --androidarch=armv7a --forcedefaultbuilddeps=1 --windowssubsystemforlinux=0 --stevedorebuilddeps=1
>>> Mono checkout = /root/mono-unity-2018.4-mbe
>> System Info :
Linux ubuntu-server 4.15.0-117-generic #118-Ubuntu SMP Fri Sep 4 20:02:41 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
fatal: not a git repository (or any of the parent directories): .git
fatal: not a git repository (or any of the parent directories): .git
>>> Mono Revision =
>>> Build Scripts Revision =
>>> External build deps = /root/mono-unity-2018.4-mbe/external/buildscripts/artifacts/Stevedore
>>> Existing Mono =
>>> Mono Arch = i686
>>> No existing mono supplied. Checking for external...
>>> Running bee to download build-deps...
./bee: 5: ./bee: mono: not found
^Cfailed to run bee
Failed building mono for armv7a
|
安装 Mono
必须先安装 Mono 才能编译 Mono,这是一个自举问题。
编译安装 Mono
虽然 Unity 官方文档中提到了编译安装 monolite,但是速度实在是太慢了
1
2
|
# Run the following line after ./autogen.sh
make get-monolite-latest
|
包管理器 Mono
不要使用 apt install mono-devel
安装 ubuntu 包管理器的 mono,无法运行 bee,提示
1
2
3
4
|
>>> Running bee to download build-deps...
Unhandled Exception:
System.TypeLoadException: Could not load type 'Bee.StandaloneBeeDriver' from assembly 'bee, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'.
|
如果安装了需要先删除
1
|
sudo apt-get --purge remove mono-runtime
|
Mono 官方预编译版本
Mono 官方的源太慢,需要使用代理
1
|
vi /etc/apt/apt.conf.d/proxy.conf
|
修改代理地址为局域网内代理
1
2
3
4
|
Acquire {
HTTP::proxy "http://192.168.1.1:7890";
HTTPS::proxy "http://192.168.1.1:7890";
}
|
必须使用代理下载安装 Mono,否则安装极慢
Ubuntu 18.04 (i386, amd64, armhf, arm64, ppc64el)
1
2
3
4
5
|
sudo apt install gnupg ca-certificates
sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF
echo "deb https://download.mono-project.com/repo/ubuntu stable-bionic main" | sudo tee /etc/apt/sources.list.d/mono-official-stable.list
sudo apt update
apt install mono-devel
|
第二次编译
1
2
3
4
5
6
7
|
# sh external/buildscripts/build_runtime_android.sh
>>> Android NDK needs to be extracted
>>> Android NDK Extension = .zip
unzip: cannot find or open /root/mono-unity-2018.4-mbe/external/buildscripts/artifacts/Stevedore/android-ndk-r13b-linux/android-ndk-r13b-linux-x86_64.zip, /root/mono-unity-2018.4-mbe/external/buildscripts/artifacts/Stevedore/android-ndk-r13b-linux/android-ndk-r13b-linux-x86_64.zip.zip or /root/mono-unity-2018.4-mbe/external/buildscripts/artifacts/Stevedore/android-ndk-r13b-linux/android-ndk-r13b-linux-x86_64.zip.ZIP.
Something went wrong with the NDK extraction
Failed building mono for armv7a
|
需要将 ndk 移动到指定位置
1
2
3
|
mv /home/ubuntu/android-ndk-r13b-linux-x86_64.zip .
mkdir /root/mono-unity-2018.4-mbe/external/buildscripts/artifacts/Stevedore/android-ndk-r13b-linux
mv android-ndk-r13b-linux-x86_64.zip /root/mono-unity-2018.4-mbe/external/buildscripts/artifacts/Stevedore/android-ndk-r13b-linux/android-ndk-r13b-linux-x86_64.zip
|
第三次编译
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
# sh external/buildscripts/build_runtime_android.sh
>>> LIBTOOLIZE before Build = /root/mono-unity-2018.4-mbe/external/buildscripts/artifacts/Stevedore/built-tools/bin/libtoolize
>>> LIBTOOL before Build = /root/mono-unity-2018.4-mbe/external/buildscripts/artifacts/Stevedore/built-tools/bin/libtool
>>> Cleaning /root/mono-unity-2018.4-mbe/tmp
>>> Calling autogen in mono
>>> Configure parameters are : --disable-mcs-build --with-glib=embedded --disable-nls --disable-btls --with-mcs-docs=no --prefix=/root/mono-unity-2018.4-mbe/tmp --host=armv5-linux-androideabi --disable-parallel-mark --disable-shared-handles --with-sigaltstack=no --with-tls=pthread --disable-visibility-hidden mono_cv_uscore=yes
**Error**: You must have `libtoolize' installed to compile Mono.
Get ftp://ftp.gnu.org/gnu/libtool/libtool-1.2.tar.gz
(or a newer version if it is available)
failing autogenning mono at /root/mono-unity-2018.4-mbe/external/buildscripts/build.pl line 1344.
Failed building mono for armv7a
|
修改 /root/mono-unity-2018.4-mbe/external/buildscripts/build.pl
1
2
3
4
5
6
7
8
9
|
# vi /root/mono-unity-2018.4-mbe/external/buildscripts/build.pl
450 $ENV{'LIBTOOLIZE'} = "$builtToolsDir/bin/libtoolize";
451 $ENV{'LIBTOOL'} = "$builtToolsDir/bin/libtool";
改为
450 $ENV{'LIBTOOLIZE'} = "/usr/bin/libtoolize";
451 $ENV{'LIBTOOL'} = "/usr/bin/libtool";
|
第四次编译
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
# sh external/buildscripts/build_runtime_android.sh
python ./genmdesc.py TARGET_ARM . cpu-arm.h arm_cpu_desc ./cpu-arm.md
/bin/bash: python: command not found
Makefile:3594: recipe for target 'cpu-arm.h' failed
make[3]: *** [cpu-arm.h] Error 127
make[3]: Leaving directory '/root/mono-unity-2018.4-mbe/mono/mini'
Makefile:481: recipe for target 'all-recursive' failed
make[2]: *** [all-recursive] Error 1
make[2]: Leaving directory '/root/mono-unity-2018.4-mbe/mono'
Makefile:555: recipe for target 'all-recursive' failed
make[1]: *** [all-recursive] Error 1
make[1]: Leaving directory '/root/mono-unity-2018.4-mbe'
Makefile:485: recipe for target 'all' failed
make: *** [all] Error 2
Failed to make
Failed building mono for armv7a
|
提示缺少 Python2,手动安装:
第五次编译
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
# sh external/buildscripts/build_runtime_android.sh
最终提示
>>> Skipping make install. We don't need to run this step when building the runtime on non-desktop platforms.
>>> Skipping build Unity Script and Boo
>>> Creating artifact...
>>> Creating embedruntimes directory : /root/mono-unity-2018.4-mbe/builds/embedruntimes/android/x86
>>> Copying libmonosgen-2.0.so
>>> Copying libmonobdwgc-2.0.so
>>> Copying libMonoPosixHelper.so
>>> Creating monodistribution directory
>>> Creating version file : /root/mono-unity-2018.4-mbe/builds/versions-android-x86.txt
>>> Skipping unit tests
|
证明编译成功,检查构建结果
检查
确认编译的目标平台目录里都存在需要的库文件:
1
2
3
4
|
# ls /root/mono-unity-2018.4-mbe/builds/embedruntimes/android/x86
libmonobdwgc-2.0.so libMonoPosixHelper.so libmonosgen-2.0.so
# ls /root/mono-unity-2018.4-mbe/builds/embedruntimes/android/armv7a/
libmonobdwgc-2.0.so libMonoPosixHelper.so libmonosgen-2.0.so
|
把所有文件拷贝到 Gradle 工程中输出使用
注意
不要按下面的方法修改 libbdwgc_libs
,会导致编译出来的 mono 无法运行,Unity 运行时在屏幕中间提示
1
2
|
Error
Failed to load Mono.
|
1
2
3
4
5
|
5,修改编译文件错误
打开 mono/mini目录下的 makefile文件,找到
libbdwgc_libs = $(monodir)/external/bdwgc/libgc_static.la
改为
libbdwgc_libs = $(monodir)/external/bdwgc/libgc.la
|
参考资料