お知らせ.bat

まだあったのか!という感じのこのhatenablogですが、今年もよろしくお願いします。

今回は(も)ざっくりお知らせです。

.NET Platform Standard日本語訳

まず、githubdotnet/corefxのリポジトリに、.NET Platform Standardというドキュメントがあって、これが.NET Coreの目指すプラットフォームの標準化について説明しています。これは将来の.NETの標準化の動向に大きく影響する内容で重要だと思うので、日本語訳を作ってみました。

https://gist.github.com/atsushieno/7056f56ce4cfd01e0239

ちなみに内容の80%くらいは、以下の岩永さんのスライドで分かりやすくまとめられているので、先にこっちを見て概要を掴んだほうがいいかもしれません。(というか、ここで言及されていないのはBait and switchの詳細とかガードレールの存在くらいかも。)

docs.com

JXUG #10 XamarinでのNuGetとCIを極めよう

次。ひさしぶりにJXUGでXamarinネタをしゃべります。

jxug.connpass.com

今回はトピック指定で来ましたので、NuGetを使う話です。まあ、NuGet自体の話はあんまり語ることがない(と思う)ので、PCLを絡めて、Xamarinで使うようなパッケージってどう使う / ビルドするといいの?みたいな話をしようと思います。(NuGetの使い方だけ何十分もひたすら聞きたい人なんて居ないよね…?)

で、PCLでライブラリを作る話ですが、最後に2014年5月にこの記事を書いてからもう2年経とうとしているわけでして*1

www.buildinsider.net

この間にいろいろアップデートがあったので(とは言ってもPCLの基礎はほとんど変わっていないという認識ですが)、その辺を反映しつつ、モダンなクロスプラットフォーム開発はどうなっている・どうなっていくのか、という方向性で話をしたいと思います。(上記の日本語訳は、そのためのものだと思ってもらえればと思います!) まあスライドはまだ1枚も書いていませんけど。

Instant Runを実現する仕組み at DroidKaigi2016

もうひとつ、セッションが確定したら書こうと思っているうちに参加人数がいっぱいになって告知する意味が全然なくなっちゃったDroidKaigi2016の1日目(2/18)に、Android Studio 2.0 Previewの新機能Instant Runについての話をします。Xamarinは無関係です。基本的には()

droidkaigi.github.io

Instant Runはパッと見では「何でそんなこと出来ちゃうの?」って思えるような不思議な機能ですが、この辺の黒魔術がどのように実現されているのか、掘り下げて解明していく話をしたいと思います。詳しくはまた事前にリークするかも。しないかも。

CFPには書いたのですが、Instant Runのソースは公開されていないので、おそらく推測で話すことになるでしょう。まあ、それなりの傍証がある、確からしい話をするつもりではあります。既にDroidKaigiに登録しているラッキーな人で、もし興味が湧いてきたら、ぜひ聞きに来て下さい。

*1:これ、公開されたのは5月なんですが、大部分はその前の冬休みに書き上げていたんですよね…

2015年の終わりに感謝する作品集

今年こそクリスマスの朝に間に合わせようと思い、しばしば年末まで引っ張っていた「今年出会ったすげー作品に感謝」の2015年版をon timeに書き上げました。例によって「今年出た」作品には限りません。わたしが今年発見した作品が対象です。

2014 2013 2012

watoさんのピアノ作品

まずは理屈抜きでハマった2曲から。最初はVocaloid曲をピアノアレンジした作品。この種の作品が原曲を超えて響いてくることはなかなかないと思うのですが、そういう懸念(?)とは完全に無縁の1曲でした(まあ原曲は全然知らなかったのですが)。

次は、アレンジ/作曲の立場が代わり、「歌ってみた」の元ネタがピアノ曲、です。「歌ってみた」を色々漁るようになったのは一昨年あたりからだったと思いますが、今年最も多く聴いていたのはコレです。コンテンツツリーを辿って、50曲を超える「歌ってみた」の大半を聴いたと思いますが、これが一番自分の好みに合っていたと思います。(わたしの場合、ボカロ自体には思い入れがほぼ皆無なので、気になったボカロ曲があると、まずコンテンツツリーを見て、好みに合う「歌ってみた」動画を探します。)

純粋に感覚的な好みでしかなく、あれこれ書けることはないのですが、どちらも、発見してからほぼ毎日聴いていて、わたしの穏和な日常の源泉でもあったと言えるでしょう。

暗鳴ニュイ

実のところつい一昨日発掘したばかりなのですが、こちらは音楽というよりUTAU音源として衝撃を受けたものでした。とりあえずこちらから:


《Anna Nyui candyVCV》FREELY TOMORROW《New VoiceBank》

曲自体は、2011年に初音ミクの神調教で話題になったやつ、のカバーですが、何がすごいかって、UTAUの特性を活かして、独自の「特殊音素」をいくつも録音した音源を作成・公開していて、この曲自体は、それ自体デモのひとつに過ぎない(!?)ところです。 動画の中で説明されていますが、喉切り母音連続音、長音母音、長子音CVVC、語尾息、特殊語尾息、喉きり語尾、舌きり語尾、といった、人間の歌唱において自然に出る(とされる)特徴のバリエーションをもつ原音を録音しているわけで、それだけでもかなりの作業量になりそうな気がします。(わたしは自分ではやったことないから本当のところは分からないわけですが、周りには録音作業をやっているグループもあるので、そこから類推するとやはり大変そう…) 詳しくは動画の中で解説されているので、ぜひ見てみていただきたいと思います。他の曲の調教解説も面白いです。

今のは連続音の音源を使った例ですが、次のCVVCのサンプルはもっとすごい。


《Anna Nyui》文学者の恋文 The Writer's Love Letter《UTAU cover》

典型的な「神調教」動画で感じるような「人間が歌っているみたい」とは性質が違う。まるで人間が感情を込めて歌っているように聞こえる。「ボカロ曲なんて『歌ってみた』で人間が情感を込めて歌ったものの魅力には絶対かなわん」というわたしの固定観念をあっさり飛び越えていった1曲です。そうか、情感はプログラムできるのか。ETMLを使わなくても。人間たるわれわれにはクオリアしか残されていないのか…

戯言はどうでもいいとして、音源を自力で作りこんでプログラマブルに表現力を広めていくというこのプロジェクトは、エンジニア的に大変魅力的です。音源ドライバやコンパイラを自作していた20世紀のコンピューター作曲家たちを見ているかのような気持ちになりました。

(まあ、あとこの1曲については、原曲の完成度が高いのも、繰り返し聴ける大きな要因だと思います。)

あと、音源だけでもすごいのに、このキャラクターコンテンツを全部1人で作られているっぽいの、本当にすごい。ルネサンス期万能主義の芸術家かよ!みたいな。

東京ザナドゥ

毎度Falcomのゲームなので、まあいつも通り遊ぼう、程度のつもりで始めたのですが…かなりしてやられた作品でした。このゲームの根幹にあるのは「立川の町おこし」なんですね。falcomはずっと本社を立川に構えている会社なので、思い入れがあるのでしょう。作中には、冒頭の立川駅の風景に始まり、「地元を知っていれば分かる」感じのシーンがたくさん登場します。作中のvenue紹介も(それぞれはほぼ現実には正確には存在しないものなのですが)いちいちそれぞれの魅力を伝えてくるようなテキストになっているんですね。エンディング画面に、全然本編で登場しなかった花火の絵まで出してくる辺り(リアルでは毎年昭和記念公園でやっているやつですね)、本当はもっと出したいものがあったのかもな、と思わせてくれます。(まあシネマシティは出てきませんでしたがw)

それでわたし自身も、あの近辺の学校に通っていたので、立川にはけっこう思い入れがあるのです。覚えている場所が出てくるたびに、ぉぉ、と思いながら進めていたものでした。間が悪いことに、その時は台湾で暮らしていた頃だったので、「もう早く東京に帰って立川を見に行きたい」と思う一方でした。それで結局台湾の居場所を引き払って東京に戻ってきてしまったわけで、たいへん罪作りな作品だったと思います(!) まあその、"立川は東京に含まれるのか問題"が無くもないですが

あと音楽もいいものが多かったと思います(曲数が抑えられていて = 粗製濫造になっていなくて良かった)し、それらの使われ方が上手かったですね。2015年にもなって未だにOPN由来っぽい音色をBGMに使っている辺り、変わらんなあと思いました。

また来年

今年は紹介数が控え目になりましたが、歌モノの動画はニコ動のマイリストだけでも30本くらい新しく追加されていて、それにyoutubeとかのものも加えて全部書いていたらキリがないので、これくらいにしておきたいと思います。

また来年も血沸き肉踊る楽しい作品に出会えることを楽しみにしています。

dotnetはどのように作られているのか

2017/03/21追記: この情報も大分古くなったので、現時点での最新情報は藤原さんによるこちらのエントリを参照すると良いでしょう。

Windows & Microsoft技術基礎Advent Calendar、25日目のエントリーです。最終日に相応しく、壮大な釣りタイトルを用意しましたが、ここでいう dotnet とは、.NET Coreにおけるコマンドラインツール dotnet のことです。

dnxに代わって最終的な.NET Coreの中心的な機能をコマンドラインで実現する予定であるこのコマンドは、.NET Coreの基礎を担う存在となるはずです。

そしてこれはオープンソースで公開されているのですから、自分でビルドすることもできるはずです。また、オープンソースディストリビューションオープンソースコンポーネントとして含まれるためには、その構成要素が本当に全てオープンソースで実現できているのか、確認する必要があります。

そういうわけで、今回は dotnet/cli リポジトリをチェックアウトしてビルドし、その内容を調べてみました。 https://github.com/dotnet/cli

はじめにお断りしておきますが、今回言及する一連のモジュールのビルドには、相応のリソース(ディスクスペース、ネットワーク)がかかります。実験するなら、家に引きこもって試す、大容量ストレージを用意する(札束で殴ってSSDを入手するか、HDDのI/Oでも良しとする忍耐心を身に付ける)等のノウハウを身につけてからが良いでしょう。

にわかの調べ物なので、適宜ツッコミ等お待ちしています。

dotnet/cli - dotnetのパッケージをビルドするツール

cli のREADME.mdの最初にはこう書いてあります:

This repo contains the source code for cross-platform .NET Core command line toolchain. It contains the implementation of each command, the native packages for various supported platforms as well as documentation.

このリポジトリには、コマンドラインツールチェインのソースコードが含まれている、と書いてあります。実際の役割は、(昔の).NET Framework SDK Tools、のサブセットのような感じです。実際のツールはほぼdotnetのみです。もっとも、この中には、C#/VBコンパイラーの呼び出しのためのdotnet-compileにはじまって、.NET Native化(dotnet-compile-native)、リソースのコンパイルdotnet-resgen)、配布パッケージ作成のためのdotnet-publishなど、さまざまな機能が実装されています。dotnetコマンドラインヘルプにresgenコマンド等は出てきませんが、dotnet resgenを実行すると、dotnet-resgenが呼び出されます。(実質的に単なるシェルスクリプトエイリアスっぽく見えますが、形式的には.NET Native化された別々のバイナリです)

実は、dotnet/cliリポジトリには、ツールの実体ソースはそれほど含まれていません。このリポジトリでビルドできるのは、インストールできるパッケージです。たとえば筆者の環境では、Ubuntu用の.debパッケージが出来上がります。WindowsならWixによるインストーラー パッケージが、OSXならproductbuildによる .pkg 形式のパッケージが、それぞれ出来るはずです。rpm系のパッケージビルダーはまだ無いようです。最近Microsoftと提携したRed Hatとか、コミュニティの誰かがcontributeすれば出来るのではないでしょうか。

では、dotnetパッケージの内容となる各種ツールはどのようにビルドしているかというと、実は重要な部分の多くは、ソースからのビルドを行っていません。代わりに、プライベートのnugetパッケージ リポジトリなどから、ビルド済みのバイナリをダウンロードしてきて、それをパッケージしています。実のところ、ビルドに必要なものを落としてくる方式は、.NET Core関係のリポジトリ群における標準的なものです。

dotnet/cliをチェックアウトして、build.shあるいはbuild.cmdを実行してみましょう。最後まで上手くいくと、パッケージがartifacts/packages/以下に作成されるはずです。

dotnetパッケージの内容

ではdotnetパッケージには何が含まれているのでしょうか。build.shを実行するとsudoパスワードを要求されて.debのパッケージまでインストールされますが(こわい!)、ここでインストールされたdotnetパッケージの内容を dpkg -L dotnet で見るとこうなります。 https://gist.github.com/atsushieno/78c2f5aef6477c3337a9

500行くらいあるのでgistにしましたが、内容はほぼ /usr/bin/dotnet*/usr/share/dotnet/* のみです。binの内容はこの通りただの /usr/share/dotnet/bin 以下へのシンボリックリンクなので、実質的に全てshare/dotnet以下に入っています。

ではこのディレクトリの中には何が入っているのでしょうか。少しずつグループに分けて見て行きたいと思います…が、無駄に長いので、次の節に進む前の「まとめ」だけ見ると良いと思います。

(1) /usr/share/dotnet/runtime/coreclr

ここには、coreclrの内容が含まれているようです。coreclrのソースは dotnet/coreclr にあります。

(2) /usr/share/dotnet/bin/corehost

以下、いくつかのファイルは、dotnet/cli 直下でビルドされ、dotnetの各コマンドの実装で使われています。このcorehostは、.NET Coreのホスティング環境で、配布パッケージに埋め込まれるものです。続くdotnet-run.dllは、dotnet runコマンドの実装です。

(3) /usr/share/dotnet/bin/Microsoft.Extensions.FileSystemGlobbing.dll

以下、いくつかのファイルは、dotnet/cli に含まれるツールの依存関係です。このdll自体は、githubのaspnet/FileSystem以下にあるモジュールで、dotnet-run.dllのソースで依存関係としてproject.jsonで指定されています。

(「いくつかのファイル」と書きましたが、FileSystemはdnxの唯一のsubmoduleでもあるので、もしかしたらこれだけが特別かもしれません。)

(4) /usr/share/dotnet/bin/dnx

このディレクトリには、ビルドスクリプトで直接ダウンロードされたdnxのパッケージが展開されます(ビルドスクリプトOSX/Linux用のshellとWindows用のpowershellで別々ですが、だいたい同じ処理内容になっていると思います)。dnxのソースはaspnet/dnxにあります。

(5) /usr/share/dotnet/bin/csi

csi。roslynに入っているC# interactiveです。dotnet-repl-csiを実装するために使われているのでしょう。roslynのソースはdotnet/roslynにあります。

(6) /usr/share/dotnet/bin/crossgen

crossgenは、ネイティブイメージの生成に使用されるクロスコンパイラーです。これは、.NET Nativeの実装…ではなく、従来のngenの実装(あるいはその一部)で、coreclrに含まれるツールです。

(7) /usr/share/dotnet/bin/libPortableRuntime.a

今度は(今度こそ).NET Nativeの一部です。.NET Nativeのソースはdotnet/corertにあります。他にもilc.exeなどcorert由来のものがしばらく続きます。

(8) /usr/share/dotnet/bin/dotnet-resgen.dll

この辺はdotnet/cliの一部で、dotnet-resgenを実装しています。

(9) /usr/share/dotnet/bin/csc.dll

ここからはだいたいroslynの一部です(たまにcliのバイナリも見られますが)。

(10) /usr/share/dotnet/bin/appdep

appdepというのは、実際にはdotnet-compile-nativeコマンドの機能のひとつである .NET Nativeコンパイラーの依存関係で、これ自体はnugetパッケージになっています。ソースとしてはcorertということになります。

パッケージ内容のまとめ

… 以上を総括すると、dotnet/cli の内容は、概ね次の各パッケージの内容を引っ張ってきていると言えます:

  • dotnet/coreclr
  • dotnet/corert
  • dotnet/roslyn
  • aspnet/dnx
  • aspnet/その他各種依存ライブラリ

dotnetのビルド

dotnetのビルドは、dotnet/cli/build.shを追いかければ分かると思いますが、3ステージに分かれています。 - stage0: stage 1 dotnetをビルドするためのツールをダウンロードします。主にscripts/compile.sh - stage1: dotnetをstage 0の(ダウンロードした)dotnetでビルドします。主にscripts/build/build-stage.sh - stage2: dotnetをstage 1のdotnetでビルドします。その後roslynにcrossgenをかけたり、.NET Nativeの依存関係(appdeps)をかけ、dotnet publishで最終的なパッケージ内容を構築します。

stage 1 buildを実行するbuild-stage.shの中で、各.NET Coreプロジェクトをビルドしているのが、このパッケージのビルドの主要な部分と言えるでしょう。

dotnetの依存関係

さて、繰り返しになりますが、dotnetのビルドでは、以下のモジュールが(直接 or 間接的に)バイナリダウンロードされているらしいことが、前述の通り明らかになりました。

  • dotnet/coreclr
  • dotnet/corert
  • dotnet/roslyn
  • aspnet/dnx
  • aspnet/その他各種依存ライブラリ

実際には、これらのモジュールが連鎖的に他のモジュールを取り込んでいる部分があります。わかりやすい例としては、dnxが参照するcorefxが挙げられるでしょう。

また、各依存モジュールが、再帰的に自分自身を参照している場合があります。たとえば、corertのビルド時には、cliが生成するパッケージ(dotnet)がダウンロードされて使用されます。

というわけで、他のモジュールがどうやってビルドされているのかも多少追いかけないと、dotnetがどのようにビルドされてその世界を構築しているのか、わからないはずです。

それぞれの分析については今後の課題としたいところですが、このcliモジュールのビルドと各モジュールのビルドの間で齟齬がないか、確認する目的で、一応それぞれをビルドしてみました。以下に、各関連リポジトリのビルド出力のファイルリストを列挙しておきます。

ここまでの考察、と補足的な分析

(1) dotnetはdnxを置き換えるために導入されたのではなかったの? 何でdnxが使われるどころかパッケージにまで含まれているの? という疑問が生じてきますが、わたしは、現状ではdotnet runコマンドの実装はdotnetコマンドでまだ(?)実現できず、最終的にdnvmに相当する機能などが整備されたらdotnetに置き換え可能になるのではないか、と想像しています。.NET Coreは現在RCですが、これは機能的にフリーズということであって、パッケージングの調整などはこれから行われるのではないか、最終バージョンに含まれるようになるかは分からないだろう、という感じで理解しています。

(2) パッケージの中にいくつかファイルの重複が見られますが(libcoreclr.soはいくつあるの?)、これは、それぞれのプログラムをdotnet publishで生成した結果であろうと思います。その意味では.debの内容を細かく分けて分析する意義はあまりなかったかもしれません(!)

同じことが、この cli 以外の各モジュールについても言えます。roslynのパッケージにはcoreclrやcorefxのファイルが含まれていますが、おそらく大半はdotnet publishでバンドルされたものであって、roslyn自身の実体は、csc, csi, vbc, Microsoft.CodeAnalysis.*.dllくらいでしょう。

(3) バイナリパッケージをダウンロードしてきてビルドするというのは、ビルドに無駄な時間がかからない、依存関係で破綻する可能性が少し低くなる、といったメリットはありますが、同時に、どこまで本当にオープンソースでビルドできるのか分からない、という問題もあります。たとえば、上記のリストからはroslynのUbuntuビルドにcsi.exeは含まれていない、ということが分かります(roslynのビルドは、WindowsではRoslyn.slnを、それ以外の環境ではCrossPlatform.slnを使用するので、その辺りで齟齬があるのでしょう)。これはWindowsでビルドされたものが巡り巡ってバイナリとしてUbuntuに含まれている、ということでしょう。この辺りは解明・解決しておかないと、Linuxディストリビューションオープンソースのパッケージとして含まれることができなくなってしまう可能性があります。

dotnetはそのビルドの性質から、既存のdotnetバイナリ パッケージを前提としていますが、それはC#コンパイラとmscorlib.dllがC#で書かれているmonoなんかもそうですし、現在ならコンパイラツールチェイン全般に言えることだと思います。オープンソースのツールチェインによってビルドできるようなソースが存在することが自明であれば十分であり、卵と鶏問題を厳密に追及するのは、ライセンスの観点からは意味がなく、実質的には非生産的です。)

(4) coreclrのビルド出力を見ると分かりますが、この中にはcorefxのアセンブリは含まれていません。一方、cliのパッケージの内容としては、dotnet/runtime/coreclrディレクトリ以下にmscorlib以外のcorefxアセンブリ含まれています。これらはどこから来ているのでしょうか?

その答えはscripts以下で “runtime/coreclr” をgrepしたら、scripts/build/build-stage.shのみが引っかかったことを契機に分かりました。このスクリプトの中で、明示的にsrc/Microsoft.DotNet.Runtimeをビルドしているのですが、ここにはREADME.mdがあって、内容にはこうあります:

This is a utility project that brings the CoreCLR down and lets us publish it as though it were an app. Do NOT add any C# code to it! It is not designed to actually be compiled as an assembly, it's just used for its dependencies.

このプロジェクトがruntime/coreclrディレクトリを出力パスとしてビルドされると、ここにproject.jsonで記述された依存関係が展開されることになります。実のところ、dependenciesは次の1行のみです。

"dependencies": {
  "NETStandard.Library" : "1.0.0-rc2-23616"
},

この"NETStandard.Library"のパッケージ、実体はcorefxのstandard platformに対応する"netstandard"のことだろうと思うのですが、どのモジュールから生成されているのか、今回は発見できませんでした。corefx(少なくともmaster)には無さそうです(nuspecが見当たらない)…ここにあるべきだとは思うのですが。

(5) corefx自体は膨大なアセンブリの集積であり、dotnetでは全てをパッケージすることはありません。各アプリケーションに必要なものは、project.jsonなどに記述すれば、dotnetコマンドがnuget経由でダウンロードしてくることになるでしょう。

dotnet/coreclr and co.

さて、今回、先ほど言及した、ダウンロードされてくる.NET Coreモジュールの全てについて、厳密にビルドを追いかけるのは、ちょっと現実的ではありませんし(何しろ書こうと思い立って調べ始めたのが3日前くらいですし!)、今回はあとdnxについて軽く言及する程度にしておいて、他のモジュールについてはざっくりと書いておこうと思います。

coreclrは、Cで書かれたランタイムであり、元来このモジュールだけで全て完結していました。mscorlibのビルドは(cscを使って)全ての実装がビルドされていました。これが、昨今ではそのソースをcorefxに移転しているようです。mscorlibの実装はやや特殊であり、ランタイムと密結合している部分が多いので、coreclrの一部となっていたわけですが、いずれにしろcoreclrとcorefxは切り離せない関係にあると言えるでしょう。

corefxのリポジトリには、coreclrをターゲットとする(けどdotnetで必須というわけではない)大量のアセンブリがあり、それらはnugetパッケージとしてビルドされます。実は、おそらくビルドの最終生成物はbinとpackagesの両方のディレクトリにあると思うのですが、今回はbinの内容だけを出して、packagesの内容は含めませんでした。ここにはcorefxのビルドに必要な依存関係もダウンロードされているようなので(たとえばdnx-monoやMSBuild.exeなど)、何がビルド出力なのか自明ではなかったためです。気になる人は一度ビルドしてみて下さい(ビルド作業は長大なものですが…)

corertは、ビルドに際してこのdotnetモジュールに依存していたりと、内容を精査してみないと分からない部分がありますが、ネイティブコンパイル機能自体は、ランタイムに必須の機能というほどでもないので、今回は調査対象外としました。個別に後で追いかける価値は、あるでしょう。

aspnet/dnx

dnxはgithub上ではdotnetではなくaspnet配下にあります(歴史的な事情によるものでしょうか)。

dnxのビルドにはKoreBuildとSakeというビルドシステムが使われます。これらはnugetパッケージとして取得されます。KoreBuildにはdnxが含まれており、つまりこのモジュールも鶏と卵の関係にあります。ちなみにnuget.exeもバイナリダウンロードされます。

KoreBuildは、おそらくSakeの応用として作られた、.NET Coreに特化したビルド構成ファイル群なのでしょう。KoreBuildのソースは、源流がどこにあるのかわたしには確認できませんでしたが、aspnet/Universe/KoreBuild-dotnetに一連のソースがあるようです(devブランチであり、masterにはありません)。

dnxに限らず、dnxを使うモジュールをビルドする際に気をつけておきたいのが、使用するdnvmのランタイムとバージョンです。Ubuntu環境であれば、現状coreclrではまだビルドできません。実のところ古いdnx-monoでも、dnxのビルドは失敗します。わたしは1.0.0-rc2-16348を使って何とかビルドできました。

ちなみに、dnxのビルドにはdnxが必要です。おそらくSakeがdnxで動作するのでしょう。dnxがビルドするプロジェクトは、その実行に必要なファイルを、dnx自身からコピーすることになります。ではdnxでビルドしたプロジェクトでは、どういうファイルが必要になるのでしょうか? それらは生成あるいはコピーされるのでしょうか? ここは未調査ですが、おそらくdotnetコマンドがMicrosoft.DotNet.Runtimeというダミープロジェクトをビルドすることで「ランタイム アセンブリ」のようなものを構築したのと、同じことが行われているのではないかと思います(つまり、project.jsonの内容に照らして、無いものはnugetからダウンロードしてくる、ということでしょう)。

いずれにしても、わたしの理解としては、dnxの使用は、ある程度過渡的なものであり、役割としても、ビルドの性格としても、概ねdotnetと重複するものであって、コレを別途追求する意義はあまりないのではないか、といったところです。

(Sake/KoreBuildが過渡的なものなのかどうかは、今は判断保留としておきます。)

総括など

ここまでざっと見てきたことで、dotnetツールが、全てをソースからフルビルドしているのではなく、関連モジュールの既成バイナリをnugetからダウンロードしてきて、それを展開するかたちで構成されていることが、そして、それぞれのビルドについて、適切にオープンなソースからビルドされたものが最終的に含まれているのかを調べる道筋が、何となく理解してもらえたのではないでしょうか。

今回調べたようなことを、CoreCLR読書会というグループで勉強会のようなかたちで共有しています。CoreCLR Book of the Runtimeの翻訳などもそこで行っています。興味のあるマニヤックな皆さんの参加をお待ちしています。そのうちまた開催すると思うので、twitterにアンテナでも張っていてください。

M is for MIDI (c88)

今年の夏コミ(C88)に、TechBooster(「てくぶ」)という技術系サークルで出す、新刊4冊のうちの1冊、Android Mの最新情報をまとめた本に、Android Mで新しく追加されたMIDI APIについての記事を寄稿しました。

techbooster.github.io

執筆者が全員入った表紙があるとのことで、さり気なくわたしもいるみたいですよ。分かるかな…?

同人誌向けの原稿、これまで書いたことがなかったわけではないのですが、だいたい原稿をテキトーに書いて渡したらそれでおしまい、くらいの軽いノリでいたわけです。そしたら、このグループの人たち、原稿の書式はRe:VIEWを使います、文章の望ましい書き方はこれこれこうこう、書き終わった後にクロスレビューをやります…と、えらいガチなんですね。なるほど、作業フローこそサークル前提だけど、こうやってクオリティを上げているのね…と感嘆したものでした。

そんなわけで、7月はのんびり日本をエンジョイ()しようと思っていたわけですが、この辺の作業で思っていたより忙しく過ごすことになっちゃいました。

わたし書いた内容ですが、本当はMIDI APIを使ったawesomeなライブラリも合わせて実装して出したかったのですが、そこまで気軽に出来るスケジュールでもなかったので、モバイルのMIDIを取り巻く状況の話と、新しいAPIの使い方の話が中心です。Android SDKのサンプルにすら含まれていないので、地味にコードを書いて調べたりissuesにレポートを登録したりしながら書きました。*1

3日目(8/16)は、わたしはCOSCUPに参加していて日本にいないことになっているので、現場にはいない予定ですが、興味のある人がいたらぜひ見ていって下さいませ。

coreclr関係もろもろ

Open .NET technology explained at COSCUP 2015

これは告知してもしょうがないのですが、8/16に台北で行われるCOSCUP(オープンソース技術系カンファレンス)で、オープンソース化した.NET関係の技術について、40分ばかり雑談してきます。

Schedule 議程 | 2015 COSCUP

今 年でセッションは3年目なのですが、monodevelop -> mono -> .NET と、だんだん話が大きくなって希薄化している感はありますね…個人的には細かい部分を掘り下げるほうが楽しいのですが、まあ正直台湾のOSS方面では現 状.NETネタを受け入れてもらうのも一苦労だと思うので、エントリーレベルの話から始めたほうがいいのかもしれません。(あれ、エントリーレベルの話な んてする気あったっけ…?)

参加申し込みももう締め切られているので(というか公開後ほどなく満員御礼になっちゃうんですよね)、万が一興味があるという方は、後日の資料公開などを期待していて下さい。

coreclr Book of the Runtime日本語訳プロジェクト

そんなわけで、coreclrやらcorefxやらroslynやらの調べ物をしようと思って日々過ごしているわけですが、最近気付いたもので、coreclrのリポジトリの中に、"Book of the Runtime" (BotR) と呼ばれるドキュメント集があって、.NETランタイムの内部設計についていろいろ解説してあるのです。これはなかなか興味深い。ランタイムの各コンポーネントの担当者がまとめた文章を集めたものであるらしく、コードの詳細までは踏み込まないけど、内部実装の理解がそれなりに得られるものだと思います。

 

というわけで、少しずつ読み解きながら翻訳してみたいと思っています。翻訳したドキュメントは、このリポジトリに置いておきたいと思います。翻訳を手伝っていただける方は随時募集しています(既にわたしだけのプロジェクトではないです)。

github.com

 

このBotR、FAQを見てもらえれば分かるかと思いますが、基本的には文書作成時からほとんど加筆修正されていないものであるようです。なので、古い内容のものもけっこうあります。とはいえ、ランタイムの基本的な構成要素、たとえば型システムなどはそうそうリニューアルされないので、それで困ることは多分あまり無いでしょう。一方でRyuJITみたいな、新し目のコンポーネントについての文書もあります。翻訳しながらじっくり読むと、勉強になるかもしれません。

coreclrをUbuntu 14.04だけでビルドする

で、調べ物をするにあたって、やっぱりcoreclrもcorefxもビルドして動かしたいと思ったわけですが、わたしの作業環境はLinuxで、どうやらcoreclrのビルドにはWindowsが必要なんだそうです。

 

blog.shibayan.jp

www.atmarkit.co.jp

えー。Windows機、ありますけど、いちいち起動してビルド環境をセットアップしてビルドするのは、ちょっとめんどくさいですね。 しかも、もしmscorlibの実装をちょっとだけ修正してビルドしたいと思っても、毎回これをやることになるわけですね。めんどくさい。

mscorlib.dllはマネージドコードだからビルドする環境が無い、というのは確かに分か…あれ? でもcorefxはLinuxでもビルドしますよね。何でcoreclrのmscorlibで同じことをしないんでしょうか? もしかして単に手が回ってないだけなんでは?

…というわけで、corefxのビルドスクリプト(主にMSBuildの大盛りtargetsスパゲッティ…)を見ながら、半ばコピペでmscorlibもビルドできるようにしてみました。

https://github.com/dotnet/coreclr/pull/1275

実際に完成させるところまでやって気付いたわけですが、けっこう大変ですね。他のcorefxのライブラリのビルドと違って、mscorlibはrc.exeの呼び出しとか、色々なバイナリ書き換えとか、チマチマとWindows依存のビルドステップが入ってきます。主にそれらを取り除く作業となりました。roslynを使ったビルドでも、デバッグシンボルを生成しようとするとpdb生成はCOM依存なので落ちるとか、割と厳しい感じです。

実のところ、何とかビルドできたmscorlib.dllでhello world的なコードを動かせて、パッチをコミットしてpull requestを送った後も、実はビルドの一部(crossgen)がクラッシュしていたとか、バイナリ書き換え(BclRewrite)がかからないと何処でエラーが出て落ちるか分からんみたいな事情があるようで、取り込んでもらえるかどうかは、雲行きが怪しいところです。BclRewriteは何でクローズドソースなんじゃあ、とか、コミュニティからも改善要望が出ていて、Microsoftも方針を決めかねている状態であるようです(ということは、よっぽどWindows依存なんだろうなあ)。とりあえずクロスプラットフォームまわりの深淵を覗きこんだような感じでした。

…とまあ、その辺の話を(盛り込む余裕があれば)COSCUPでしてこようかなあと思っています(そのための調べ物だった)。

llilcについて

Microsoftがcoreclrまわりの新しいネタを投入してきましたね。LLVMを.NET Coreで使うものだそうです。

github.com

"an LLVM based compiler for .NET Core." 何だかよくわからないですね。

llilcは、.NETで言えばランタイムの一部分の一種であり、99%の.NET開発者には意識する必要のないプロジェクトです。

.NETランタイムには、MSILを解釈して、実行マシン上のCPUネイティブコードに変換して実行する機能が求められます。いわゆるJITコンパイラーというやつです。LLVM based "compiler"というのは、このJITコンパイラーのことです(RoslynみたいなC#コンパイラーとは、取り扱っている問題が違います)。

オープンソースで公開されているcoreclrには、現在、RyuJITというJITコンパイラーがあります。このJITコンパイラーは差し替え可能なcoreclrの部品なので す。llilcは、その代替候補のひとつとなります。Javascriptの世界では、よく新しいJITが導入されて(v8, spidermonkey, chakra, ftljit…)、そのパフォーマンスが議論されますが、MSIL JITの世界でも同じことが起こっているということですね。

これらのJITの実装にはさまざまな特徴があり、Javascriptの世界だと、大概は「新しいほうがパフォーマンスが良い」みたいな文脈で語られますが、実際には一長一短の世界でもあります。RyuJITはWindowsで動作する.NETのMSILに特化したJITとして開発されてきたものであり、MSILを最適に実行できるJITとして在るのだと思いますが、LLVMほど多様な環境を前提としてはおらず、移植性(あるいは「可能性」)は、LLVMほど高くはないでしょう。

JITで活用されるLLVMフロントエンド、とは何なのか?

llilcはLLVMフロントエンドのひとつとして実装されています。この意味が分かる人は、ここからしばらく読み飛ばしてもらっても大丈夫ですが、LLVMについてよく分かっている人は多くないと思うので、この辺で少し解説しておこうと思います。

LLVMは "compiler infrastructure" なのですが、LLVMが主にターゲットにしている「コンパイラー言語」は、ネイティブコードを直接生成するC++のような言語です。われわれは、コンパイラーを作成する時、まずソースコード構文解析してシンタックス ツリー(AST)を構築し(文法エラーなどをレポートし)、そのASTを解釈してコードのセマンティック モデルを構築し(おかしなコードの定義や参照をレポートし)、そこから仮想的な実行命令(IR*1)の集合を生成します。この実行命令の集合は、プラットフォームやアーキテクチャに特化していないもの(そのようにあることを意図したもの)であり、実行するためにはこれを各プラットフォーム/アーキテクチャのネイティブコードに置き換えるものが必要です。

LLVMでは、この仮想的な実行命令の集合を構築するまでの部分をLLVMフロントエンド、仮想的な実行命令の集合からCPU固有のネイティブコードを生成する部分をLLVMバックエンドと呼びます。これらが切り離されていることで、LLVMは、多様なコンパイラー言語(のLLVMフロントエンド)から、さまざまなプラットフォーム用の実行コードを(LLVMバックエンドで)生成できるような "compiler infrastructure" であるわけです。例を挙げるなら、AppleObjective-Cコンパイラはフロントエンド、emscriptenのようなプロジェクトは(特殊な)バックエンドですね*2

LLVMフロントエンドが.NET Coreをサポートするというのは、まだよくわかりませんね。.NETはMSILを実行するためのものです。LLVMコンパイラーです。llilcはC#ソースコードを解析するLLVMフロントエンドなんでしょうか?

そういうことではありません。llilcにとっての「ソース」は、C#ではなく、MSILなのです。そして、llilcはコンパイラツールとして使われるわけではないのです*3C#からMSILを生成するのは、これまで通りC#コンパイラー(csc, mcs, roslyn)の仕事です。llilcは、CoreCLRにおけるJITコンパイラーとして使われます。言い換えれば、LLVMはllilcのJITコンパイラインフラストラクチャー」となるわけですね。

ちなみに(ここに来てようやく)monoの話をしますと、monoにも、開発初期からずっと存在しているMSILのみをターゲットとするコード生成エンジンと、LLVM IRを生成するmono-llvmエンジンのふたつが存在します。これらは、JITの側面では、概ねRyuJITとこのllilcの関係に近いと言えるでしょう。mono-llvmはmonoのエンジンに比べてサイズが大きく、Xamarin.Androidのような環境では、まだデフォルトとしては使えません。

(ちなみにmonoの実装の中では、"LLVM Backend"という表現が使われていますが、monoの実行エンジンのbackendという意味であって、mono-llvmLLVMの世界におけるLLVM backendとして実装されているわけではありません。あーややこし。)

AOT実装について

JITのコード生成部分が差し替え可能な環境でしばしば挙げられる目標として、ネイティブコードに直接変換した上で実行できるような事前コンパイル(AOT; ahead of time compilation)が挙げられます。llilcは意欲的で、このAOTサポートも目的の一つとしています(まだ出来ていません)。動的コード生成がAppleによって独占されているiOSのような環境で使おうと思うと、AOT対応が必須になってきます。

llilcが特に興味深いのは、コード生成部分だけが異なるmono-llvmとは異なり、llilcのAOTはcoreclrを実行時に組み込む前提としていないところです。llilcのアーキテクチャ ドキュメントには、JITとAOTのモデルが図示されているのですが、

llilc/llilc-arch.md at master · dotnet/llilc · GitHub

AOTの方にはCoreCLRのブロックが見当たりません。アーキテクチャのドキュメントでは、詳しいことはこれから書く、みたいに書かれているのですが、どうも実行エンジンそのものがcoreclrから独立している感じですね。そのせいか、llilcで実行する場合にはメモリ管理をどうするか(LLVMに含まれるGC実装を使う)、とか、例外のpropagationをどうするか、とかいった話が、割と詳しく書かれているようです。

(これらはAOT固有の話というわけではなく、coreclrに実行エンジンを組み合わせる場合にはここから実装しなければならないということかもしれません。monoのLLVMサポートでは、独自にメモリ管理まわりを繋ぎ込んでいることは ない よう です。)

この辺は今後出てくるドキュメントとコード次第ですね。

ちなみに、RyuJITに対応するAOTは今のところ存在しないと思いますが、.NETの世界では、.NET Nativeというものがあって(と言っても正式版はまだでしたか)、.NETのコードをネイティブアプリケーションにして配布できるようになっているのですが、あれもAOT技術のひとつなので、coreclrのメインストリームにおけるAOTの実態は既にあるか、準備出来つつあるということなのではないかと思います。

というわけで、llilcがどんな位置付けにあるのかをざっと解説してみました。LLVMを使うことで、RyuJITでは手が回らないようなプラットフォーム / アーキテクチャでも.NET Coreのコードが動くとなると、なかなか魅力的である気がします。

まあ、マネージドコードを書くだけの開発者にとっては、これで大きく可能性が広がったというわけでは特に無くて、主に、ランタイムを.NETが動かないプラットフォームに組み込んで使いたい人なんかが、こういったプロジェクトで恩恵をこうむるんじゃないかとは思います。

*1:intermediate representation https://idea.popcount.org/2013-07-24-ir-is-better-than-assembly/ が参考になるでしょう

*2:「プラットフォームの実行コードとして」Javascriptを生成するわけですね

*3:最終的には、AOTコンパイラーとしての部分とroslynを繋ぎ合わせて、ソースから実行ファイルを生成するようなツールが作られるかもしれませんが、ここで書いていることはそういう話ではありません

JXUG #4で Java Bindingの話をしてきました

書くの忘れてた!

もう終わってしまったネタですが、先週末にJXUGでちまちまとしゃべってきました。

jxug.connpass.com

スライドも公開してあります。

speakerdeck.com

後半は割とworldwideでも喋られていないレベルで掘り下げてあります(かつて主に実装していたのが自分なので…)。Javaバインディングまわりは意のままにならず気に入らない部分も多いのですが、まあ現状の紹介としてはこんなものでしょう。

実際にバインディングのDLLを作るという目的を達成するところまで辿り着けるかは、かなり運次第なところもあるのですが、なんかしらの参考になればと思います。