Part of #10958.
The current trimmable typemap task has target-level MSBuild incrementality, but the in-task per-assembly typemap write skip appears too coarse. GenerateTrimmableTypeMap.WriteAssembliesToDisk() decides whether to skip writing each non-root typemap DLL by checking only whether the output timestamp is newer than the source assembly timestamp.
That can become stale when _GenerateTrimmableTypeMap reruns because a non-assembly input changed, while the individual source assembly timestamp did not. Examples include manifest/rooting inputs, package naming policy, Debug vs Release shared-universe mode, $(_AndroidBuildPropertiesCache) inputs, and $(_AndroidTrimmableTypeMapMaxArrayRank).
Current locations
src/Xamarin.Android.Build.Tasks/Tasks/GenerateTrimmableTypeMap.cs
WriteAssembliesToDisk(...)
IsUpToDate(...)
src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.TypeMap.Trimmable.targets
_GenerateTrimmableTypeMap target Inputs includes non-assembly inputs that can invalidate generation.
Suggested fix
Prefer correctness over clever timestamp checks:
- Either always pass the generated stream through
Files.CopyIfStreamChanged(...) for per-assembly typemap DLLs, or extend the skip logic so it accounts for every input that can affect the generated bytes.
- Keep timestamp-preserving behavior when bytes are unchanged.
- Ensure the root
_Microsoft.Android.TypeMaps.dll is regenerated when its inputs change, not only when a per-assembly file timestamp was touched.
Acceptance criteria
- A rebuild triggered only by a relevant non-assembly typemap input cannot leave stale per-assembly typemap DLLs behind.
- Timestamp-preserving behavior remains for true no-content-change cases.
- Add targeted tests covering at least one non-assembly input change that affects generated output.
Part of #10958.
The current trimmable typemap task has target-level MSBuild incrementality, but the in-task per-assembly typemap write skip appears too coarse.
GenerateTrimmableTypeMap.WriteAssembliesToDisk()decides whether to skip writing each non-root typemap DLL by checking only whether the output timestamp is newer than the source assembly timestamp.That can become stale when
_GenerateTrimmableTypeMapreruns because a non-assembly input changed, while the individual source assembly timestamp did not. Examples include manifest/rooting inputs, package naming policy, Debug vs Release shared-universe mode,$(_AndroidBuildPropertiesCache)inputs, and$(_AndroidTrimmableTypeMapMaxArrayRank).Current locations
src/Xamarin.Android.Build.Tasks/Tasks/GenerateTrimmableTypeMap.csWriteAssembliesToDisk(...)IsUpToDate(...)src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.TypeMap.Trimmable.targets_GenerateTrimmableTypeMaptargetInputsincludes non-assembly inputs that can invalidate generation.Suggested fix
Prefer correctness over clever timestamp checks:
Files.CopyIfStreamChanged(...)for per-assembly typemap DLLs, or extend the skip logic so it accounts for every input that can affect the generated bytes._Microsoft.Android.TypeMaps.dllis regenerated when its inputs change, not only when a per-assembly file timestamp was touched.Acceptance criteria