Quantcast
Channel: C#タグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 9297

corertのrd.xmlについて

$
0
0

始めに

dotnet coreでAOTでネイティブシングルバイナリを実現するための一つのツールとして、corertというものがある。
成熟度合でいうと絶賛開発中で、仕様もこれからいくらでも変わる可能性があるので、プロダクションで使えるかと言われるとお薦めはしないが、自分プロジェクトのちょっとしたツールでは色々と便利なので使っている。

この中でリフレクション関連の処理を行うための補助設定ファイルとしてrd.xmlというファイルがあるが、それについて現時点でどうすれば良いかという文書は無かったので、ここに書いておく。

なお、corertは現在開発中のライブラリであり、仕様変更も予告なく行うため、記事執筆時の最新コミットを参照して解説する。

corertにおけるリフレクション

corertはコンパイル時にネイティブバイナリを作成する関係上、リフレクション関連の処理に大きな制限がかかる。
しかし、昨今のC#の状況をみると、リフレクション関連の処理を全てNGとするのは非現実的(enum関連とか)なため、API呼び出しやフロー解析を用いて、コンパイル時にメタ情報を静的に作成して使用することで、一定の範囲でリフレクションAPIを利用できるようにしている。

しかし、自動的な解析だけではどうしても限界が出てくるため、予めメタ情報を保持しておくものを指定しておくファイルとして、rd(Runtime Directive).xmlが使用される。

この辺りの、API呼び出し+フロー解析+補助設定ファイルというのはGraalVMでも似たようなことをしており、AOTでは結局同じような手法に行きつくという事だと思う。

rd.xmlの出自

rd.xml自体はcorertのオリジナルではなく、.NET Nativeからのもの。
しかし、corertで使えるのはそのサブセットであり、全ての記法をサポートしているわけではない。

いつ書くべきか

Type.GetType()直呼び出し程度ならば、コンパイルの段階で自動検出してくれるので、記述の必要は多くの場合は無い。
しかし、自動検出されなかった場合、ネイティブバイナリ実行時にMissingMetadataExceptionTypeLoadExceptionが発生する
この時にrd.xmlを書くことを検討する。

書き方

  • Directivesを頂点として、その下にApplicationLibrary要素を追加する
    • 現時点ではどちらでも入れてOK
  • その配下にAssembly要素を追加し、属性としてそのアセンブリ名(System.Reflection.AssemblyName.Name)を指定
  • 配下にType要素を追加し、属性Nameに名前空間を含めたタイプ名と、属性Dynamicに`Required All"を指定する
    • corertでは今の所DynamicにはRequired All以外の記述は認められていない
    • メソッド指定のみ必要な場合は、Dynamic属性は付けなくてもOK
      • どのような効用があるかは今の所不明なので、とりあえずつけるという感じで良いかもしれない
    • ジェネリッククラスの場合、TypeName`1[[Type1,AssemblyName]]のような記述になる
    • インナークラスの場合、OuterClass+InnerClassのような記述になる
  • メソッドの指定をしたい場合は、Type配下にMethod要素を追加する
    • ジェネリックメソッドの場合は、更に配下にGenericArgumentを追加する
<Directivesxmlns="http://schemas.microsoft.com/netfx/2013/01/metadata"><Application><AssemblyName="My.Assembly.Name"><TypeName="Full.Typename"Dynamic="Required All"/><TypeName="Full.Typename2"><MethodName="Method1"/><MethodName="Method2>
                    <GenericArgument Name="System.Int32"/></Method></Type></Assembly></Application></Directives>

プロジェクト設定

rd.xmlはItemGroupにRdXmlFileを追加することで読み込んでくれる。
rd.xmlが不正なフォーマットだったり、クラス指定等が間違っていると、コンパイル時に例外として捕捉される。

終りに

簡単ではあるが、corertのrd.xmlについて書いた。
corertは、ネイティブバイナリ実行時にしか出ないエラーがあったり、何も言わずにSEGVで落ちる場合等があるので、お世辞にも現時点では使いやすいとは言えないが、PublishSingleFileよりもコンパクトにまとまったり(1-10MB程度)、初回起動が非常に早かったり(ほぼCのネイティブバイナリと変わらない)するので、将来的に使いやすいものになると良いと思う。


Viewing all articles
Browse latest Browse all 9297

Trending Articles