オープンソース化されたXamarin.Androidの概要

追記: この辺の詳細はEssential Xamarin -Yin/陰-で一章使ってまとめてあるので、興味のある方はどうぞ。

何がオープンソース化されたのか

Xamarin Evolve 2016で、以下のリポジトリがMITライセンスで公開されました。

XamarinComponentsは、どちらかといえば(以前からある)pluginsの内容を吸収した、他リポジトリにリンクする、ポータルのようなかたちになっています。

今回オープンソース化されたのは、Xamarin platform SDKという部分で、これは一言で言えば「スタンドアローンで実行可能なリリースビルドのアプリケーションをビルドできる環境」になります。ビルドして実行するコードは提供するよ、それ以上の開発環境は提供しないよ、ということですね。Xamarin Studioはオープンソースになっていません(言うまでもないですがMonoDevelopは昔からオープンソースです)。アプリケーションをデバッグ実行したい場合は、相変わらずプロプラエタリのXamarin StudioかVisual Studioを使う、ということになります(ちとがっかり)。

これに伴って、Xamarin.iOSもXamarin.AndroidもXamarin.Formsも、大幅なリポジトリの再構成を余儀なくされており、またプロプラエタリコードの切り離し作業もおこなわれているので、率直に言えば開発者もまだ何が起こっているのかよくわからない状態です。ビルドも公式にはMacしかサポートされておらず、他のメンバーがせっせと壊したLinuxビルドを試行錯誤して直す作業をわたしがやったりしていました(というか今でもしている感じですね)。

ともあれ、今公開されてあるソースは、昔からあるやつのコードとは多少違うものだ、ということです。

そんなわけで、ソースが公開されたので、今回はこれまで詳しく書いていなかったXamarin.Androidの細かい部品について、ちまちまと書いていこうと思います。あんまり読みやすくまとめようという感じではなく、思いついたことを書き並べている感じです。

xamarin-androidの使い方

(この1行は後で消しますが)現状ではビルドされるファイルが不足していて、動かせる環境にないのですが、それでは目的が達成できていないので、今後数日のうちに修正されていくと思います。

Xamarin.Android SDKを使うには、コンソールからプロジェクトのcsprojをビルドするしかありません。

xamarin-androidリポジトリをチェックアウトすると、tools/scripts/xabuild というスクリプトがあり、これが必要な環境変数などをセットアップしつつxbuildを呼び出すように作られています。xbuildの代わりにこれを使うと良いです。(もちろん、無償化公表前のXamarin.Androidとは異なり、コンソールからビルドするのにProfessionalライセンスを必要とするようなことは、もはやありません。)

基本的には、MSBuildタスクを含むXamarin.Android.Build.Tasks.dllが、xbuildがMSBuild extension DLLを解決するパス(MSBuildExtensionPaths)に存在していれば、あとはXamarin.Androidのプロジェクトをビルドするために必要なXamarin.Android.{CSharp|FSharp}.targetsファイルがそのDLLの中に含まれるEmbeddedResourceとして解決されて、Xamarin.Android固有のタスク(BuildApkなど)を処理できるようになるはずです。

最新Xamarin.Androidの構成要素

monoランタイム

monoランタイムはxamarin-androidのgit submoduleとしてチェックアウトすることになります。

Xamarin.Androidは内部的にNDKでビルドしたmonoランタイムを使用するため、アーキテクチャ依存のネイティブライブラリ libmonosgen-2.0.so を含むことになるわけですが、公表時点でのxamarin-androidは、(あろうことか)デフォルトではarmeabiでのみビルドされます。まあこれはAndroid開発者のことを全く理解していないAndroidチームのやる気の無さの表れというよりは、OSS化の方針が決まってからEvolveまでほとんど時間がなかったからというのが大きいです。

xamarin-android内部では、この embedded mono runtime とAndroidプラットフォームを結びつける libmonodroid.so が使われています。xamarin-android自身は、monoランタイムとJNIのinteropを実現しているわけではなく、Androidアプリケーションのブートストラップの過程でmonoランタイムを初期化して利用可能にするためのコードなどが含まれています(Java.Interopモジュールの登場以前はこの辺は一体化していたのですが、Java.Interopの導入以降は、そういう構成になったようです)。

バインディング作成ツール

OSS版Xamarin.Androidには、Androidプロジェクトを新規作成するためのツールは含まれていません(!)が、IDEが無くても、バインディング ライブラリは、自前で作成することができます(!!)。

バインディング ライブラリは、Xamarin.Androidにおける機能の一部にすぎませんが、Mono.Android.dllはこのバインディング ライブラリをサポートする機能に基づいて作られているものであり、Xamarin.Androidの根幹を成す機能であると言えます。

バインディングDLLはどのように作成されているのでしょうか? 基本的な流れは、次のようになっています。

  • jar2xml: Javaライブラリ(jar)を解析して、API定義XMLを生成する
  • generator: API定義に対する修正を適用しながら、C#ソースを生成する
  • csc/mcs: C#ソースをビルドする

最初の部分では、膨大なAPI定義のXMLを生成します。C#コードをAPI定義とするXamarin.iOSとは全然違いますね。なぜこんな設計になっているかというと、これはもともと必要ないはずのツールだったのです。Android AOSPにはXMLベースのAPI定義が含まれており、Android 3.0がクローズドソースで公開されるようになるまでは、Xamarin.AndroidはAOSPのXML定義を解析するツール(generator.exe)のみを使用していました。それがクローズドソースのandroid.jarが登場するようになり、このままでは対応できない状態がいつまで続くか分からなかったので、jarファイルを開いて解析できるツールが必要になった、というわけです。

また、この頃からAndroid supportライブラリなどが登場し、外部ライブラリのAPIを簡単に使えるようにするための汎用的な仕組みが求められてきていました。そのため、それまでandroid.jarだけを相手にしていれば良かっただけのバインディング生成ツールに、さまざまな修正を加えてそれなりに一般化することになりました。この時点で、たとえば、generatorはjarだけでなくDLLも解析しなければならなくなっています(APIの階層構造を把握するためには、全てのjarが必要になるわけですが、依存ライブラリのjarは無いかもしれないですし、そもそもバインドされていないかもしれませんし、DLL上では全く別の名前になっているかもしれません)。

既にそれまでの時点でgeneratorはかなり複雑化していたところに屋上屋を架すことになって、今は割と「誰も触りたくない」部品になっています。残念ながら今のところこれを書き直す計画はありません。

class-parse: 新しいAPI抽出ツール

実は、この最初の部分については、次回リリースから選択肢が増えます。この選択肢は、バインディング プロジェクト ファイル(.csproj。F#はバインディングライブラリの作成ではサポートされていません)にMSBuildプロパティAndroidClassParserで制御できます。そこには、次の値のいずれかを指定します。

  • jar2xml
  • class-parse

jar2xmlJavaのリフレクションとバイトコード操作ライブラリASMを使用して作成されていましたが、class-parseC#で実装されています。jar2xmlが抱えていた絶妙な問題として、Javaリフレクションによって取得されるAPIは、そのコードを実行しているJVMに束縛されてしまう、というものがあります(.NETのSystem.Reflection APIと同じような問題ですね)。Mono.Android.dllには、本来android.jarに無いはずのJava7のAPIへのバインディングが含まれている、というバグがあって、これを解決するのはjar2xmlでは根本的に無理があった(出来なくはないが設計が全く異なるものになる)、というわけです。IKVMのコードを使いまわしたり、javapの出力を利用してはどうか、といったアイディアがいくつか出てきましたが、最終的にC#で書かれたシンプルなバイトコードパーサーを作って終わりということになりました。

もっとも、class-parseが銀の弾丸となったわけでは全くありませんでした。jar2xmlに知らないうちに頼りきっていたわれわれが直面した問題は、バイトコード解析だけではきちんとしたクラス階層の処理ができない、ということです。たとえば、Javaではpublic型をnon-public型から派生できるわけですが、java.lang.reflectはそれをうまく隠してくれていたわけです。class-parseは愚直なパーサーで、その辺りを全く解決しませんでした。

class-parseの開発時は、jar2xmlの出力フォーマットとの互換性も全く気にしていなかったため(generator.exeも拡張してclass-parseフォーマットもサポートすればいい、程度に考えていました)、生成されたXMLに対してさらにMetadata.xmlなどによってAPI定義を修正しなければならないという問題もありました。

また、AOSP由来のXMLでは、派生クラスでオーバーライドされた実装メソッドなどの情報は含まれていませんが、class-parseは愚直なバイトコードパーサーなので、その辺の事情を全く考慮しません。つまりclass-parseの出力は情報の構成が変わってしまっているわけで、そのままgeneratorに渡したわれわれが目にしたのは、大量のコンパイルできないC#コードでした。

結局のところ、今まで通りgeneratorに仕事してもらうためには、class-parseの出力を変換して正常化しなければなりませんでした。以上のような問題をまとめて解決するために、新たにapi-xml-adjusterというツールが作成されました。これは、class-parseの情報をもとにクラスの階層構造を解決して適切な修正を加えつつ、API XMLの構造を変換する役割を分担します。

generator

generatorは以上のような過程を経て生成されたAPI定義XML (バインディング ライブラリ プロジェクトをビルドすると、obj/* 以下に、api.xmlというファイルが生成されるはずです)をもとに、指定されたMetadata API fixup(Metadata.xmlなど)を適用して、クラス階層構造を構築し、インターフェース メソッドなどを抽象クラスで適宜追加し、プロパティやイベントにメンバーを変換・追加して、最終的なDLLのソースを生成します。コードの生成はTextWriter.WriteLineで行っています。いちいちCodeDomなんて使っていません(CodeDomはResource.designer.cs/.fsの生成時に使っています)。

ここ数ヶ月の間に追加された地味な機能のひとつに、Android Annotationsのサポートがあって、たとえばRequirePermissionなどのアノテーションJavaソースに追加してビルドしてさらにきちんとaarにパッケージされたものについては、それを読み込んだ上で対応するattributeを追加するようにしたはずなのですが、肝心のandroid.jarに対応するAndroid SDKのplatform-tools/api/annotations.zip の内容が、いつまで経ってもLollipopの内容のままで止まっていて、たとえばandroid.media.midiAPIに対応するIntDefなどが追加されないままなので、Google仕事しろと思いながら日の目を見ない機能のひとつとなっています。

あとさらに細かすぎて伝わらない追加機能として、同じくAndroid SDKのplatform-tools/apiにある api-versions.xml を読み込んで、ApiSinceというattributeを生成するようにしたのですが、IDE側でこれに対応するメッセージが表示されているかどうかは未確認です(出るようにする、とは言っていました)。使っているAPIがminSdkVersionで指定したバージョンにに無く、コード上でバージョンチェックも通していないと、実行時エラーになってしまうので、簡単に回避できるようにはしたいですよね。

MSBuildタスク

Xamarin.AndroidMSBuildタスク…というより正確には一連のタスク群ですが…は、xbuildあるいはMSBuildでXamarin.Androidのプロジェクトをビルドするために必要なもので、Xamarin.Android.Build.Tasks.dllに含まれています。

このMSBuildタスク群の中には、Androidアプリケーションのプロジェクトで使われるAaptやBuildApkといったタスクの他、Binding projectのためのJarToXmlやBindingsGeneratorといったタスクも含まれています。

ただ、これまでの製品版と大きく異なる部分があって、fast deploymentなど、デバッグビルドのために存在していたタスクが、根こそぎプロプラエタリコードに持って行かれています(つまり、xamarin-androidには含まれていません)。やれやれですね。最新のプレビュー版にはInstant Runのcold swap相当のコードも実装してあるので、そこも公開されていると少し面白かったのですが。

ライブラリ

Mono.Android.dll

Mono.Android.dllは、複数のAndroidプラットフォームに対応する、やや特殊なバインディング ライブラリです。基本的に、サポートするAPI LevelごとにMono.Android.dllをビルドするのですが、それぞれのAPI Levelのandroid.jarの単純なバインディングを生成しているのではなく、それぞれのAPI Level以下のAPI定義をマージした上で、それに対するバインディングを生成しています。これは、Java言語のVMCLIでは、存在しないメソッドを解決するやり方が微妙に異なり、異なるプラットフォーム間でのandroid.jar(に対応するDalvikバイトコード)では生じない問題が、Mono.Android.dllでは生じることになるため、メソッドの定義を適宜前方互換にしてやるひつようがあるためである、と説明されています。

(その副作用で、いつまで経っても邪魔なOrg.Apache.Http*が消えない、といった問題を抱えています。)

以上のような理由などもあって、Mono.Android.dllのビルドは次のように、いくつかの点で特殊な構成になっています:

  • API定義XMLは、生成済みのものがリポジトリに含まれています。
    • API定義XMLは、それぞれのAPI Levelについて、class-parseとapi-xml-adjusterを使用して生成しますが、ビルド時には必要ありません(この辺りをハックしたい人や、新しいAPI Levelの登場時にそのサポートを追加したい人がやります)
  • Mono.Android.dllのビルドでは、まずapi-mergeが呼び出され、生成済みのAPI定義XMLがマージされ、その次にgeneratorがソースを生成し、最後にmcsがC#ソースをコンパイルします。
  • Mono.Android.dll用のメタデータXMLではなくCSVファイルになっています(!) これはXamarinのチーム内ではもともと使われていたフォーマットが、前述のような歴史的な理由で公開ツールとなった時に、仕様の不安定なCSVフォーマットは公開せずにXMLにするという決定が下されたためです。これはgenerator内部でXML形式に変換されて処理されます。

Mono.Android.dllのソースはgithub上の xamarin-android リポジトリにありますが、これは(名前から推測できる通り)Xamarin.Androidの(OSS版の)中心的なリポジトリです。Java.Interopやmonoをsubmoduleにしており、libmonodroidと呼ばれる、Androidアプリケーションのライフサイクル上で動作するmonoのホスティング環境を、Androidの各CPUアーキテクチャごとにビルドします。これには非常に時間がかかります。monoをひとつビルドするだけでも時間がかかるのに、それを(ランタイムだけとはいえ)アーキテクチャごとに行っているわけです。

5/4追記: ↑は現在は正確ではないかもしれません(libmonodroidがarmeabiのビルドしか行っていないため、多分こちらもarmeabiのみ)

xamarin-android リポジトリのソースは、大別して3つに分けられます。

  • ライブラリ (src/Mono.Android, src/Mono.Android.Export)
  • msbuildタスク
  • ビルドツール (ライブラリのソースを生成するツールなど)

Java.Interop.dll

Xamarin.Androidは、前回のstableリリースから、内部的な構成を大きく変えて、Mono.Android.dllの内部で、新しくJava.Interop.dllというライブラリを参照しています。ただし、公開APIの観点では、特に変更はありません。この新しいDLLは、Android APIバインディングを含まず、JNIを通じたJava APIの呼び出しを実現するために必要な機能だけを含むライブラリです。

Java.Interop.dllは、ほぼJNI呼び出し部分を最適化するために新規開発されたものであり(README.mdには「これはセカンドシステム症候群だ」と明言されています)、アプリケーション開発者が気にするべき部分は基本的にありません(もともと、このリポジトリは、メイン開発者が実験的な遊び場として使っていたという側面が大きいです)。

github上の Java.Interop リポジトリには、Java.Interop.dllと、これに基づくバインディングを作成するためのビルドツールの機能を実装するDLLがいくつか含まれています。現状、このリポジトリには、実際の製品で使われていない実験的なコードも数多く含まれているので、ここで全てを説明することはしません。

Java.Interopに含まれるソースは、大別して2つに分けられます。

  • ライブラリ。src/Java.Introp がその中心となる、Java.Introp.dllをビルドするためのプロジェクトです。
  • 公開ビルドツール用ライブラリ。Java APIバインディングを生成するためのツール(generator.exeなど)の機能を実装しているライブラリが、ここに含まれます。

この他に、ビルド時にしか使用しないツールなども含まれているのですが、重要性は低いので省略します(JNIEnvクラスの大量のメンバーを自動生成するツールなどがあります)。

Java.Interopは、開発者が何を思ったのかMSBuildの仕組みだけで全てビルドできるように複雑なビルドスクリプトをセットアップしたのですが、Windows上ではビルドしないわ、Linuxビルドも壊れているわ、Android SDKダウンロードまでスクリプト化したもののエラー トラッキングなどがまともに出来ないわ、カスタムSDKセットアップの柔軟性は微塵もないわで、端的に言ってこのビルドスクリプトは失敗作です。が現状それしかないので我慢するしか無い。

それはさておき、Java.Interop.dllがあると何が出来るかというと、たとえば、このコア部分だけを再利用したまま、全く別のAPIマッピング理論に基づくバインディングDLLを構築して使用することができます。当然ながら、そうすると過去の遺産は使えなくなるわけですが、support-v*ライブラリなどは自分でビルドすることもできるため、多くの人にとっては、あまり問題にならないでしょう。特にXamarinが提供してきたGoogleのライブラリに対するバインディングは、ソースが公開されることが期待されていますXamarinComponentsリポジトリでソースが公開されています。

(今のところ、XamarinでMono.Android.dllのAPIを抜本的に差し替える予定はありません。)

もちろん、Xamarin.AndroidAndroidアプリケーションを作るためのものであり、Androidアプリケーションは、Androidアプリケーションのライフサイクルに従ったものでなければなりません。既存のMono.Android.dllを使用しなくても、その根本に変わりはありません。

Xamarin.AndroidのN previewとJava8サポートについて

Google I/Oが近づいていますが、それに先立ってAndroid N previewが公開されていますね。既にpreview 2で、今後も5週間ごとにプレビューが出続けるというので、最新版Androidへの対応もだいぶやりやすくなったなという感じです。

そんなわけで、Xamarin.AndroidのMono.Android.dllも、OSS版xamarin-androidとXamarin.Androidの最新preview版は、最新のN preview 2まで対応しています。

Android N APIの最大の特徴は、Java8に対応したことですが、Xamarinユーザーにとっての恩恵はほぼ無いでしょう。

恩恵は無いのですが、Java8サポートは極めて難しい問題をもたらしました。インターフェースのデフォルトメソッドです。当初、N preview 1が登場した後、Mono.Android.dllはこれらについてもメソッドを生成していました。しかし、C#Javaとは異なり、デフォルトメソッドをサポートしません。当然ながら、インターフェースで定義されたメソッドは実装しなければならないことになります。Javaではこれは「やってもいいし、基本やらなくていい」ことなのに、C#になったとたん「やらなければならない」ことになるのは大変です。Java.Util.Iteratorなど、ごく基本的なインターフェースに、突如大量のメソッドが追加されて実装しなければならなくなったわけです。しかしインターフェースでAPIを定義しないと、誰も実装をオーバーライドできないことになります。

しばらく考えましたが、これはいくら何でもメソッドを追加するわけにはいかない、ということで、今のところ、デフォルトインターフェースメソッドは生成しないことにしました。通常のインターフェースメソッドでこういう「省略」を行うと、アプリケーション開発者がバインディングクラスの派生クラスを定義した時に生成するAndroid Callable Wrapper (ACW)が必要なインターフェースメソッドを生成せず、javacがコンパイルエラーを起こすことになるわけですが、インターフェースデフォルトメソッドの場合には問題になりません。

必要であれば、多少ややこしいコードを書く必要がありますが、手作業で追加することも一応可能です。

この辺は、OSS版xamarin-androidのrepoでRFC状態になっているので、何かしら意見があれば書いておいて下さい。

Java 8 Interface Binding · Issue #25 · xamarin/java.interop · GitHub

個人的には、まだどこにどう需要が出てくるかわからない現状で、中途半端なバインディング生成機能を実現したくない派です。現状ほぼメリットないし。

ちなみに、Android SDKでJava8が必要となるソースをコンパイルする際には、javacではなくjackという新しいGoogleコンパイラーを使用する必要がある(ということになっている)ことになっているのですが、

gfx.hatenablog.com

Xamarin.Androidが内部的に生成するコードはJava8の文法を使用しませんし、Java8のjavacをそのまま使っていても問題ないはずです。

JavaバイトコードをDalvikに変換するdx(dx.jar)には、--no-strictというオプションがあって、これを指定しないとJava8のバイトコードは拒絶されてしまうのですが、Xamarin.Androidでは内部的にこれを指定してdxを呼び出しています。

また、java8が問題になるのはproguard(およびそれを内部的に使用するmultidexのツールmainDexClasses)で、この古いツールはJava8に対応していないので、Xamarin.Androidではproguardの使用が指定されていたら、Java7にフォールバックします(実のところ、proguardの中身をいじって、参照されているデフォルトメソッドも全部スキャンするようにしてしまえば良いわけで、それほど対応が難しいとは思えないのですが、Googleはjackへの移行を促進するために政治的に非対応にしているんじゃないかと邪推しています)。

以上、インパクトがありそうでない、ちょっとしたXamarin.Android小ネタでした。

Xamarin Workbookの起源とインスタント実行の系譜

しばらく前、2月の半ば頃のことになりますが、MiguelがThe Evolution of Interactive C#というブログポストを投げていました。

The Evolution of Interactive C# - Miguel de Icaza

奇しくもわたしがDroidKaigi 2016でInstant Runについてのセッションを行う直前に公開されたもので、まあ幸い誰も気づかなかったと思いますが、完全にセッションのオチのネタバレだったんですね。 どうネタバレだったのかはスライドの最後の方を見てもらえれば分かると思いますが、

speakerdeck.com



最後に触れているContinuous Coding、けっこう新しいネタだったので、誰も知らなかったと思いますが、先のMiguelの投稿でも触れられているんですね。

(そういえば、このセッション資料、先日のGoogle Developers Summit TokyoでもGoogle Japanの人に紹介していただいたそうです。インスタント実行とは関係のない文脈だと思いますが、いずれにしろ役に立つネタで良かった^2)

さ て、先の投稿でWorkbookについて言及していることに気付きましたか? 実はシークレットでも何でもなかったんですね。まあ、せっかくなので、Miguelが書いたネタを日本語でなぞってみようと思います。

Xamarin Evolve 2014で発表されたXamarin Sketches、皆さん覚えているでしょうか?

atsushieno.hatenablog.com



Sketches はIDEのpane上に描画されたREPL環境で、XcodeのPlaygroundによく似ていますが(と言ってもそれを誰でも使えるかたちで実現した のはXamarinが先なんだよね、みたいな話は↑のエントリで説明してあります)、この時のcanvasは確かXamarin.Macがベースになって いて、Miguelはこれを「みんなが実際にやりたかったことは、単独のスケッチを実行することじゃなくて、アプリケーションを実際に動かしながら描画す ることだったから、あまり便利じゃなかった」と回想していますね。そして、それで作られたのがXamarin Inspectorだった、というわけです。

blog.xamarin.com


Inspector は、その名の通り、UI要素の内容をinspectするために作られたものですが(それ自体はTest Cloudの要素でもあるXamarin.UITestや、そもそもAndroid SDKにはhierarchy viewerなんかも同じですね)、その内容を動的に書き換える機能もREPLの統合によって実現しています。Inspectorが面白いのは、UI要素 をクエリする部分と描画する部分を切り分けていて、描画する部分は基本的にHTML Canvasでやっているんですね。

https://developer.xamarin.com/guides/cross-platform/inspector/Images/mac-3d-view-small.png



Inspectorはまだプレビューですが、基本的にこの辺りのプロジェクトは全て繋がっているわけです。

ところで、ハッカーの皆さんには割とよく知られていると思いますが、Jupyter Notebookというプロジェクトがありますよね。

Try Jupyter!


Jupyter Notebook、かつてIPython Notebookとして公開されていたプロジェクトですが(Miguelの先の投稿でIPythonって書いてあることに気付きました?)、まあ、要する に、これらは皆同じ「markdownの中に埋め込まれたREPL」の系譜です。Workbookの発想そのものは、特に新しいものじゃないんです。

Xamarin Workbook、面白いので、みんなこれを使ってドキュメントを書くといいと思います。と言いたいところなんですが、Workbookは Inspectorの一部で、Inspectorはオープンソースじゃないんですよね…まあ、コードが実行できなくても、サンプルコードフラグメントがド キュメントに含まれていて、それが実行可能だというのは有用なので、手元で動かせればいいという人はぜひ使ってみて下さい。

この Workbookも、Continuous Codingも、基盤として使用しているのはInspectorです。特にContinuous Codingはソースが公開されているので、使おうと思えば誰でも使えるということがみてとれるかと思います。けっこう夢がひろがりんぐだと思いませんか? (無理ですかそうですかそうですね。。)

アンカンファレンスやろう

Xamrin Evolveが再来週に迫ってきましたね。

https://evolve.xamarin.com/

参加される皆さんどうぞよろしくお願いします。

 

まあそんな人はほぼ皆無だと思うわけですが、日本ではde:codeの前夜祭のようなものがあって、de:code参加者でなくても参加できるそうなので*1、前回書いたようなゲリラ(非公認)ミートアップのようなものをここでやりましょう。*2

connpass.com

アンカンファレンスって何?

アンカンファレンスというのは、セッションのように誰かが1人だけ発表して他の人はそれを聞くだけ、みたいな退屈な時間ではなくて、誰かがトピックを持ち込んで、それについてみんなが会話に参加するかたちで作っていく、単なる雑談の場よりはもう少しオーガナイズされたミートアップのようなものです。

プロジェクターがあるのでスライドを見せながらしゃべることもできますが、1人でしゃべっているだけだと単なる短いセッションで終わってしまうので、それは用意しても手短に、あるいは画面を共有するに留めるのが良いでしょう。わたしは基本的にスライドみたいなものを用意するつもりはありません。(Webページをみんなで眺めることはあるかもしれませんが。) 質疑応答が活発であれば、それで終わるかもしれませんね。

まあ先着順のようなので、そもそもその場でアンカンファレンスにエントリーできるかどうかは当日にならないとわからないのですが、わたしがいることには変わりないので、何かしらの場が作れるだろうと思います。15分で終わらなかった話をテーブルの外で続けてもいいですしね。

*1:かく言うわたしもde:codeには参加登録していませんし

*2:すぐに人数がいっぱいになったらどうしようと思ってちょっと待っていたのですが、その懸念は必要なかったようですしね。

Xamarin is going to be open to Everyone

Microsoft Build 2016 2日目のキーノートで、MonoランタイムがMITライセンスに変更され、Xamarin Runtimeと称されるXamarinプラットフォームの部分がオープンソース化されることが発表されました。

blog.xamarin.com

今後数ヶ月、おそらくは来月のXamarin Evolveまでに、何かしらの成果が公開されるのでしょう。Buildから1ヶ月もしないうちにXamarinオンリーイベントとか、まあまさかもう動かせないしやるしかないって感じですね。ちなみに参加が危ぶまれていたわたしですが、何とか行けることになったので、現地に赴かれる酔狂な皆様もある意味ご安心下さい。(?)

(XamarinがVSに…云々は、ここではどうでもいい話なので、そういう話はそういう方面のコミュニティを眺めて下さい。)

monoランタイムがMITライセンスになると、Unity(3D)のような製品が、ライセンスを気にすること無く、既に組み込みLinux環境に最適化されたmonoを、改変ソースを公開せずに使用できるようになります。(ただし、Unityで使用されているmonoランタイムは、本家monoにかなり手を加えたものであり、かつかなり昔のバージョンをもとにしているはずなので、最新版のmonoにすんなりアップデートするということはないだろうと思います。) .NET Coreも既にクロスプラットフォームで動作しますし、.NET MicroFxという選択肢もありますが、いま.NET Coreを選ぶのは、長期的な計画でもなければかなりチャレンジャーであることは否めませんし、minimized runtimeやstable embedded APIを期待している人は、まだmonoを選んだほうが良いかもしれません。この辺は、それぞれの特性や自分の計画を踏まえて選ぶのが良いでしょう。

ランタイムがMITライセンスに変更になったのは、もちろんMonoチームがもはや組み込みライセンスビジネスで生きていく必要がなくなった(Microsoftエコシステムの一部として開発していく)ことから実現したものです。

そしてXamarinプラットフォームのOSS化。ついにこの日が来てくれた、という感じです(まだですけど)。

いずれはLinux環境でも利用可能になり、全てとは言わないまでもコア部分だけでもオープンソースの環境として公開し、アプリケーションが開発できるようになってほしい、と思っていましたが、とうとう実現しそうです。

公式ブログには、アプリケーションをビルドするために必要となるツールとライブラリ一式がOSS化される、とあります。もちろんMicrosoftは全てをオープンソースに捧げているわけではなく、Visual StudioなどのIDEに統合する部分を、引き続き製品の一部として(のみ)提供していくわけで(ちなみにXamarin Studio for Windowsは無くなります。もちろんMonoDevelopは引き続きOSSです)、その部分はクローズドソースで収益源になるようです(その辺はFAQを見てもらえればと思います)。

ソースを書いてアプリケーションをビルドするための、最小限の環境は提供するから、IDEに頼りきらない開発者は我が道を切り開いて歩いてくれ、ということです。面白い。受けて立とうじゃないか。われわれは.NET Framework SDK Toolsしか無いような環境でも生き延びてきたんだぜ。(って自分が中の人だったことを忘れるところだった…)

個人的にも、自作のライブラリなどをiOS/Androidで展開する時に、商用製品を買ってもらわないとcontributeしてもらえない事態には、忸怩たる思いがあったので、これで誇りをもって開発していくことができます。

オープンソースで.NET開発を推進してきたMonoが、Xamarinになってクローズドソースの製品を売り続けてきたのを、Microsoftが買収してオープンソースにして公開するというのは、歴史の皮肉とも言えますが、実に面白い展開になってきましたね。

面白いといえば、JetBrainsとUnity3DとRedHatが.NET Foundationにjoinするというニュースもなかなかのインパクトだと思います。Riderもプレビュー版が公開されたばかりなので、JetBrainsが、Javaで書かれたIDEに.NETをどう組み込んで統合していくか、見ものですね。わたしが彼らに大いに期待しているのは、.NET Core統合の実現です。RedHatLinux環境で.NET Coreの普及を促進していくための協業をどう展開していくかですね。Unityは、まあ言うまでもないでしょうけど、最適なランタイムを実現するための選択肢が広がって、近くない将来の見通しは良くなったのではないかと思います。

Build1日目のUbuntu組み込みの件も含めて、今回のBuildには面白いネタがたくさんありましたね。日本でも5月下旬のde:codeでいろいろ紹介されると期待しています。わたしは今のところ参加する予定はないのですが(どういう身分になっているのかすら何も決まっていないし!)、この辺に関心のある人が集まる日々になるので、何かしら集まって話せる機会を設けたいところですね。

長かったこれまでと、分からないけど楽しみなこれから

今回は振り返り無駄話です。

もう遡ること13年以上前、初めてmonoにパッチを送った時のことを、今でも覚えています。実のところ、monoのML(当時はmono-listしかありませんでした)には当時のアーカイブがあるので、今でも見ることが出来るんですね。 http://lists.ximian.com/pipermail/mono-list/2002-October/008988.html

.NETは、2002年当時のわたしにとっては、オープンソース開発の世界における脅威でした。

.NET Frameworkを知ったのは、仕事でWindowsアプリケーション開発に初めて関わってほどなくのことでした。当時はJavaのコードを書き始めて半年くらいだったと思います。C++VBじゃない、Java並に簡単な言語でGUIアプリまで作れてしまう、その大きな可能性に魅了されましたが、同時にこれがWindowsでしか動作しない、プロプラエタリな開発環境であることは、わたしの目には大きな脅威として映りました。

わたしが職業エンジニアになったのは、ついうっかりのようなものです。当時のわたしは、大学で知財法制に無駄に詳しくなった後、その非論理的な制度設計に嫌気が差して*1、自由なソフトウェア(まあ正確にはオープンソースですが)の世界に魅入られており、この.NET Frameworkのような開発環境がオープンソースで存在すればいいのに、と思っていたのでした。.NETはECMAで標準化を図っていましたが、それはもう完全にJavaの標準化プロセスに対抗しているように見えました。だいたい技術標準だというのなら、実装が2つあるべきじゃないか。他に実装もないのに、何が標準化だ、と。

…そして、monoを「発見」したのです。

当時、monoは始まってから既に1年弱が経過していたと思います。その時点で、既にmcsでコンパイルしたコンソール アプリケーションをmonoランタイムで実行できるようになっていました。mcsはC#で書かれていて、セルフホストしておらず(mcsでmcsをビルドできるほど完成しておらず)、Windows上でcscを使ってビルドしなければなりませんでした。

そんな状態のmonoでしたが、さまざまなドキュメントが既に存在していたので、とりあえずそれらを日本語訳するところから始めました。MLにも登録して、眺めるようになりました。MLを眺めているうちに、Miguel de IcazaがXML DOMのAPIが足りないから実装してくれ〜、みたいなメッセージを投げたのを見て、えっ、そんなのも無いの?…と思って、ソースに手を入れはじめたのが、最初の一歩でした。(ちなみに書いたコードはいい加減で、間違って彼だけに送ってしまったら「すばらしい! ちなみにテストを書いてくれ!」みたいな返事が来て、初めてテストなるものを書いてみたら、全く期待通りに動かなかったのでした…)

当時、monoチームには日本語を話せるDuncanというハカーがいて(というか今でもXamarinにいるのですが)、彼といろいろ日本語で会話しながら、いつの間にかmonoの開発チャットに出入りして、カタコトの英語でやりとりできるようになったのでした。誰が誰だかは当初全然わかりませんでしたが、あのmonoを毎日作っている連中です。すげー!と思いながら、同時にとても追いつけない量の会話を流し見しながら、参加していたものでした。

1年ほど経って、わたしが転職を考えていた時、その話をそのDuncanにしたら「じゃあうちで働きなよ!」みたいなことになって、翌日Miguelから「何ドルで働く?」(うはhドルかよ!) 「Novellに統合されたら人を雇えるから来いよ」みたいな話が来て…それでmonoチームに入ることになったのでした。

そんなわけで、会社に入ったのはNovellになってからなのですが、Ximianは近くでずっと見ていましたし、完全にNovellとは別の指針で動いているXimianの一員として仕事していました。MiguelとNatの2人が始めたベンチャー企業が、Novellという大企業に買収されて、それでも(エンジニアの目に見える範囲では)あまり変わらない体制でGNOMEとMonoを開発していくのを、9年近く見てきました。

MonoとNovellの話は(今日は)どうでもいいのでした。今日は.NETの話を書きたい。

.NET Frameworkが猛威を振るっていた(ようにわたしに見えていた)のは、Microsoftが.NET 2.0をリリースして、並行して次世代.NETでWinFXと呼ばれる「全てがマネージド」の世界を構築しようとしていた頃でした。大量のマネージドコードのプロプラエタリなフレームワークが、うっすらとしたECMA CLIの上に悪夢のように覆いかぶさって、せっかくASP.NETが動くようになったLinuxが、また.NET開発の一線から遠ざかってしまう。何とかして対抗しなければならない。そう思いながらMonoの機能を拡張していたのでした。(まあそれはわたしの話であって、他のメンバーには当然ながら各々の思想があります。)

結果的にWinFXはだいぶ縮小した存在になり、WPFもWFもしばらくは大規模に使われず、WCFは出来るとみて着手することになったので、そういった懸念は概ね杞憂に終わったのでした。

その頃から、Microsoftの開発の潮流に変化が見え始めます。(WinFXの反省だったのかな、とわたしは勘ぐるのですが、)新しい.NET 3.5の開発からは宣伝的な文句は消え、Linqなど質実剛健な機能拡張が行われるようになりました。オープンな技術標準を目指したIdentity Metasystemのコンセプトとともに、Infocardが登場しました。ASP.NETの中核となるMVCオープンソースで公開され、ほどなくいくつかのコンポーネントオープンソースで公開されるようになっていったのでした。その後も、IronLanguages、Reactive Extensions、Roslyn、そして.NET Coreと、NET Framework (referencesource)、VSCodeと、オープンソース指向で開発していくMicrosoftの姿勢は、もはや揺るがないものになりました。

このオープンカルチャーの契機となったASP.NET MVCをリードしていたのが、今回の買収の結果、Xamarinチームを配下におさめることになった、Scott Guthrieです(今はAzureチームのトップですね)。彼はMiguel、Natの2人とは長く交友関係にあって、XimianのMonoチームがNovellレイオフされた時も、いろいろ出来る範囲で手助けしようとしてくれたそうです。今回の統合は、ごく自然に成り立ったと言えるでしょう。"married" と表現している人も少なからずいました。

今回の買収は、MiguelとNatの2人にとっては、2度目の大成功ということになります。Xamarinの立ち上げは容易なものではありませんでしたが(その辺はXamarinの2年半を振り返るを見てもらえればと思います)、今回このゴールのひとつに到達できて、わたしは、期待されていた、あるべき結末を見た思いになりました。

MiguelがECMA標準をもとにMonoを始めてから約15年。MonoはXamarin製品の中核であり、まだまだ使われていきますが、大きな節目を迎えたとは言えるでしょう。Nadellaの新生Microsoftの傘下に加わったXamarinが、これからMicrosoftと一緒に、Monoが築いてきたエコシステムをどう発展させていくのか。おそらくは中の人として、今後も見続けていきたいと思います。

*1:その辺は http://d.hatena.ne.jp/atsushieno/20070813/p1 にあります

DroidKaigi2016セッションと資料にまつわるあれやこれや

2/18-19のDroidKaigiで、Android Studio 2.0のInstant Runについて話してきたので、少しその補足というか背景とかを書いておこうと思うます。

(DroidKaigi自体はいろんな人といろんな話ができてちょう面白かったのだけど、これじゃただの小並感なのでその辺は他の人にお任せです。)

 

speakerdeck.com

DroidKaigiは、2015には一応CFPにXamarinネタを投げてみたけど採用されず(CFPにも「とりあえず使い方から.NETっぽいリアクティブなコードとか書くよー」とか適当なことしか書いてなかった)、参加申込も寝て起きたら瞬殺で終わっていて、結果的にノータッチだったのでした。

今年も当初は参加予定すら無かったのだけど、CFPがそれほど集まっていなくて、たまたまInstant Runの調べ物をしていて、これくらいなら軽くしゃべれて、新しいモノ好きにはウケる話かなーと思って、投げてみたら通ったという感じでした。(最終的にはえらい数のCFPが届いていましたが。)

今回はまずそれなりのストーリーラインがほしいなと思い、まずスライドの下地となる話をちゃんと書こうと決めました。それが最終的にはコレです。

qiita.com

多分それなりに長期的に役に立つ読み物になるんではないかと思います(自己評価)。

実のところ大半は3ヶ月くらい前にgistでまとめてあったのだけど、とりあえずDroidKaigiまで待ってから出すことにしました。インスタント実行の部分 (Part III)をどうするか決めていなかったためです。

この部分は、実のところちゃんと調べないと分からなかったので(今でもだいぶうっすらとした情報量のはず)、話に入れるかどうかも決めていませんでした。30分しかなかったし。割と直前まで迷いました。ただ、ビルドの話だけにするとどうしてもオチが弱かったので、それならInstant実行のあるべき姿をプッシュする方が面白いかなと思って、滑りこませることにしました。Xamarin関係の言及が多くなってしまったのは、完全に副作用です。仕事でもないのにわざわざ宣伝なんてうんざりだし。Continuousがオープンソースでなければ完全にカットするところでした。

DroidKaigiではInstant Runおじさんとか言われたりしてたけどw、あれ自体にはあんまし思い入れはない、というか普段はXamarin Studioで日々fast deploymentしているわけで、自分にとっては新しくないわけです。ついでに言えば、YAPF(横浜Androidプラットフォーム部, 当時)で Xamarin.Androidの話をした時にその基本的な仕組みをちょっとだけしたこともあるので、実はInstant Runの基本的な仕組みは、ごく一部の(?)Androidersにとっては、完全に新しい話ではなかったりします。Android SDKが追い付いてきて、お、やったね?という感じです。

(ちなみに、従来の Xamarin.Androidのfast deploymentでは、dllの変更はすぐに反映されるけど、生成されるACW(java interop部分)に変更が生じると、Javaビルドタスクが実行される→APKが生成される→再インストール、となってfast deployment効かないじゃん!ってことになっていたので、最近はその辺を改善する仕事をやっていたのでした。*1

まあ仕事中に得られた知見は発表のごく一 部にしか活かせず*2、基本的には仕事と無関係なJavaとGradleの調べ物の産物です。

セッション全体的には、しゃべりがちょっと早すぎたかな?とは思ったものの、まあ内容がやや詰め込み気味だったのでいたしかたなく(だいぶ削ったのでした)、伝えるべきことは伝えられたかと思います。

…次回、DroidKaigiかは分かりませんが、似たような機会があったら、また.NETやXamarinとは全く無関係な調べ物と話をしたいですね。

*1:2/20に初登場したアルファ版 では、アプリケーションのcsproj に<FastDeploymentType>Assemblies:Dexes</FastDeploymentType> というプロパティを追加してやると、その辺が機能するわけですが(今こっそり隠し機能を暴露した!)、くだらない政治的な紛争の結果、この辺はまだ リリースノートにも載っていません(!)。秘密ってほどのことではないけど

*2:Bazelに似たようなコードがあることを教えてもらった程度。Instant Runの発表直後にそんなの見つけてくるmonodevelopハカーこわい