Linux下编译Unity mono源码的libmonobdwgc-2.0.so
1 编译简介
我这里编译mono.so目的是为了安卓做dll热更(也可dll加密),热更和加密部分主要就是修改源码mono/metadata/image.c里面的mono_image_open_from_data_with_name函数(参考http://blog.sina.com.cn/s/blog_9e5d42ee0102vvtg.html),这里不做介绍,只介绍不一样的打包方式。先补充几个概念(这一部分来源:https://www.cnblogs.com/lijiajia/p/7822571.html)
md导过来图片有丢失,可以去下载我这篇文章的PDF版:Mono-mbe版源码编译.pdf
1.1 unity跨平台运行原理
通常Unity的脚本有C#、JS、Boo。不过现在官方都只推荐使用C#了,为什么Unity可以支持用不同的语言编写代码呢?因为它使用了一种叫CIL的中间语言,C#、JS、Boo,最终都会被编译成一种叫IL的中间语言,然后通过Mono运行时编译成原生代码运行。
1.2 Mono JIT
JIT就是及时编译(just in time),能把IL及时编译成原生代码运行,跟解释语言又有些不同,JIT不是逐行解释执行,而是会把解释过的代码缓存起来,以备下次运行,因此从理论上说JIT可以接近以前的纯编译技术。Unity的跨平台是运行在Mono虚拟机上的,在安卓上可以通过JIT实现动态编译IL Assembly来热更新代码,但是在IOS平台,由于苹果公司禁用了JIT,只能通过AOT提前静态编译后执行。
1.3 unity不同设置对应的mono源码选择和编译结果
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wjOPHgdT-1578308868516)(C:\Users\szgla\AppData\Roaming\Typora\typora-user-images\image-20200105162036735.png)]
Unity的PlayerSetting里面Scripting Runtime Version选择.Net3.5的话,mono源码版本选择普通版本即可,编译生成普通mono.so。编译方法网上比较多:https://www.cnblogs.com/lijiajia/p/7822571.html
如果Scripting Runtime Version选择.Net4.x的话(unity2018开始已经将.Net3.5的选项标记为弃用了),此时mono源码版本要选择相应的mbe版本,编译会生成libmonobdwgc-2.0.so。
2 Linux环境搭建
如果用windows编译,比较麻烦,问题也千奇百怪(旧版本mono是这样的,网上也有很多教程提到),所以选择Linux下编译,大部分人估计都没装Linux系统,所以推荐windows下安装虚拟机即可,比较使用。
主要是下载VM和Ubuntu,关于这两步的操作,网上大把教程,在此就不赘述。有个教程比较详细,两个软件的安装都在里面:
https://blog.csdn.net/u013142781/article/details/50529030
其他需要的东西,在第6步正式编译时候会慢慢说。
3 安装mono平台
可以参考官网安装方法:https://www.mono-project.com/download/stable/#download-lin-ubuntu
3.1 下载mono资源库到本地
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3zcvqq2F-1578308868518)(C:\Users\szgla\AppData\Roaming\Typora\typora-user-images\image-20200105144822639.png)]
运行截图里面的命令
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
即可下载,有进度显示,下载较慢。
有时候会有提示有些packages是自动下载的,而且现在已经不需要了,你可以去移除他们(当然不移除也没什么问题,反正也是没用的资源)移除命令:
sudo apt autoremove
3.2 安装mono资源库
安装命令:
sudo apt install mono-devel
安装过程有需要确认的地方输入:Y,(确保你的磁盘大小足够)
安装过程也去去下载一些关联资源,所以时间很久,网络不好可能会出现下图这种下载错误:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uizhyKov-1578308868519)(C:\Users\szgla\AppData\Roaming\Typora\typora-user-images\image-20200105150602546.png)]
最后一行已经提示了,你可以运行apt-get update或者运行修复丢失的命令即:
apt-get install mono-devel --fix-missing
即可继续下载之前下载失败的资源
3.3 验证mono
可以输入版本号查询,发现已经有信息了
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-apgGJoml-1578308868519)(C:\Users\szgla\AppData\Roaming\Typora\typora-user-images\image-20200105152120915.png)]
如果还不放心的话,可以去验证官网那个链接的例子:
https://www.mono-project.com/docs/getting-started/mono-basics/
4 下载unity-mono源码
先去下载unity-2018.4-mbe的mono源码压缩包:https://github.com/Unity-Technologies/mono/tree/unity-2018.4-mbe
然后解压到虚拟机的某个文件夹,我的就直接放在Downloads下面了。
注意:
这里最好用命令去下载,这样会把项目关联的一些扩展文件也一起下载下来,不过很慢,而且不一定能下得动(有些地区网络就下不了,这方面不太懂,我在深圳就下载不了,就找了武汉的朋友用浏览器下载压缩包给我的)。手动下载压缩包的话,就下不到关联文件,这时需要挨个手动下载,不下载的话解压后的external文件夹是空的,编译不了,所以比较麻烦但没办法,关联的扩展文件下载地址:
https://github.com/Unity-Technologies/mono/tree/unity-2018.4-mbe/external
5 安装安卓NDK
一定要安装mono源码需要的ndk,不然等会编译会报错,查看mono源码需要的ndk版本,可以打开mono源码的external/buildscripts/build.pl查看
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TRoeYkCe-1578308868520)(C:\Users\szgla\AppData\Roaming\Typora\typora-user-images\image-20200106185501504.png)]
5.1 下载NDK
ndk下载地址:
https://developer.android.google.cn/ndk/downloads/older_releases.html#ndk-13b-downloads
5.2 安装NDK
下载后,我这边就解压到了Home下面,然后需要配置ndk的环境变量:
sudo gedit ~/.bashrc
在文件末尾添加如下内容:
export ANDROID_NDK="/home/android-ndk-r13b"
export PATH=" A N D R O I D N D K : ANDROID_NDK: ANDROIDNDK:{PATH}"
保存退出,然后运行使之生效命令:
source ~/.bashrc
验证环境变量生效方法:
输入命令:$PATH,查看环境变量是否已经有刚才添加的ndk路径
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YfeDEpQo-1578308868520)(C:\Users\szgla\AppData\Roaming\Typora\typora-user-images\image-20200105210751093.png)]
5.3 验证NDK
验证ndk安装成功方法:
运行命令:
ndk-build
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ufDnJDsh-1578308868520)(C:\Users\szgla\AppData\Roaming\Typora\typora-user-images\image-20200106122349176.png)]
只要不是command not found
,ndk-build命令不存在
,就表明Android-NDK安装并配置成功。
6 正式编译
主要就是编译build_runtime_android.sh文件,但是编译过程会有很多错误挡住,下面来重头开始编译一遍。
1.首先进入编译目录:mono2018.4mbe/mono-unity-2018.4-mbe/external/buildscripts,然后打开命令窗口,最好先将当前账户升级到root账户,不然有些需要权限的地方需要频繁输入密码,升级最高权限账户命令:sudo su
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KFysThMP-1578308868521)(C:\Users\szgla\AppData\Roaming\Typora\typora-user-images\image-20200106123153140.png)]
2.设置root用户,执行命令:./build_runtime_android.sh,这时会看到说权限不够
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lFlBGKz9-1578308868521)(C:\Users\szgla\AppData\Roaming\Typora\typora-user-images\image-20200105101056807.png)]
那么给该文件夹添加执行权限: chmod +x -R *,然后执行查看当前文件夹内容命令:ls,发现文件都变成绿色的了,就表示执行成功了(原本没有权限时候都是白色的)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-j991OTNu-1578308868522)(C:\Users\szgla\AppData\Roaming\Typora\typora-user-images\image-20200105101517892.png)]
3.然后继续执行命令:./build_runtime_android.sh
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rBovdYyX-1578308868522)(C:\Users\szgla\AppData\Roaming\Typora\typora-user-images\image-20200105101952356.png)]
输入yes继续执行,会提示编译失败,截图如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Jv4mGwm6-1578308868523)(C:\Users\szgla\AppData\Roaming\Typora\typora-user-images\image-20200105102126438.png)]
在build.pl里面搜索“Failed to checkout mono build tools extra”的代码会发现在294行
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yZjgWKwu-1578308868523)(C:\Users\szgla\AppData\Roaming\Typora\typora-user-images\image-20200105110752737.png)]
分析那段代码意思是说要去下载一个“mono-build-tools-extra”的东西,但是这玩意网上已经找不到了,所以暂时修改这个checkout结果(有大佬知道怎么回事,欢迎留言指导!)
4.修改"$checkoutResult = 0;" 注意0后面加个分号
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KZvWomEd-1578308868524)(C:\Users\szgla\AppData\Roaming\Typora\typora-user-images\image-20200105112436968.png)]
5.然后继续执行命令:./build_runtime_android.sh (没错,就是不断的修改报错,继续执行,直到成功…),会出现如下提示:failed to run bee
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Bn3blVH1-1578308868524)(C:\Users\szgla\AppData\Roaming\Typora\typora-user-images\image-20200105112715825.png)]
分析这个错误,大概意思是说:我们执行编译后,程序要跑一个bee.exe去下载build-deps,这个bee.exe是需要mono来驱动的,但是现在驱动失败了,所以我们要检查自己有没有装mono平台(官网描述:mono是一个软件平台,它允许开发者轻松地创建跨平台的应用程序)
6.检查mono,运行命令:mono --version,查询安装的mono的版本
如果查询不到,那么第3步去下载安装即可;
如果有查询到(Ubuntu中默认安装了一个mono,但可能能还不是最新的),但是还是有此错误,那么可能是mono版本或者安装有问题,少了一些文件,这时保险起见最好先移除现有mono,再按第3步去重新下载安装,卸载命令:
sudo apt-get –purge remove mono-runtime
sudo apt-get autoremove
7.安装完mono后,继续执行命令:./build_runtime_android.sh,执行后会出现如下界面(由于我原来的ndk版本不对,所以才有这个报错):
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pMrq7J73-1578308868524)(C:\Users\szgla\AppData\Roaming\Typora\typora-user-images\image-20200105194604911.png)]
提示是说指定路径下找不到android-ndk-r13b,就是说缺少相应的安卓ndk,那么我们去下载r13b的安卓ndk(可以用浏览器下载,一定要选人家要的r13b的版本),按照第5步就可以安装ndk了,
8.软链接。ndk弄好后,由于前面说的指定文件夹找不到ndk,现在ndk安装位置也不在那个位置,所以要链接过去,链接命令:
ln -s ndk根目录 前面报错提示的位置
然后会发现那个文件夹会生成如下这个带箭头的文件夹:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Z6WfAaHb-1578308868525)(C:\Users\szgla\AppData\Roaming\Typora\typora-user-images\image-20200106184910038.png)]
然后继续执行命令:./build_runtime_android.sh,之后会有一个报错提示:failing autogenning mono,意思是调用autogen.sh出错了,错误是在build.pl的1363行:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mHpCJSRT-1578308868525)(C:\Users\szgla\AppData\Roaming\Typora\typora-user-images\image-20200105201351748.png)]
还有其他提示是找不到某个路径(忘记截图了),反正查询一番后需要在470行这里修改如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sDxBojSD-1578308868526)(C:\Users\szgla\AppData\Roaming\Typora\typora-user-images\image-20200106170747808.png)]
9.继续执行命令:./build_runtime_android.sh,这次就顺利的编译成功了!
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1Evak28D-1578308868526)(C:\Users\szgla\AppData\Roaming\Typora\typora-user-images\image-20200105204652708.png)]
编译成功后生成的.so文件在:mono-unity-2018.4-mbe/builds/embedruntimes/android文件夹下
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Pjy3p1G1-1578308868527)(C:\Users\szgla\AppData\Roaming\Typora\typora-user-images\image-20200106171739377.png)]
10.替换unity编辑器下的libmonobdwgc-2.0.so
unity编辑器需要替换的目录有两个:
一个Develop版的:Unity\Editor\Data\PlaybackEngines\AndroidPlayer\Variations\mono\Development\MonoLibs
一个Release版的:Unity\Editor\Data\PlaybackEngines\AndroidPlayer\Variations\mono\Release\MonoLibs)
其实就是你打包时候有没有勾选Development的问题:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Av6ewkD3-1578308868527)(C:\Users\szgla\AppData\Roaming\Typora\typora-user-images\image-20200106182159148.png)]
**切记:**替换前一定要先备份好MonoLibs文件夹。
然后将刚才编译生成的armv7a和x86里面的"libmonobdwgc-2.0.so"分别替换unity安装目录下对应的 “libmonobdwgc-2.0.so”,切记不要替换反了
切记:不要把生成的文件全部替换过去(libMonoPosixHelper.so不能替换),不然打包出来的apk启动直接报“Failed to load Mono”,用不了,全是泪啊。。。切记切记!
然后就可以打包测试一下自己生成的mono是否能用。
3-1578308868527)]
**切记:**替换前一定要先备份好MonoLibs文件夹。
然后将刚才编译生成的armv7a和x86里面的"libmonobdwgc-2.0.so"分别替换unity安装目录下对应的 “libmonobdwgc-2.0.so”,切记不要替换反了
切记:不要把生成的文件全部替换过去(libMonoPosixHelper.so不能替换),不然打包出来的apk启动直接报“Failed to load Mono”,用不了,全是泪啊。。。切记切记!
然后就可以打包测试一下自己生成的mono是否能用。
总之对于我这种Linux小白来说,编译过程还是相当艰难的,从安装虚拟机、vm到各种编译命令,百度了无数次,也万分感谢我同事路峰的热心指导和帮助,祝大家好运!