Rd.xml in CoreRT

Andrii Kurdiumov
3 min readJan 31, 2021

ILCompiler by default lookup for types to be compiled starting from the entry point of the application. If application using reflection, that is not enough to make application running.
To help ILCompiler found types which should be analyzed rd.xml file can be supplemented. This is similar format as format used by .NET Native, but much more limiting.

Minimal Rd.xml configuration

<Directives xmlns=”http://schemas.microsoft.com/netfx/2013/01/metadata">
<Application>
<Assembly Name=”mscorlib” />
</Application>
</Directives>

ILCompiler supports 2 top level directives Application or Library. Right now, both of them can be used interchangeably and just define area where actual assembly configuration happens.
Developer can put multiple <Assembly> tags inside the <Application> directive to configure each assembly individually.

Assembly directive

There 3 forms how assembly can be configured:

  • Module metadata only,
  • All types,
  • Module metadata and selected types.

Module metadata only just need simple <Assembly> tag with short name of the assembly.

<Directives xmlns=http://schemas.microsoft.com/netfx/2013/01/metadata">
<Application>
<Assembly Name="mscorlib" />
</Application>
</Directives>

All types in the assembly require adding Dynamic attribute with value Required All. NOTE: This is only available value for this attribute.

<Directives xmlns="http://schemas.microsoft.com/netfx/2013/01/metadata">
<Application>
<Assembly Name="mscorlib" Dynamic="Required All" />
</Application>
</Directives>

Note that if you have generic types in the assembly, then specific instantiation would not be present in generated code, and if you need one to be included,
then you should include this instantiation using nested <Type> tag.

Option Module metadata and selected types based on module metadata only mode with added <Type> tags inside <Assembly>.

<Directives xmlns="http://schemas.microsoft.com/netfx/2013/01/metadata">
<Application>
<Assembly Name="MonoGame.Framework">
<Type Name="Microsoft.Xna.Framework.Content.ListReader`1[[System.Char,mscorlib]]" Dynamic="Required All" />
</Assembly>
</Application>
</Directives>

Types directives.

Types directives provide a way to specify which parts of code related to classes are needed. Developer can have two options here:

  • Take all type methods,
  • Select which methods should be rooted.

Take all type methods:

<Type Name="Microsoft.Xna.Framework.Content.ListReader`1[[System.Char,mscorlib]]" Dynamic="Required All" />

Example how to specify typenames

// just int
System.Int32
// string[]
System.String[]
// string[][]
System.String[][]
// string[,]
System.String[,]
// List<int>
System.Collections.Generic.List`1[[System.Int32,System.Private.CoreLib]]
// Dictionary<int, string>.KeyCollection
System.Collections.Generic.Dictionary`2[[System.Int32,System.Private.CoreLib],[System.String,System.Private.CoreLib]]+KeyCollection

Note that it likely does not make sense to have generic type to be placed here, since code generated only over specific instantiation of the generic type, and not for generic class.
Example of invalid scenario:

// List<T>
System.Collections.Generic.List`1

To select which methods should be rooted add nested <Method> tags.

<Type Name="System.Collections.Generic.Dictionary`2[[System.Int32,System.Private.CoreLib],[System.String,System.Private.CoreLib]]">
<Method Name="EnsureCapacity">
<Parameter Name="System.Int32, System.Private.CoreLib" />
</Method>
</Type>

or if you want to instantiate generic method you can pass <GenericArgument>.

<Type Name="System.Array">
<Method Name="Empty">
<GenericArgument Name="System.Int32, System.Private.CoreLib" />
</Method>
</Type>

Take not that methods distinguished by method name and parameters. Type of return value does not used in the method signature.

Excercises

Let’s try to apply that on practice.

Let’s start with task of serialization of following WeatherForecast class

public class WeatherForecast
{
public DateTimeOffset Date { get; set; }
public int TemperatureCelsius { get; set; }
public string Summary { get; set; }
}

Let’s create small function which perform serialization.

static void SerializeNonNullableProperties()
{
var weatherForecast = new WeatherForecast()
{
TemperatureCelsius = 15,
Summary = "Hot",
Date = DateTimeOffset.UtcNow,
};
string jsonString;
jsonString = JsonSerializer.Serialize(weatherForecast);
Console.WriteLine(jsonString);
}

To make CoreRT happy you should create following rd.xml file

<Directives xmlns="http://schemas.microsoft.com/netfx/2013/01/metadata">
<Application>
<Assembly Name="System.Text.Json">
<!-- for serialization of WeatherForecast -->
<Type Name="System.Text.Json.JsonPropertyInfoNotNullable`4[[CoreRtRdXmlExamples.WeatherForecast,CoreRtRdXmlExamples],[System.DateTimeOffset,System.Private.CoreLib],[System.DateTimeOffset,System.Private.CoreLib],[System.DateTimeOffset,System.Private.CoreLib]]" Dynamic="Required All" />
<Type Name="System.Text.Json.JsonPropertyInfoNotNullable`4[[CoreRtRdXmlExamples.WeatherForecast,CoreRtRdXmlExamples],[System.Int32,System.Private.CoreLib],[System.Int32,System.Private.CoreLib],[System.Int32,System.Private.CoreLib]]" Dynamic="Required All" />
</Assembly>
</Application>
</Directives>

if you interested how do I create these rd.xml. Basically, by trial and error. Without adding rd.xml and publishing application, I receive following runtime error:

Unhandled Exception: System.Reflection.MissingMetadataException: 'System.Text.Json.JsonPropertyInfoNotNullable<CoreRtRdXmlExamples.WeatherForecast,System.DateTimeOffset,System.DateTimeOffset,System.DateTimeOffset>' is missing metadata. For more information, please visit http://go.microsoft.com/fwlink/?LinkID=392859

This error indicates that class System.Text.Json.JsonPropertyInfoNotNullable<CoreRtRdXmlExamples.WeatherForecast,System.DateTimeOffset,System.DateTimeOffset,System.DateTimeOffset> was not compiled. As such I have to add it like that

<Type Name="System.Text.Json.JsonPropertyInfoNotNullable`4[[CoreRtRdXmlExamples.WeatherForecast,CoreRtRdXmlExamples],[System.DateTimeOffset,System.Private.CoreLib],[System.DateTimeOffset,System.Private.CoreLib],[System.DateTimeOffset,System.Private.CoreLib]]" Dynamic="Required All" />

Notice how JsonPropertyInfoNotNullable<TClass, TDeclaredProperty, TRuntimeProperty, TConverter> was converted to System.Text.Json.JsonPropertyInfoNotNullable`4 and subsequently generic arguments was declared like that [System.DateTimeOffset,System.Private.CoreLib] and [CoreRtRdXmlExamples.WeatherForecast,CoreRtRdXmlExamples] . Please notice, since classes DateTimeOffset and WeatherForecast does not located in System.Text.Json assembly you should provide name of the assembly where to CoreRT should look for these types.

Small example placed in following GitHub repository: https://github.com/kant2002/CoreRtRdXmlExamples

--

--

Andrii Kurdiumov

Math lover, lost in the woods of software development