[tools/msbuild] Add support for mergeable libraries. Fixes #20262. - #24710
[tools/msbuild] Add support for mergeable libraries. Fixes #20262.#24710rolfbjarne wants to merge 22 commits into
Conversation
Add support for detecting and stripping mergeable library metadata (LC_ATOM_INFO) from frameworks embedded in app bundles. Mergeable libraries are dylibs/frameworks built with -make_mergeable that contain extra static linking metadata, roughly doubling their size. When used as dynamic libraries, this metadata is unnecessary. Changes: - Add LC_ATOM_INFO (0x36) to LoadCommands enum in MachO.cs - Add HasAtomInfo property and IsMergeableLibrary() method for detection - Add -no_atom_info flag to SymbolStrip task when stripping frameworks - Add tests for detection and stripping of mergeable libraries Fixes #20262
Add a new StripMergeableLibraries MSBuild property that controls whether LC_ATOM_INFO (mergeable library metadata) is stripped from frameworks during symbol stripping. The property defaults to the value of Optimize, so Release builds strip the metadata (reducing app size) while Debug builds preserve it. Changes: - SymbolStrip task: add StripMergeableLibraries property, conditionally pass -no_atom_info to strip. - Xamarin.Shared.props: define StripMergeableLibraries defaulting to Optimize. - Xamarin.Shared.targets: pass StripMergeableLibraries to SymbolStrip. - test-libraries: add XMergeableTest framework built with -Wl,-make_mergeable, including plists for all RIDs. - NativeMergeableFrameworkReferencesApp: test app that references the mergeable framework. - ProjectTest.cs: add test cases for building the mergeable framework app and verifying atom info stripping behavior. - MergeableLibraryTests.cs: add test for preserving atom info when StripMergeableLibraries is false.
Add a binding project that embeds the XMergeableTest mergeable framework, with pack tests verifying the nupkg contains the framework correctly. - bindings-framework-test/dotnet-mergeable: binding project referencing XMergeableTest.framework with IsBindingProject=true. - PackTest.cs: BindingMergeableFrameworksProject test verifying dotnet pack produces correct nupkg structure with the mergeable framework. - ProjectTest.cs: BuildNativeMergeableFrameworkReferencesApp_AtomInfoStripping test verifying atom info is stripped when Optimize=true and preserved when Optimize=false.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Add a new StripMergeableLibraryMetadata MSBuild task and target that strips LC_ATOM_INFO from frameworks in the app bundle. This runs independently of the regular symbol stripping (_NativeStripFiles), which is disabled for simulator builds, debug builds, and macOS/MacCatalyst. The new task: - Scans the app bundle's Frameworks directory for .framework directories - Checks each framework executable with MachO.IsMergeableLibrary() - Only strips frameworks that actually have LC_ATOM_INFO - Runs strip -no_atom_info on matching frameworks This ensures mergeable library metadata is stripped when StripMergeableLibraries=true (i.e. Optimize=true), regardless of whether NoSymbolStrip is enabled.
- Remove RuntimeIdentifier from NativeMergeableFrameworkReferencesApp platform projects (default values are chosen automatically). - Add NativeMergeableDylibReferencesApp test app referencing a standalone mergeable dylib (libMergeableFramework.dylib). - Add libMergeableFramework.dylib build rule in test-libraries Makefile. - Extend StripMergeableLibraryMetadata task to also scan dylib directories (e.g. MonoBundle) for mergeable libraries. - Add BuildNativeMergeableDylibReferencesApp_AtomInfoStripping test verifying dylib atom info stripping behavior. All 8 integration tests and 10 unit tests pass.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Fix the optimized-build default, pass StripPath through to the metadata stripping task, scan the app bundle root for standalone dylibs, and handle missing fat-file entries safely. Also restore the missing MachO closing brace reported by CI. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 35b9fddd-0b2f-4427-9990-90225546e53a
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Pass -S when removing atom info so strip preserves symbols needed by indirect symbol table entries in other architecture slices. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
🟡 Changes recommended
The new MergeableLibraryTests invoke xcrun without an OS guard, which can break test runs on non-macOS agents.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Review details
Suppressed comments (1)
tests/dotnet/UnitTests/ProjectTest.cs:690
- 💡 suggestion: Same as above for the dylib variant: only macOS/Mac Catalyst are covered. Adding iOS/tvOS simulator cases would strengthen confidence that mergeable dylibs are stripped correctly in mobile app bundles too.
[Test]
[TestCase (ApplePlatform.MacOSX, "osx-arm64", true)] // Optimize=true should strip atom info
[TestCase (ApplePlatform.MacOSX, "osx-arm64", false)] // Optimize=false should preserve atom info
[TestCase (ApplePlatform.MacCatalyst, "maccatalyst-arm64", true)]
[TestCase (ApplePlatform.MacCatalyst, "maccatalyst-arm64", false)]
- Files reviewed: 39/39 changed files
- Comments generated: 3
- Review effort level: Lite
Clarify dylib handling and skip unchanged libraries using per-library stamps. Register generated stamps as FileWrites for incremental cleanup. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 35b9fddd-0b2f-4427-9990-90225546e53a
Use zero-length stamp files with deterministic names without computing a SHA. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 35b9fddd-0b2f-4427-9990-90225546e53a
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Hash each absolute library path before creating its incremental stamp file. This keeps stamp names deterministic and unique without exceeding the filesystem's per-component length limit for deeply nested app bundles. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
✅ 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 |
🚀 [CI Build #ab786e1] Test results 🚀Test results✅ All tests passed on VSTS: test results. 🎉 All 264 tests passed 🎉 Tests counts✅ assembly-processing: All 1 tests passed. Html Report (VSDrops) Download macOS tests✅ Tests on macOS Sonoma (14): All 5 tests passed. Html Report (VSDrops) Download Linux Build VerificationPipeline on Agent |
Summary
Adds MSBuild support for mergeable libraries by detecting mergeable framework/dylib metadata and stripping it when requested during native reference processing.
This includes:
StripMergeableLibrariesbuild propertyStripMergeableLibraryMetadatatask wired into native reference handlingTesting
Fixes #20262.