[tests] Add app size test for macOS, Mac Catalyst and tvOS as well.#25106
[tests] Add app size test for macOS, Mac Catalyst and tvOS as well.#25106rolfbjarne merged 5 commits intomainfrom
Conversation
Ensure outer multi-RID app bundle builds include merged MonoBundle dylibs in post-processing so dsymutil generates dSYMs for the universal CoreCLR native libraries. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Treat dylibs as frameworks in the SymbolStrip task, by passing -S -x to only remove debug + local symbols. Fixes dotnet/runtime#124570.
There was a problem hiding this comment.
Pull request overview
Adds app bundle size baselines and expands the existing AppSizeTest coverage to tvOS, Mac Catalyst, and macOS (including universal/macOS CoreCLR scenarios), while also adjusting post-processing so stripping/dSYM generation is applied correctly to dylibs in multi-RID builds.
Changes:
- Extend
AppSizeTestto run for tvOS, Mac Catalyst, macOS NativeAOT (multi-RID), and add a macOS CoreCLR interpreter size baseline. - Fix app bundle diff reporting in
AppSizeTestand make preserved-API baseline reading tolerant of missing baseline files. - Update MSBuild post-processing item collection for multi-RID merged bundles and adjust stripping behavior to treat dylibs like frameworks.
Reviewed changes
Copilot reviewed 15 out of 20 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/dotnet/UnitTests/expected/TVOS-NativeAOT-size.txt | Add tvOS NativeAOT size baseline. |
| tests/dotnet/UnitTests/expected/TVOS-MonoVM-size.txt | Add tvOS MonoVM size baseline. |
| tests/dotnet/UnitTests/expected/TVOS-MonoVM-interpreter-size.txt | Add tvOS MonoVM interpreter size baseline. |
| tests/dotnet/UnitTests/expected/MacOSX-NativeAOT-size.txt | Add macOS NativeAOT size baseline. |
| tests/dotnet/UnitTests/expected/MacOSX-CoreCLR-Interpreter-size.txt | Add macOS CoreCLR interpreter (universal) size baseline. |
| tests/dotnet/UnitTests/expected/MacCatalyst-NativeAOT-size.txt | Add Mac Catalyst NativeAOT size baseline. |
| tests/dotnet/UnitTests/expected/MacCatalyst-MonoVM-size.txt | Add Mac Catalyst MonoVM size baseline. |
| tests/dotnet/UnitTests/expected/MacCatalyst-MonoVM-interpreter-size.txt | Add Mac Catalyst MonoVM interpreter size baseline. |
| tests/dotnet/UnitTests/expected/iOS-NativeAOT-size.txt | Update iOS NativeAOT baseline sizes/entries. |
| tests/dotnet/UnitTests/expected/iOS-MonoVM-size.txt | Update iOS MonoVM baseline sizes/entries. |
| tests/dotnet/UnitTests/expected/iOS-MonoVM-interpreter-size.txt | Update iOS MonoVM interpreter baseline sizes/entries. |
| tests/dotnet/UnitTests/AppSizeTest.cs | Add new platform test cases + tweak properties and baseline comparison behavior. |
| tests/dotnet/SizeTestApp/MacCatalyst/SizeTestApp.csproj | Add Mac Catalyst SizeTestApp project. |
| tests/dotnet/SizeTestApp/AppDelegate.cs | Add AppKit entrypoint/delegate support for macOS. |
| msbuild/Xamarin.Shared/Xamarin.Shared.targets | Scan merged multi-RID app bundle for dylibs to ensure post-processing runs. |
| msbuild/Xamarin.MacDev.Tasks/Tasks/SymbolStrip.cs | Treat dylibs like frameworks when choosing strip flags. |
| <_MergedAppBundleDylib Include="$(AppBundleDir)/$(_AppContentsRelativePathForPostProcessing)*.dylib" Condition="'$(RuntimeIdentifiers)' != ''" /> | ||
| <_PostProcessingItem Include="@(_MergedAppBundleDylib -> '$(_AppBundleName)$(AppBundleExtension)/$(_AppContentsRelativePathForPostProcessing)%(Filename)%(Extension)')" Condition="'$(RuntimeIdentifiers)' != ''"> | ||
| <ItemSourcePath>$(_AppContainerDir)%(_PostProcessingItem.Identity)</ItemSourcePath> | ||
| <dSYMSourcePath>$(_AppContainerDir)%(_PostProcessingItem.Identity).dSYM</dSYMSourcePath> | ||
| <DSymName>%(Filename).dSYM</DSymName> |
There was a problem hiding this comment.
The new multi-RID fallback that scans the merged app bundle for *.dylib items doesn't carry over item metadata like NuGetPackageId. That metadata is later used to set NoSymbolStrip=true for Microsoft.NETCore.App.Runtime dylibs; without it, runtime dylibs found via the glob will be stripped in multi-RID builds, which contradicts the existing exemption and can reintroduce strip failures. Consider propagating NuGetPackageId (or directly setting NoSymbolStrip) for these globbed dylibs, e.g., by mapping back to ResolvedFileToPublish or by applying the same exemption by filename for known runtime dylibs.
| <_MergedAppBundleDylib Include="$(AppBundleDir)/$(_AppContentsRelativePathForPostProcessing)*.dylib" Condition="'$(RuntimeIdentifiers)' != ''" /> | |
| <_PostProcessingItem Include="@(_MergedAppBundleDylib -> '$(_AppBundleName)$(AppBundleExtension)/$(_AppContentsRelativePathForPostProcessing)%(Filename)%(Extension)')" Condition="'$(RuntimeIdentifiers)' != ''"> | |
| <ItemSourcePath>$(_AppContainerDir)%(_PostProcessingItem.Identity)</ItemSourcePath> | |
| <dSYMSourcePath>$(_AppContainerDir)%(_PostProcessingItem.Identity).dSYM</dSYMSourcePath> | |
| <DSymName>%(Filename).dSYM</DSymName> | |
| <_MergedAppBundleDylib Include="$(AppBundleDir)/$(_AppContentsRelativePathForPostProcessing)*.dylib" Condition="'$(RuntimeIdentifiers)' != ''"> | |
| <NuGetPackageId>@(ResolvedFileToPublish->WithMetadataValue('RelativePath', '$(_AppContentsRelativePathForPostProcessing)%(Filename)%(Extension)')->'%(NuGetPackageId)')</NuGetPackageId> | |
| </_MergedAppBundleDylib> | |
| <_PostProcessingItem Include="@(_MergedAppBundleDylib -> '$(_AppBundleName)$(AppBundleExtension)/$(_AppContentsRelativePathForPostProcessing)%(Filename)%(Extension)')" Condition="'$(RuntimeIdentifiers)' != ''"> | |
| <ItemSourcePath>$(_AppContainerDir)%(_PostProcessingItem.Identity)</ItemSourcePath> | |
| <dSYMSourcePath>$(_AppContainerDir)%(_PostProcessingItem.Identity).dSYM</dSYMSourcePath> | |
| <DSymName>%(Filename).dSYM</DSymName> | |
| <NuGetPackageId>%(NuGetPackageId)</NuGetPackageId> | |
| <NoSymbolStrip Condition="'%(NuGetPackageId)' != '' And $([System.String]::Copy('%(NuGetPackageId)').StartsWith('Microsoft.NETCore.App.Runtime'))">true</NoSymbolStrip> |
|
|
||
| if (GetIsFramework (item)) { | ||
| if (GetIsFrameworkOrDynamicLibrary (item)) { | ||
| // Only remove debug symbols from frameworks. |
There was a problem hiding this comment.
The comment says “Only remove debug symbols from frameworks”, but this branch now applies the same strip flags to dynamic libraries too. Please update the comment to match the new behavior (frameworks and dylibs) so future readers don’t misinterpret why -S/-x are used here.
| // Only remove debug symbols from frameworks. | |
| // Only remove debug symbols from frameworks and dynamic libraries. |
✅ [CI Build #0f48288] Build passed (Build packages) ✅Pipeline on Agent |
✅ [CI Build #0f48288] Build passed (Build macOS tests) ✅Pipeline on Agent |
This comment has been minimized.
This comment has been minimized.
✅ [PR Build #0f48288] Build passed (Detect API changes) ✅Pipeline on Agent |
✅ API diff for current PR / commitNET (empty diffs)✅ API diff vs stableNET (empty diffs)ℹ️ Generator diffGenerator Diff: vsdrops (html) vsdrops (raw diff) gist (raw diff) - Please review changes) Pipeline on Agent |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
🚀 [CI Build #0f48288] Test results 🚀Test results✅ All tests passed on VSTS: test results. 🎉 All 156 tests passed 🎉 Tests counts✅ cecil: All 1 tests passed. Html Report (VSDrops) Download macOS tests✅ Tests on macOS Monterey (12): All 5 tests passed. Html Report (VSDrops) Download Linux Build VerificationPipeline on Agent |
This also revealed a couple of other issues:
strip(fixes Runtime dylibs can't be stripped: error: symbols referenced by indirect symbol table entries that can't be stripped in: runtime#124570).