Skip to content

Conversation

@jtschuster
Copy link
Member

Implements the alternative to #121138 mentioned in #121138 (comment)

Enables the TypeMap to be used in Library output types. Projects can set the following RuntimeHostConfigurationOption to enable this behavior. If it exists, this option takes priority over the entrypoint assembly.

<ItemGroup>
    <RuntimeHostConfigurationOption Include="System.Runtime.InteropServices.TypeMappingEntryAssembly"
        Value="$(TypeMapEntryAssembly)"
        Condition="$(TypeMapEntryAssembly) != ''" />
</ItemGroup>

@github-actions github-actions bot added the area-Tools-ILLink .NET linker development as well as trimming analyzers label Nov 10, 2025
@dotnet-policy-service dotnet-policy-service bot added the linkable-framework Issues associated with delivering a linker friendly framework label Nov 10, 2025
@dotnet-policy-service
Copy link
Contributor

Tagging subscribers to this area: @dotnet/illink
See info in area-owners.md if you want to be subscribed.

@jtschuster jtschuster marked this pull request as ready for review November 12, 2025 17:51
Copilot AI review requested due to automatic review settings November 12, 2025 17:51
Copilot finished reviewing on behalf of jtschuster November 12, 2025 17:53
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR implements a new feature that enables the TypeMap entrypoint assembly to be configured via a RuntimeHostConfigurationOption, allowing TypeMap to be used with Library output types instead of only executable output types. The change provides a way to specify which assembly should be scanned for TypeMap attributes when the entry point assembly is not appropriate (e.g., in library scenarios).

Key changes:

  • Added support for System.Runtime.InteropServices.TypeMappingEntryAssembly configuration option across the CoreCLR compiler, trimmer, and runtime
  • Modified the --feature flag in illink to accept string values in addition to boolean values
  • Added new tests to validate TypeMap entry assembly configuration works correctly

Reviewed Changes

Copilot reviewed 15 out of 15 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/TypeMapLazyDictionary.cs Modified runtime to check AppContext for TypeMappingEntryAssembly override before falling back to entry assembly
src/coreclr/tools/aot/ILCompiler/Program.cs Added runtime knob parsing to extract TypeMappingEntryAssembly and use it for TypeMap metadata
src/tools/illink/src/linker/Linker/Driver.cs Modified --feature flag to accept and store string values alongside boolean values
src/tools/illink/src/linker/Linker/LinkContext.cs Added Features dictionary to store string-valued features
src/tools/illink/src/linker/Linker.Steps/MarkStep.cs Added logic to check Features for TypeMappingEntryAssembly override
src/coreclr/tools/aot/ILCompiler.Trimming.Tests/TestCasesRunner/TrimmingDriver.cs Added comment explaining test behavior with entry assembly
src/tests/Interop/TypeMap/*.cs Added new runtime test files validating TypeMappingEntryAssembly configuration
src/tools/illink/test/Mono.Linker.Tests.Cases/Reflection/*.cs Added trimmer test cases and updated existing tests for renamed method

RuntimeAssembly? startingAssembly;
if (AppContext.GetData("System.Runtime.InteropServices.TypeMappingEntryAssembly") is string entryAssemblyName)
{
startingAssembly = Assembly.Load(entryAssemblyName) as RuntimeAssembly;
Copy link

Copilot AI Nov 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Assembly.Load can throw exceptions (e.g., FileNotFoundException, BadImageFormatException) if the assembly name is invalid or not found. Consider wrapping this in a try-catch block and providing a clear error message that includes the assembly name that failed to load, or let the exception propagate with additional context.

Suggested change
startingAssembly = Assembly.Load(entryAssemblyName) as RuntimeAssembly;
try
{
startingAssembly = Assembly.Load(entryAssemblyName) as RuntimeAssembly;
}
catch (Exception ex) when (
ex is FileNotFoundException ||
ex is FileLoadException ||
ex is BadImageFormatException)
{
throw new InvalidOperationException(
$"Failed to load assembly '{entryAssemblyName}' specified by 'System.Runtime.InteropServices.TypeMappingEntryAssembly'.",
ex);
}

Copilot uses AI. Check for mistakes.
if (Context.Features.TryGetValue("System.Runtime.InteropServices.TypeMappingEntryAssembly", out string? assemblyNameString))
{
var assemblyName = AssemblyNameReference.Parse(assemblyNameString);
startingAssembly = Context.TryResolve(assemblyName);
Copy link

Copilot AI Nov 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If Context.TryResolve returns null (assembly not found), the code falls back to the entry point assembly without logging or warning. Consider adding a warning message when the specified TypeMappingEntryAssembly cannot be resolved, as this could indicate a configuration error that should be surfaced to users.

Suggested change
startingAssembly = Context.TryResolve(assemblyName);
startingAssembly = Context.TryResolve(assemblyName);
if (startingAssembly is null)
{
Context.LogWarning(
$"Could not resolve assembly '{assemblyNameString}' specified by the 'System.Runtime.InteropServices.TypeMappingEntryAssembly' feature. Falling back to the entry point assembly.",
origin: null);
}

Copilot uses AI. Check for mistakes.
<ItemGroup>
<RuntimeHostConfigurationOption Include="System.Runtime.InteropServices.TypeMappingEntryAssembly"
Value="$(TypeMapEntryAssembly)"
Condition="'$(TypeMapEntryAssembly)' != ''"
Copy link

Copilot AI Nov 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The condition checks if TypeMapEntryAssembly is not empty, but line 6 always sets it to 'TypeMapLib5', making this condition always true. Consider removing the condition or explaining why it's needed for cases where the property might not be set.

Suggested change
Condition="'$(TypeMapEntryAssembly)' != ''"

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-Tools-ILLink .NET linker development as well as trimming analyzers linkable-framework Issues associated with delivering a linker friendly framework

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant