IL2CPP深入详解-总览

导语

该系列将会分为以下几个部分:
1. 总览(本文)
2. c++代码解析
3. 调试c++代码
4. 方法调用(一般方法,虚方法等)
5. 泛型共享
6. 类型与方法的 P/invoke 封装
7. 垃圾回收
8. 测试框架与使用

什么是IL2CPP

IL2CPP 是 Unity 自 4.6.1p5版本 提出的一种新的 scripting backend 方式,为Unity提供了更加高效、更加便携的虚拟机,IL2CPP分为两个独立的部分:

  • AOT(静态编译)编译器
  • 运行时库

其中AOT编译器将 IL(由.Net编译器输出的中间语言)转换为C++源码,而运行时库则会提供诸如 垃圾回收、线程/文件获取(独立于平台,与平台无关)、内部调用直接修改托管数据结构的原生代码 的服务与抽象。

AOT编译器

所谓AOT编辑器即 il2cpp.exe
在 Windows 系统中你可以在 Editor\Data\il2cpp 目录中找到它,
在 OSX 系统中你可以在 Contents/Frameworks/il2cpp/build,即Unity的安装目录中找到它。
il2cpp.exe 是由C#编写的受托管的可执行程序,它接受我们在Unity中通过Mono编译器生成的托管程序集,并生成指定平台下的C++代码。

IL2CPP的工具链如下图所示:

il2cpp-toolchain

运行时库

IL2CPP技术的另一部分是运行时库(libil2cpp),它的存在是为了支持IL2CPP虚拟机的运行,运行时库几乎完全由C++代码编写,并作为一个静态库与最终的可执行程序链接。(值得一提的是,IL2CPP技术十分得益于使用了libil2cpp这一更轻便的运行时库)

你可以通过查看 libil2cpp 的头文件了解其的代码构成(Windows 系统下的目录为Editor\Data\PlaybackEngines\webglsupport\BuildTools\Libraries\libil2cpp\include,OSX 系统下的目录为 Contents/Frameworks/il2cpp/libil2cpp),例如你可以在 codegen/il2cpp-codegen.h 文件中看到 il2cpp.exe 生成C++代码的接口以及 运行时库 的接口。

运行时库的另一关键功能是提供了垃圾回收,这一块内容将在后续的文章里再详细探讨。

AOT编译器是如何运行的

让我们来看一个例子(该例子运行在 Windows 系统下 Unity 5.0.1版本中)
开启一个新的工程,将如下脚本添加至主相机上:

using UnityEngine;

public class HelloWorld : MonoBehaviour 
{
  void Start () 
  {
    Debug.Log("Hello, IL2CPP!")
  }
}

此时我们发布一个WebGL平台下的程序,并使用 Process Explorer 工具查看Unity通过什么命令行对 il2cpp.exe 进行了调用:

"C:\Program Files\Unity\Editor\Data\MonoBleedingEdge\bin\mono.exe" 
"C:\Program Files\Unity\Editor\Data\il2cpp/il2cpp.exe" 
--copy-level=None 
--enable-generic-sharing 
--enable-unity-event-support 
--output-format=Compact 
--extra-types.file="C:\Program Files\Unity\Editor\Data\il2cpp\il2cpp_default_extra_types.txt" 
"C:\Users\Josh Peterson\Documents\IL2CPP Blog Example\Temp\StagingArea\Data\Managed\Assembly-CSharp.dll" 
"C:\Users\Josh Peterson\Documents\IL2CPP Blog Example\Temp\StagingArea\Data\Managed\UnityEngine.UI.dll" 
"C:\Users\Josh Peterson\Documents\IL2CPP Blog Example\Temp\StagingArea\Data\il2cppOutput"

这个命令行看起来又复杂又吓人,不用担心,让我们逐步来解析它,

"C:\Program Files\Unity\Editor\Data\MonoBleedingEdge\bin\mono.exe"

首先,Unity启动 mono.exe

"C:\Program Files\Unity\Editor\Data\il2cpp/il2cpp.exe

接着启动 il2cpp.exe


剩下的命令行则是传递给 il2cpp.exe ,而非传递给 mono.exe的参数,首先这里传递了5个标识符给 il2cpp.exe:


–copy-level=None

告诉 il2cpp.exe 不要复制生成的C++代码.

–enable-generic-sharing

IL2CPP将会共享泛型以此来减少最终包体的大小。

–enable-unity-event-support

支持通过反射获取的Unity事件,保证代码能够正确生成。

–output-format=Compact

在生成的C++代码中,为类与方法使用更少的字符数来命名,这样会使得代码更难以调试,因为IL代码的命名将会发生改变(笔者注:应该类似于代码混淆),但是却能够被编译器更快编译,因为编译器所需要解析的字符数变少了。

–extra-types.file=”C:\Program Files\Unity\Editor\Data\il2cpp\il2cpp_default_extra_types.txt”

使用默认的 额外类型文件 ,这个文件会被加入到你的Unity工程里,并告知 il2cpp.exe 哪些泛型类型或者数组类型没有在IL代码中出现,却会在运行时被创建。


值得注意的是这些命令行也许会在后续的Unity版本中发生变化。最后,让我们看看剩下的三条命令行。


“C:\Users\Josh Peterson\Documents\IL2CPP Blog Example\Temp\StagingArea\Data\Managed\Assembly-CSharp.dll”
“C:\Users\Josh Peterson\Documents\IL2CPP Blog Example\Temp\StagingArea\Data\Managed\UnityEngine.UI.dll”

il2cpp.exe 接受所有应该被转换的 IL 程序集,在这里例子中它应该包含我的 MonoBehaviour脚本Assembly-CSharp.dll 以及 GUI assemblyUnityEngine.UI.dll ,很显然,上面的命令行里似乎少了些什么, 我的脚本引用了 UnityEngine.dll 和 mscorlib.dll,但是它们却没有被包含在上述的命令行中,那么它们在哪儿呢?事实上,il2cpp.exe 在内部对这些程序集进行了处理,因此在上述的命令行中它们不是必须的,Unity只显式地需要 根程序集(不被任何程序集引用的程序集)在命令行中被提及。

“C:\Users\Josh Peterson\Documents\IL2CPP Blog Example\Temp\StagingArea\Data\il2cppOutput”

最后的一个参数表示 il2cpp.exe 的输出目录,即 il2cpp.exe 生成代码的输出位置,如果你对此感兴趣的话,可以看一看生成目录下的C++文件,而这一块内容我们也会在后续的文章中对其进行详解。此外,如果你希望浏览生成目录下的代码的话,推荐在出包的时候选择 Development Player 模式,这样一来将会移除 –output-format=Compact 命令行,使得你的代码更具可读性。

PS:你可以通过改变 Player Settings 中的设置来观察 Unity 传递给 il2cpp.exe 的命令行的差异,例如将
Enable Exceptions 设置为 Full,那么命令行中就会增加 –emit-null-checks–enable-stacktrace–enable-array-bounds-check 三项.

IL2CPP没有做的工作

Unity官方并没有重写C#的标准库,因此当你发布一个Unity工程的时候,即使你选择了 IL2CPP 的方式来生成你的代码,所有在 mscorlib.dll、System.dll 等标准库中的代码都将使用Mono2X的方式来生成。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269

推荐阅读更多精彩内容