Unity でプリプロセッサを使わずビルド環境を分ける方法
#if DEVELOPMENT_BUILD
// ...
#endif
これをやるとリファクタリングがし辛くなってしゃあない。
けど変数で分岐するといらんコードが入ってしまう…。
どうすればいい?
JIT 環境ではコンパイラが賢くコードストリップをしてくれるおかげで、変数によるプラットフォーム分岐ができるようだ。
たしかに、コンパイル結果をみてみると IL では残っている分岐が JIT Asm ではなくなっている。
ん、でも IL2CPP ってたしか AOT だったよな…。
IL2CPP は IL2CPP でまた別のコードストリップができるのね。
実際にコードがなくなっているかどうかをそれぞれの環境で検証してみるか。
どうやって検証すればいいかよくわからないけど…。
今後は Mono については考えずに IL2CPP を前提とする。(たぶんもう使わない)
IL2CPP ではこんな感じでコンパイルが進んでいく。
Unity の Stripping Level は Managed code stripping についての設定。
Managed code stripping について調べた。
- 最初にいくつかのクラスやメソッドをマーキングする
- 静的解析を行いマーキングした個所から辿っていってさらにマーキングを進める
- マーキングされていない部分を削除する
ストリップのレベルを選択することで、最初のマーキングやほかのクラスを辿っていくときのやり方を選ぶことができる。
リフレクションを使っていたりバックエンドから呼び出すコードはマーキングから外れてしまうので、手動でマーキングする必要がある。
属性を記述したり link.xml に追加したりすることで手動でマーキングすることができる。
さて、読んでみてわかったけど、クラスとかメソッドとかそういう単位でのストリップはしてくれるみたいだけど、どうやら「不要な分岐の削除」はここではやってくれないみたいだ。
たしかに、JIT 環境でも IL の段階では残っていたわけだから、そりゃそうか…。
ということは頼れるのは C++ コードになった後の C++ コンパイラということになるけど、ここはプラットフォーム依存らしくて、どうしたらいいのか…?
Android 環境でビルドを行い apk の中身をのぞいてみた。
上記のツールで apk の中の libil2cpp.so と global-metadata.dat を展開してみる。
const
で分岐
cpp の段階で不要な分岐は削除されていた。
readonly static
で分岐
不要な分岐は残っていた。
getter
で分岐
不要な分岐は残っていた。
あれ…。期待していたのと違うなぁ…。
もっと激しく最適化してもらうためには、なにかオプションの設定がいるのだろうか。
試しに Mono でビルドしてみて、dnSpy で Assembly-CSharp の中身をのぞいてみたら、普通に分岐残ってたぞ…?どういうこと…?
SharpLab の JIT コンパイラとは別物ってこと?