Skip to content

[dotnet] Detect when the RuntimeIdentifier is changed too late in the build - #26477

Open
rolfbjarne wants to merge 3 commits into
mainfrom
dev/rolf/validate-runtimeidentifier-simulator-mismatch
Open

[dotnet] Detect when the RuntimeIdentifier is changed too late in the build#26477
rolfbjarne wants to merge 3 commits into
mainfrom
dev/rolf/validate-runtimeidentifier-simulator-mismatch

Conversation

@rolfbjarne

Copy link
Copy Markdown
Member

_SdkIsSimulator is computed from the RuntimeIdentifier very early in the build (in Xamarin.Shared.Sdk.props), and a lot of other things are derived from it: the clang flags, the sysroot, and the intermediate and output paths.

A *.csproj.user file is imported after that, so setting the RuntimeIdentifier there results in a build that's partially configured for the simulator and partially for device. The first sign of trouble is a rather confusing linker error much later in the build:

ld: building for 'iOS-simulator', but linking in dylib (.../iossimulator-arm64/nativelibraries/libSystem.Globalization.Native.dylib) built for 'iOS'

It's also quite hard to figure out on your own, because neither rm -rf bin obj nor dotnet nuget locals --clear removes the *.csproj.user file.

So detect the inconsistency in _ValidateRuntimeIdentifier instead, and show an error that says what's actually wrong.

The test uses a dedicated test project with the *.csproj.user file checked in, so that the test doesn't have to create (and clean up) any files while running. Verified that the test fails without the fix (with the linker error above).

This showed up in #26453, where it prevented the reporter from building at all.

🤖 Pull request created by Copilot

rolfbjarne and others added 3 commits August 27, 2026 02:08
… build

'_SdkIsSimulator' is computed from the RuntimeIdentifier very early in the
build (in Xamarin.Shared.Sdk.props), and a lot of other things are derived
from it: the clang flags, the sysroot, and the intermediate and output
paths.

A '*.csproj.user' file is imported after that, so setting the
RuntimeIdentifier there results in a build that's partially configured for
the simulator and partially for device. The first sign of trouble is a
rather confusing linker error much later in the build:

    ld: building for 'iOS-simulator', but linking in dylib (.../iossimulator-arm64/nativelibraries/libSystem.Globalization.Native.dylib) built for 'iOS'

It's also quite hard to figure out on your own, because neither
'rm -rf bin obj' nor 'dotnet nuget locals --clear' removes the
'*.csproj.user' file.

So detect the inconsistency in '_ValidateRuntimeIdentifier' instead, and
show an error that says what's actually wrong.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 57a20054-5162-48cd-97a2-58bceaa09807
…TooLate test

Instead of writing a '*.csproj.user' file next to MySimpleApp and deleting
it again afterwards (which leaves the repository dirty while the test is
running, and leaves the file behind entirely if the test crashes), add a
new 'RuntimeIdentifierInUserFile' test project with the '*.csproj.user'
file checked in.

'*.user' is in the root .gitignore, so add a .gitignore in the new test
project directory to re-include the two files.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 57a20054-5162-48cd-97a2-58bceaa09807
…sSimulator

I originally skipped the validation when 'RuntimeIdentifiers' contained a
simulator runtime identifier, on the theory that '_SdkIsSimulator' is
computed from 'RuntimeIdentifiers' as well, and could thus legitimately
disagree with 'RuntimeIdentifier'. That turns out not to be the case:

* In the outer build of a multi-RID build 'RuntimeIdentifier' is empty, so
  '_ValidateRuntimeIdentifier' doesn't run at all.
* In an inner build, 'RuntimeIdentifier' is one of the values in
  'RuntimeIdentifiers', so if the latter is a list of simulator runtime
  identifiers, both are simulator values and there's no mismatch.
* A 'RuntimeIdentifiers' with both device and simulator runtime identifiers
  already fails earlier, in '_RunRidSpecificBuild'.

So the only thing the condition accomplished was to hide real instances of
the very problem this validation is supposed to catch (such as a device
'RuntimeIdentifier' in a project that declares simulator
'RuntimeIdentifiers'). Remove it.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 57a20054-5162-48cd-97a2-58bceaa09807
Copilot AI lite review requested due to automatic review settings August 27, 2026 14:55
@rolfbjarne
rolfbjarne requested a review from dalexsoto as a code owner August 27, 2026 14:55

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

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 improves build-time validation in the .NET for Apple platforms SDK by detecting when RuntimeIdentifier is modified after simulator/device-dependent configuration has already been computed, and emitting a clear, actionable error instead of failing later with confusing linker messages.

Changes:

  • Add a _ValidateRuntimeIdentifier check to detect RuntimeIdentifier simulator/device mismatches introduced late in evaluation (commonly via *.csproj.user).
  • Add a regression unit test plus a dedicated test project that checks in *.csproj.user files to reproduce the scenario reliably.
  • Introduce minimal test-project scaffolding (shared props/Makefiles/source) to support the unit test.

Reviewed changes

Copilot reviewed 13 out of 13 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
dotnet/targets/Xamarin.Shared.Sdk.targets Adds late-change detection for RuntimeIdentifier vs _SdkIsSimulator and a dedicated error message.
tests/dotnet/UnitTests/ProjectTest.cs Adds a unit test asserting the new diagnostic when RuntimeIdentifier is changed via *.csproj.user.
tests/dotnet/RuntimeIdentifierInUserFile/.gitignore Allows *.csproj.user to be checked in for the regression test.
tests/dotnet/RuntimeIdentifierInUserFile/Makefile Test project wrapper makefile for shared dotnet test infrastructure.
tests/dotnet/RuntimeIdentifierInUserFile/Main.cs Minimal app entry point to ensure platform assembly participation.
tests/dotnet/RuntimeIdentifierInUserFile/shared.csproj Shared project configuration imported by platform-specific csproj files.
tests/dotnet/RuntimeIdentifierInUserFile/shared.mk Shared makefile fragment to connect to common dotnet test rules.
tests/dotnet/RuntimeIdentifierInUserFile/iOS/Makefile iOS-specific makefile including the shared mk.
tests/dotnet/RuntimeIdentifierInUserFile/iOS/RuntimeIdentifierInUserFile.csproj iOS test app project targeting net$(BundledNETCoreAppTargetFrameworkVersion)-ios.
tests/dotnet/RuntimeIdentifierInUserFile/iOS/RuntimeIdentifierInUserFile.csproj.user Checked-in user file that sets RuntimeIdentifier=ios-arm64 to trigger the mismatch.
tests/dotnet/RuntimeIdentifierInUserFile/tvOS/Makefile tvOS-specific makefile including the shared mk.
tests/dotnet/RuntimeIdentifierInUserFile/tvOS/RuntimeIdentifierInUserFile.csproj tvOS test app project targeting net$(BundledNETCoreAppTargetFrameworkVersion)-tvos.
tests/dotnet/RuntimeIdentifierInUserFile/tvOS/RuntimeIdentifierInUserFile.csproj.user Checked-in user file that sets RuntimeIdentifier=tvos-arm64 to trigger the mismatch.

💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.

Comment thread dotnet/targets/Xamarin.Shared.Sdk.targets
@vs-mobiletools-engineering-service2

This comment has been minimized.

@rolfbjarne
rolfbjarne enabled auto-merge (squash) August 28, 2026 08:52
@rolfbjarne rolfbjarne added the ready-to-review This PR is ready to review/merge. label Aug 28, 2026
@vs-mobiletools-engineering-service2

Copy link
Copy Markdown
Collaborator

🚀 [CI Build #29bb3ae] Test results 🚀

Test results

✅ All tests passed on VSTS: test results.

🎉 All 205 tests passed 🎉

Tests counts

✅ assembly-processing: All 1 tests passed. Html Report (VSDrops) Download
✅ cecil: All 1 tests passed. Html Report (VSDrops) Download
✅ dotnettests (iOS): All 1 tests passed. Html Report (VSDrops) Download
✅ dotnettests (MacCatalyst): All 1 tests passed. Html Report (VSDrops) Download
✅ dotnettests (macOS): All 1 tests passed. Html Report (VSDrops) Download
✅ dotnettests (Multiple platforms): All 1 tests passed. Html Report (VSDrops) Download
✅ dotnettests (tvOS): All 1 tests passed. Html Report (VSDrops) Download
✅ framework: All 2 tests passed. Html Report (VSDrops) Download
✅ fsharp: All 4 tests passed. Html Report (VSDrops) Download
✅ generator: All 5 tests passed. Html Report (VSDrops) Download
✅ interdependent-binding-projects: All 4 tests passed. Html Report (VSDrops) Download
✅ introspection: All 4 tests passed. Html Report (VSDrops) Download
✅ linker (iOS): All 15 tests passed. Html Report (VSDrops) Download
✅ linker (MacCatalyst): All 15 tests passed. Html Report (VSDrops) Download
✅ linker (macOS): All 21 tests passed. Html Report (VSDrops) Download
✅ linker (tvOS): All 15 tests passed. Html Report (VSDrops) Download
✅ monotouch (iOS): All 19 tests passed. Html Report (VSDrops) Download
✅ monotouch (MacCatalyst): All 18 tests passed. Html Report (VSDrops) Download
✅ monotouch (macOS): All 21 tests passed. Html Report (VSDrops) Download
✅ monotouch (tvOS): All 19 tests passed. [attempt 2] Html Report (VSDrops) Download
✅ msbuild: All 2 tests passed. Html Report (VSDrops) Download
✅ sharpie: All 1 tests passed. Html Report (VSDrops) Download
✅ windows: All 3 tests passed. Html Report (VSDrops) Download
✅ xcframework: All 4 tests passed. Html Report (VSDrops) Download
✅ xtro: All 1 tests passed. Html Report (VSDrops) Download

macOS tests

✅ Tests on macOS Monterey (12): All 5 tests passed. Html Report (VSDrops) Download
✅ Tests on macOS Ventura (13): All 5 tests passed. Html Report (VSDrops) Download
✅ Tests on macOS Sonoma (14): All 5 tests passed. Html Report (VSDrops) Download
✅ Tests on macOS Sequoia (15): All 5 tests passed. Html Report (VSDrops) Download
✅ Tests on macOS Tahoe (26): All 5 tests passed. Html Report (VSDrops) Download

Linux Build Verification

Linux build succeeded

Pipeline on Agent
Hash: 29bb3aeaf5f38dbb8e6220efbd2826a524a9472e [PR build]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

copilot ready-to-review This PR is ready to review/merge.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants