Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
071efbd
[TrimmableTypeMap] Add GenerateTrimmableTypeMap MSBuild task and targets
simonrozsival Mar 12, 2026
aa3b259
Add unit tests for GenerateTrimmableTypeMap task
simonrozsival Mar 12, 2026
046de51
Add integration tests for trimmable TypeMap build pipeline
simonrozsival Mar 12, 2026
49b2322
Improve GenerateTrimmableTypeMap: extract methods, filter BCL, fail o…
simonrozsival Mar 12, 2026
0739767
Fix task return types, Java output dir, remove TrimmerRootAssembly
simonrozsival Mar 12, 2026
729f0d4
Add per-assembly timestamp check to skip up-to-date typemaps
simonrozsival Mar 12, 2026
3395f63
Add thorough incrementality tests for GenerateTrimmableTypeMap
simonrozsival Mar 12, 2026
e026447
Document future scan optimization path in task
simonrozsival Mar 12, 2026
5f462c6
Move TypeMappingEntryAssembly config to shared targets
simonrozsival Mar 12, 2026
5eaee94
Make scanner/generator types public, fix invalid TFV test
simonrozsival Mar 12, 2026
a9bc05a
Skip writing unchanged JCW Java files for faster incremental builds
simonrozsival Mar 12, 2026
b3e0d9b
Revert "Skip writing unchanged JCW Java files for faster incremental …
simonrozsival Mar 12, 2026
ce586d2
Move UsingTask to Trimmable.targets — only needed in trimmable path
simonrozsival Mar 12, 2026
48f739a
Sign TrimmableTypeMap assembly with product.snk
simonrozsival Mar 13, 2026
18f333d
Address review: FileWrites, ->Count(), #nullable enable
simonrozsival Mar 13, 2026
77a7739
Fix malformed <Touch> element in Trimmable.targets
simonrozsival Mar 13, 2026
f2e5558
Add test: no peers found with non-empty assembly input
simonrozsival Mar 13, 2026
8c17189
Fix FindMonoAndroidDll to use TestEnvironment.MonoAndroidFrameworkDir…
simonrozsival Mar 13, 2026
0825496
Address review: use MonoAndroidHelper, leave outputs null, drop LINQ
simonrozsival Mar 13, 2026
5b99699
Fix UsingTask to use $(_XamarinAndroidBuildTasksAssembly)
simonrozsival Mar 16, 2026
3e0d62f
Fix CI: package TrimmableTypeMap DLL and add metadata to test TaskItems
simonrozsival Mar 16, 2026
72eb604
Make JavaFieldInfo record public for MSBuild task consumption
simonrozsival Mar 17, 2026
06c6abe
Fix integration tests: target _GenerateJavaStubs only
simonrozsival Mar 17, 2026
054dafc
Fix CI: ensure stamp directory exists for trimmable _GenerateJavaStubs
simonrozsival Mar 18, 2026
e4d743f
Fix CI: use full Build for trimmable typemap integration tests
simonrozsival Mar 18, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions build-tools/installers/create-installers.targets
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,8 @@
<_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)Microsoft.Android.Sdk.Bindings.Gradle.targets" />
<_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)Xamarin.Android.Build.Tasks.dll" />
<_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)Xamarin.Android.Build.Tasks.pdb" />
<_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)Microsoft.Android.Sdk.TrimmableTypeMap.dll" />
<_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)Microsoft.Android.Sdk.TrimmableTypeMap.pdb" />
<_MSBuildFiles Include="@(_LocalizationLanguages->'$(MicrosoftAndroidSdkOutDir)%(Identity)\Microsoft.Android.Build.BaseTasks.resources.dll')" />
<_MSBuildFiles Include="@(_LocalizationLanguages->'$(MicrosoftAndroidSdkOutDir)%(Identity)\Xamarin.Android.Build.Tasks.resources.dll')" />
<_MSBuildFiles Include="@(_LocalizationLanguages->'$(MicrosoftAndroidSdkOutDir)%(Identity)\Xamarin.Android.Tools.AndroidSdk.resources.dll')" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ namespace Microsoft.Android.Sdk.TrimmableTypeMap;
/// }
/// </code>
/// </remarks>
sealed class JcwJavaSourceGenerator
public sealed class JcwJavaSourceGenerator
{
/// <summary>
/// Generates .java source files for all ACW types and writes them to the output directory.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ namespace Microsoft.Android.Sdk.TrimmableTypeMap;
/// [assembly: TypeMapAssemblyTarget&lt;Java.Lang.Object&gt;("_MyApp.TypeMap")]
/// </code>
/// </remarks>
sealed class RootTypeMapAssemblyGenerator
public sealed class RootTypeMapAssemblyGenerator
{
const string DefaultAssemblyName = "_Microsoft.Android.TypeMaps";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ namespace Microsoft.Android.Sdk.TrimmableTypeMap;
/// High-level API: builds the model from peers, then emits the PE assembly.
/// Composes <see cref="ModelBuilder"/> + <see cref="TypeMapAssemblyEmitter"/>.
/// </summary>
sealed class TypeMapAssemblyGenerator
public sealed class TypeMapAssemblyGenerator
{
readonly Version _systemRuntimeVersion;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@
<Nullable>enable</Nullable>
<WarningsAsErrors>Nullable</WarningsAsErrors>
<RootNamespace>Microsoft.Android.Sdk.TrimmableTypeMap</RootNamespace>
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>..\..\product.snk</AssemblyOriginatorKeyFile>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="System.IO.Hashing" Version="$(SystemIOHashingPackageVersion)" />
<PackageReference Include="System.Reflection.Metadata" Version="$(SystemReflectionMetadataPackageVersion)" />
<InternalsVisibleTo Include="Microsoft.Android.Sdk.TrimmableTypeMap.Tests" />
<InternalsVisibleTo Include="Microsoft.Android.Sdk.TrimmableTypeMap.Tests" Key="0024000004800000940000000602000000240000525341310004000011000000438ac2a5acfbf16cbd2b2b47a62762f273df9cb2795ceccdf77d10bf508e69e7a362ea7a45455bbf3ac955e1f2e2814f144e5d817efc4c6502cc012df310783348304e3ae38573c6d658c234025821fda87a0be8a0d504df564e2c93b2b878925f42503e9d54dfef9f9586d9e6f38a305769587b1de01f6c0410328b2c9733db" />
</ItemGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ namespace Microsoft.Android.Sdk.TrimmableTypeMap;
/// Contains all data needed by downstream generators (TypeMap IL, UCO wrappers, JCW Java sources).
/// Generators consume this data model — they never touch PEReader/MetadataReader.
/// </summary>
sealed record JavaPeerInfo
public sealed record JavaPeerInfo
{
/// <summary>
/// JNI type name, e.g., "android/app/Activity".
Expand Down Expand Up @@ -116,7 +116,7 @@ sealed record JavaPeerInfo
/// Contains all data needed to generate a UCO wrapper, a JCW native declaration,
/// and a RegisterNatives call.
/// </summary>
sealed record MarshalMethodInfo
public sealed record MarshalMethodInfo
{
/// <summary>
/// JNI method name, e.g., "onCreate".
Expand Down Expand Up @@ -200,7 +200,7 @@ sealed record MarshalMethodInfo
/// <summary>
/// Describes a JNI parameter for UCO method generation.
/// </summary>
sealed record JniParameterInfo
public sealed record JniParameterInfo
{
/// <summary>
/// JNI type descriptor, e.g., "Landroid/os/Bundle;", "I", "Z".
Expand All @@ -216,7 +216,7 @@ sealed record JniParameterInfo
/// <summary>
/// Describes a Java constructor to emit in the JCW .java source file.
/// </summary>
sealed record JavaConstructorInfo
public sealed record JavaConstructorInfo
{
/// <summary>
/// JNI constructor signature, e.g., "(Landroid/content/Context;)V".
Expand All @@ -239,7 +239,7 @@ sealed record JavaConstructorInfo
/// Describes a Java field from an [ExportField] attribute.
/// The field is initialized by calling the annotated method.
/// </summary>
sealed record JavaFieldInfo
public sealed record JavaFieldInfo
{
/// <summary>
/// Java field name, e.g., "STATIC_INSTANCE".
Expand Down Expand Up @@ -270,7 +270,7 @@ sealed record JavaFieldInfo
/// <summary>
/// Describes how to call the activation constructor for a Java peer type.
/// </summary>
sealed record ActivationCtorInfo
public sealed record ActivationCtorInfo
{
/// <summary>
/// The type that declares the activation constructor.
Expand All @@ -289,7 +289,7 @@ sealed record ActivationCtorInfo
public required ActivationCtorStyle Style { get; init; }
}

enum ActivationCtorStyle
public enum ActivationCtorStyle
{
/// <summary>
/// Xamarin.Android style: (IntPtr handle, JniHandleOwnership transfer)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ namespace Microsoft.Android.Sdk.TrimmableTypeMap;
/// Phase 1: Build per-assembly indices (fast, O(1) lookups)
/// Phase 2: Analyze types using cached indices
/// </summary>
sealed class JavaPeerScanner : IDisposable
public sealed class JavaPeerScanner : IDisposable
Copy link
Member Author

Choose a reason for hiding this comment

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

🤖 💡 API design — This type (and JavaPeerInfo, MarshalMethodInfo, JniParameterInfo, JavaConstructorInfo, ActivationCtorInfo, ActivationCtorStyle, JcwJavaSourceGenerator, RootTypeMapAssemblyGenerator, TypeMapAssemblyGenerator) were changed from internal to public. These are only consumed by the GenerateTrimmableTypeMap MSBuild task in Xamarin.Android.Build.Tasks. Making them public exposes them as API surface that customers could depend on.

Consider keeping them internal and adding [InternalsVisibleTo("Xamarin.Android.Build.Tasks")] in the TrimmableTypeMap csproj instead. This is consistent with the existing InternalsVisibleTo entries for test projects.

Rule: New helpers default to internal (Code Organization #4)

Copy link
Member Author

Choose a reason for hiding this comment

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

Intentionally keeping these public. The benchmark script in the PR description consumes them directly, and they'll also be useful for the pre-generation step in #10760 which runs outside of Xamarin.Android.Build.Tasks. This assembly isn't part of the public SDK surface shipped to customers — it's an internal build-time dependency.

{
readonly Dictionary<string, AssemblyIndex> assemblyCache = new (StringComparer.Ordinal);
readonly Dictionary<(string typeName, string assemblyName), ActivationCtorInfo> activationCtorCache = new ();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
<!-- Trimmable typemap targets for CoreCLR runtime (stub).
The actual implementation will be added in a follow-up. -->
<!-- Trimmable typemap targets for CoreCLR runtime.
Adds generated typemap assemblies to the linker inputs. -->
<Project>

<!-- After typemap generation, add generated assemblies to resolved assemblies for the linker.
NOT as TrimmerRootAssembly — the trimmer must process TypeMapAttributes and trim entries
whose trimTarget types were removed. -->
<Target Name="_AddTrimmableTypeMapAssembliesToLinker"
AfterTargets="_GenerateJavaStubs"
Condition=" '@(_GeneratedTypeMapAssemblies->Count())' != '0' ">
<ItemGroup>
<_ResolvedAssemblies Include="@(_GeneratedTypeMapAssemblies)" />
</ItemGroup>
</Target>

</Project>
Original file line number Diff line number Diff line change
@@ -1,4 +1,17 @@
<!-- Trimmable typemap targets for NativeAOT runtime (stub).
The actual implementation will be added in a follow-up. -->
<!-- Trimmable typemap targets for NativeAOT runtime.
Adds generated typemap assemblies to ILC inputs. -->
<Project>

<!-- After typemap generation, add generated assemblies to ILC inputs.
NOT as TrimmerRootAssembly — ILC must process TypeMapAttributes and trim entries
whose trimTarget types were removed. -->
<Target Name="_AddTrimmableTypeMapAssembliesToIlc"
AfterTargets="_GenerateJavaStubs"
Condition=" '@(_GeneratedTypeMapAssemblies->Count())' != '0' ">
<ItemGroup>
<IlcReference Include="@(_GeneratedTypeMapAssemblies)" />
<UnmanagedEntryPointsAssembly Include="@(_GeneratedTypeMapAssemblies)" />
</ItemGroup>
</Target>

</Project>
Original file line number Diff line number Diff line change
@@ -1,12 +1,27 @@
<!-- Trimmable typemap: managed type mapping instead of native binary typemaps.
This is a stub — the actual implementation will be added in a follow-up. -->
Generates per-assembly TypeMap .dll assemblies, a root _Microsoft.Android.TypeMaps.dll,
and JCW .java source files with registerNatives. -->
<Project>

<UsingTask TaskName="Xamarin.Android.Tasks.GenerateTrimmableTypeMap" AssemblyFile="$(_XamarinAndroidBuildTasksAssembly)" />

<Import Project="$(MSBuildThisFileDirectory)Microsoft.Android.Sdk.TypeMap.Trimmable.CoreCLR.targets"
Condition=" '$(_AndroidRuntime)' == 'CoreCLR' " />
<Import Project="$(MSBuildThisFileDirectory)Microsoft.Android.Sdk.TypeMap.Trimmable.NativeAOT.targets"
Condition=" '$(_AndroidRuntime)' == 'NativeAOT' " />

<PropertyGroup>
<_TypeMapAssemblyName>_Microsoft.Android.TypeMaps</_TypeMapAssemblyName>
<_TypeMapOutputDirectory>$(IntermediateOutputPath)typemap\</_TypeMapOutputDirectory>
<_TypeMapJavaOutputDirectory>$(IntermediateOutputPath)typemap\java</_TypeMapJavaOutputDirectory>
</PropertyGroup>

<!-- Tell the runtime which assembly contains the TypeMap attributes -->
<ItemGroup>
<RuntimeHostConfigurationOption Include="System.Runtime.InteropServices.TypeMappingEntryAssembly"
Value="$(_TypeMapAssemblyName)" />
</ItemGroup>

<Target Name="_ValidateTrimmableTypeMapRuntime"
BeforeTargets="Build"
Condition=" '$(_AndroidRuntime)' != 'CoreCLR' And '$(_AndroidRuntime)' != 'NativeAOT' ">
Expand All @@ -18,10 +33,25 @@
from the Cecil-based GenerateJavaStubs task. Extracting them into a shared target
requires decoupling from NativeCodeGenState first. See #10807. -->
<Target Name="_GenerateJavaStubs"
DependsOnTargets="_SetLatestTargetFrameworkVersion;_PrepareAssemblies;_GetGenerateJavaStubsInputs"
DependsOnTargets="_SetLatestTargetFrameworkVersion;_CleanIntermediateIfNeeded;_PrepareAssemblies;_GetGenerateJavaStubsInputs"
Inputs="@(_GenerateJavaStubsInputs)"
Outputs="$(_AndroidStampDirectory)_GenerateJavaStubs.stamp">
<Message Text="Trimmable typemap: skipping legacy _GenerateJavaStubs" Importance="High" />

<GenerateTrimmableTypeMap
ResolvedAssemblies="@(_ResolvedAssemblies)"
OutputDirectory="$(_TypeMapOutputDirectory)"
JavaSourceOutputDirectory="$(_TypeMapJavaOutputDirectory)"
TargetFrameworkVersion="$(TargetFrameworkVersion)">
<Output TaskParameter="GeneratedAssemblies" ItemName="_GeneratedTypeMapAssemblies" />
<Output TaskParameter="GeneratedJavaFiles" ItemName="_GeneratedJavaFiles" />
</GenerateTrimmableTypeMap>

<ItemGroup>
<FileWrites Include="@(_GeneratedTypeMapAssemblies)" />
<FileWrites Include="@(_GeneratedJavaFiles)" />
</ItemGroup>

<MakeDir Directories="$(_AndroidStampDirectory)" Condition=" !Exists('$(_AndroidStampDirectory)') " />
<Touch Files="$(_AndroidStampDirectory)_GenerateJavaStubs.stamp" AlwaysCreate="True" />
</Target>

Expand Down
Loading