Fix PlatformTarget validation for RuntimeIdentifiers - #12188
Conversation
Android per-RID inner builds assign RuntimeIdentifier after the outer assembly has already been compiled. Run the common configuration validation hook before reusing that assembly so incompatible PlatformTarget and RID combinations fail with NETSDK1032 instead of crashing at runtime. Add a regression test for PlatformTarget=x64 with RuntimeIdentifiers=android-arm64. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: c072388c-788f-44a1-9b09-824dfe7c1d6c
There was a problem hiding this comment.
Pull request overview
This PR fixes a build-time validation gap in Android’s per-RuntimeIdentifier inner builds: when RuntimeIdentifier is only assigned in the RID-specific inner build, an incompatible outer-built managed assembly (e.g., PlatformTarget=x64) could be reused for android-arm64, leading to runtime crashes. The change forces MSBuild’s common configuration/platform validation to run before the outer assembly is reused, producing the expected NETSDK1032 error instead of a runtime failure.
Changes:
- Run
_CheckForInvalidConfigurationAndPlatformas part of_ComputeFilesToPublishForRuntimeIdentifiersso incompatiblePlatformTarget/RID combinations fail during the inner build. - Add a unit test that asserts the build fails and reports
NETSDK1032forandroid-arm64+Platform=x64.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest2.cs | Adds a regression test ensuring incompatible Platform + RuntimeIdentifiers fails with NETSDK1032. |
| src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.AssemblyResolution.targets | Ensures MSBuild configuration/platform validation runs before reusing the outer intermediate assembly in RID inner builds. |
| <!-- RuntimeIdentifier is assigned in these inner builds, after the outer assembly has been compiled. | ||
| _CheckForInvalidConfigurationAndPlatform is a private MSBuild target, but there is no public | ||
| validation-only target. Microsoft.Common.targets explicitly directs custom targets that require | ||
| configuration validation to depend on it. This also avoids depending on the SDK's private | ||
| _CheckForMismatchingPlatform implementation target. | ||
| See https://github.com/dotnet/msbuild/blob/eae54023463db15e9a9081f35a959c9162797643/src/Tasks/Microsoft.Common.CurrentVersion.targets#L823-L836 --> | ||
| <Target Name="_ComputeFilesToPublishForRuntimeIdentifiers" | ||
| DependsOnTargets="BuildOnlySettings;_FixupIntermediateAssembly;_PatchNuGetReferenceMetadata;ResolveReferences;ComputeFilesToPublish;$(_RunAotMaybe)" | ||
| DependsOnTargets="BuildOnlySettings;_CheckForInvalidConfigurationAndPlatform;_FixupIntermediateAssembly;_PatchNuGetReferenceMetadata;ResolveReferences;ComputeFilesToPublish;$(_RunAotMaybe)" |
There was a problem hiding this comment.
I could find no other public target we can use here, but they actually say to use the private target here:
Android's per-RID inner builds assign
RuntimeIdentifierafter the outer assembly has already been compiled. This allowed an x64 managed assembly to be reused forandroid-arm64, producing an application that built successfully but crashed at runtime.Run the common MSBuild configuration validation hook before reusing the outer assembly so incompatible combinations fail with
NETSDK1032. The target is private, but Microsoft.Common.targets explicitly directs custom targets requiring configuration validation to depend on it; the source comment includes a permanent link documenting that contract.Fixes #12183
Tests:
IncompatiblePlatformTargetAndRuntimeIdentifiersFailsBuildBuildBasicApplicationThenMoveIt