今からだいたい1ヶ月前に、Googleが新しいDexコンパイラd8
を紹介していました。
android-developers.googleblog.com
d8
はAndroid SDKの既存のツールで言えばdx
に相当する機能を実装しています。dxはJava bytecode (*.class)をDalvik bytecode (*.dex)に変換するコンパイラですね。通常はclasses.dexをビルドするために使われています(が、大抵の人は意識していないでしょう)。
Android Studio 3.0のbetaでは既にこのd8を有効に出来ます。既に使えるならXamarin.Androidでも使えるようにしたいところです。ただ、リリース当初はd8のソースが見当たらず、しばらく待っていました。その後、d8がr8のリポジトリに含まれていると教えてもらったので、試しに使ってみたら上手くいきました。
というわけで、dxの代わりにr8を使うようなNuGetパッケージを作っておきました。ソース…と言うほどのものは無いのですが…はここにあります。ちなみにxamarin-androidに加えた変更もかなり小さいものです。
xamarin-android-d8-build
をpackages.config に追加するとインストールできます(このパッケージはまだリスティングに載せていないので、パッケージマネージャのUIで検索しても出てきません)。パッケージをインストールするだけでMSBuildプロパティが追加されるだけで、Xamarin.Androidアプリケーション以外で副作用は無いはずです。
このパッケージですが、実のところXamarin.Androidを製品版から使用している人には使えません。xamarin-androidをmasterからビルドしている人は今すぐ使えます。そうでない人はd15-5ブランチがalpha channelに降ってきてから利用できるようになります。ちなみに今はd15-3がstable、d15-4がalphaですね。
これ自体は大したコードの変更を伴っていないのに、なぜこんな根本的な差し替えが可能なのでしょうか? それは、Xamarin.AndroidのMSBuildタスクを読み解くことが出来れば誰にでも出来ます(MSBuildタスクはデバッグビルドのサポート固有の部分以外はgithubで公開されています)。dx.jarを呼び出す部分はCompileToDalvik
ターゲットであり、CompileToDalvik
タスクでコマンドラインを生成しています。ここではdx.jarはDxJarPath
プロパティ、その引数はDxExtraArguments
プロパティで指定されています。
今回のNuGetパッケージはこれらのプロパティをオーバーライドして、同梱のr8.jarを使用するように指定しているだけです。ちなみにdx.jar
を使う場合は--dex
と--no-strict
というオプションが必要なので、これらはDxExtraArgumentsのデフォルト値となっています。r8を既存のCompileToDalvikタスクで使うにはこれらが邪魔だったので、消す作業をした、というわけです。
DxJarPathはもともとカスタマイズ可能になっていたので、全体的な変更も些少なものです。
…というわけで、ごく簡単なハックですが、MSBuildタスクをどうやってカスタマイズすればいいか、簡単に解説できるネタだったのでまとめてみました。