We might actually support a newer OS version than the one we're building for,
if we're supporting a preview version in a stable release. In this case, we
need to make sure to load the correct sdk when we run into errors, so that we
show the correct error messages.
Fixes this test failure:
Xamarin.Tests.DotNetProjectTest.InvalidTargetPlatformVersion(MacCatalyst): Error message
Expected string length 92 but was 87. Strings differ at index 84.
Expected: "...ormVersion for MacCatalyst. Valid versions include:\n16.4\n17.0"
But was: "...ormVersion for MacCatalyst. Valid versions include:\n17.0"
* Fix boolean logic to determine whether .NET is enabled or not
* Update mlaunch to get a fix where we trim the project.
* Update the list of files that need to be signed from mlaunch.
If anything we're supposed to link with *.o files, not publish them, but
since we're currently not handling any *.o files, just explicitly remove them
from the build. This avoids a warning where ComputeBundleLocation would issue
a warning about not knowing what to do with them.
Contributes towards https://github.com/xamarin/xamarin-macios/issues/18629.
---------
Co-authored-by: Ivan Povazan <55002338+ivanpovazan@users.noreply.github.com>
Fixes this linker failure when compiling monotouch-test:
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Errors
xamarin-macios/builds/downloads/dotnet-sdk-8.0.100-rc.2.23428.11/packs/Microsoft.macOS.Sdk/13.3.8852-net8-rc2/targets/Xamarin.Shared.Sdk.targets(1527,3): clang++ exited with code 1:
ld: library not found for -lswiftCore
clang: error: linker command failed with exit code 1 (use -v to see invocation) [/Users/rolf/work/maccore/net8.0/xamarin-macios/tests/dotnet/MySimpleApp/macOS/MySimpleApp.csproj]
We're going to change the pack names to support multi-targeting, so ahead
of the pack name change I'm changing the existing logic to use a variable
for the pack name in most places (this will make the rename much easier and
simpler).
These changes should have no effect by themselves.
Added default entitlements for MacCatalyst templates.
For Debug, the com.apple.security.get-task-allow entitlement that allows for using developer tools when developing MAUI Blazor apps.
For release, com.apple.security.app-sandbox is required to publish MacCatalyst apps to the Mac App Store.
Also added unit test to check for entitlements when project is created.
Fixes#18344
---------
Co-authored-by: GitHub Actions Autoformatter <github-actions-autoformatter@xamarin.com>
Co-authored-by: Rolf Bjarne Kvinge <rolf@xamarin.com>
Make 'Full' the default link mode for all platforms for NativeAOT because:
* It will achieve the best app size.
* NativeAOT is not a drop-in replacement that's guaranteed to work - there are
already known features NativeAOT don't support (and may never support), so
this may be an opportunity for app developers (and component vendors) to
make their products trimmer safe.
* NativeAOT will be in preview in .NET 8, so we can change our mind later if
it turns out to cause too many problems.
* In some cases NativeAOT might require trimming, because we may
optimize/rewrite assemblies to be NativeAOT-compatible to support existing
libraries.
This requires #18666 to be merged first, so that ests aren't linked away.
Add partial support for the `[Preserve]` attribute for NativeAOT. This
is done by injecting an equivalent `[DynamicDependency]` attribute. The
partial support comes from the fact that there's no way to map a
conditional preserve attribute (`[Preserve (Conditional = true)]`) to a
`[DynamicDependency]` attribute, so we report a warning instead.
For non-conditional `[Preserve]` attributes, we'll now add a
`[DynamicDependency]` attribute to the assembly's module constructor for
the type/member in question, effectively rooting it.
This makes it possible to fully link all our test suites when NativeAOT
(otherwise NativeAOT would just link out all the tests, leaving the test
suites empty - and unfortunately green, so this was a rather accidental
discovery).
This PR enables trim warnings with NativeAOT by default.
In our current ILLink+ILC setup, we first need to suppress the warnings for ILLink, after which we need to enable them for ILC.
For this reason, setting up `SuppressTrimAnalysisWarnings` properly needs to happen very early as it will get overwritten by 45acd380b3/src/tools/illink/src/ILLink.Tasks/build/Microsoft.NET.ILLink.targets (L54-L59)
Verified with building an iOS application that the trim warnings are displayed only during ILC trimming (after `Generating native code` message below):
```
../dotnet publish -c Release -r ios-arm64 -bl /p:PublishAot=true /p:PublishAotUsingRuntimePack=true
MSBuild version 17.7.0+5785ed5c2 for .NET
Determining projects to restore...
Restored /Users/ivan/repos/xamarin/xamarin-macios/builds/downloads/dotnet-sdk-8.0.100-rc.1.23415.19/TrimTest/TrimTest.csproj (in 127 ms).
/Users/ivan/repos/xamarin/xamarin-macios/builds/downloads/dotnet-sdk-8.0.100-rc.1.23415.19/sdk/8.0.100-rc.1.23415.19/Sdks/Microsoft.NET.Sdk/targets/Microsoft.NET.RuntimeIdentifierInference.targets(311,5): message NETSDK1057: You are using a preview version of .NET. See: https://aka.ms/dotnet-support-policy [/Users/ivan/repos/xamarin/xamarin-macios/builds/downloads/dotnet-sdk-8.0.100-rc.1.23415.19/TrimTest/TrimTest.csproj]
Detected signing identity:
Code Signing Key: "Apple Development: Ivan Povazan (53PXX466YZ)" (3CC7B9372E3BB19DEBECBA95A6AF3E0EB26C5B29)
Provisioning Profile: "iOS Team Provisioning Profile: *" (6e598984-dd21-4632-b707-72cfa247991d)
Bundle Id: com.companyname.TrimTest
App Id: SGGM6D27TK.com.companyname.TrimTest
TrimTest -> /Users/ivan/repos/xamarin/xamarin-macios/builds/downloads/dotnet-sdk-8.0.100-rc.1.23415.19/TrimTest/bin/Release/net8.0-ios/ios-arm64/TrimTest.dll
/Users/ivan/repos/xamarin/xamarin-macios/builds/downloads/dotnet-sdk-8.0.100-rc.1.23415.19/packs/Microsoft.iOS.Sdk/16.4.8777-ci.trim-warn/targets/Xamarin.Shared.Sdk.targets(1826,3): warning : The file '/Users/ivan/repos/xamarin/xamarin-macios/packages/microsoft.netcore.app.runtime.nativeaot.ios-arm64/8.0.0-rc.1.23414.4/runtimes/ios-arm64/native/libbootstrapper.o' does not specify a 'PublishFolderType' metadata, and a default value could not be calculated. The file will not be copied to the app bundle. [/Users/ivan/repos/xamarin/xamarin-macios/builds/downloads/dotnet-sdk-8.0.100-rc.1.23415.19/TrimTest/TrimTest.csproj]
/Users/ivan/repos/xamarin/xamarin-macios/builds/downloads/dotnet-sdk-8.0.100-rc.1.23415.19/packs/Microsoft.iOS.Sdk/16.4.8777-ci.trim-warn/targets/Xamarin.Shared.Sdk.targets(1826,3): warning : The file '/Users/ivan/repos/xamarin/xamarin-macios/packages/microsoft.netcore.app.runtime.nativeaot.ios-arm64/8.0.0-rc.1.23414.4/runtimes/ios-arm64/native/libbootstrapperdll.o' does not specify a 'PublishFolderType' metadata, and a default value could not be calculated. The file will not be copied to the app bundle. [/Users/ivan/repos/xamarin/xamarin-macios/builds/downloads/dotnet-sdk-8.0.100-rc.1.23415.19/TrimTest/TrimTest.csproj]
/Users/ivan/repos/xamarin/xamarin-macios/builds/downloads/dotnet-sdk-8.0.100-rc.1.23415.19/packs/Microsoft.iOS.Sdk/16.4.8777-ci.trim-warn/targets/Xamarin.Shared.Sdk.targets(536,3): warning : All assemblies must be processed by the linker when using NativeAOT. Please don't set neither the 'MtouchLink' nor the 'TrimMode' property, so that the build can default to linking all assemblies. [/Users/ivan/repos/xamarin/xamarin-macios/builds/downloads/dotnet-sdk-8.0.100-rc.1.23415.19/TrimTest/TrimTest.csproj]
Optimizing assemblies for size may change the behavior of the app. Be sure to test after publishing. See: https://aka.ms/dotnet-illink
Optimizing assemblies for size. This process might take a while.
Generating native code
resource ILLink.LinkAttributes.xml in System.Private.CoreLib(335,8): warning IL2049: System.Private.CoreLib: The internal attribute name 'RemoveAttributeInstances' being used in the xml is not supported by ILLink, check the spelling and the supported internal attributes. [/Users/ivan/repos/xamarin/xamarin-macios/builds/downloads/dotnet-sdk-8.0.100-rc.1.23415.19/TrimTest/TrimTest.csproj]
resource ILLink.LinkAttributes.xml in System.Private.CoreLib(342,8): warning IL2049: System.Private.CoreLib: The internal attribute name 'RemoveAttributeInstances' being used in the xml is not supported by ILLink, check the spelling and the supported internal attributes. [/Users/ivan/repos/xamarin/xamarin-macios/builds/downloads/dotnet-sdk-8.0.100-rc.1.23415.19/TrimTest/TrimTest.csproj]
resource ILLink.LinkAttributes.xml in System.Private.CoreLib(349,8): warning IL2049: System.Private.CoreLib: The internal attribute name 'RemoveAttributeInstances' being used in the xml is not supported by ILLink, check the spelling and the supported internal attributes. [/Users/ivan/repos/xamarin/xamarin-macios/builds/downloads/dotnet-sdk-8.0.100-rc.1.23415.19/TrimTest/TrimTest.csproj]
resource ILLink.LinkAttributes.xml in System.Private.CoreLib(356,8): warning IL2049: System.Private.CoreLib: The internal attribute name 'RemoveAttributeInstances' being used in the xml is not supported by ILLink, check the spelling and the supported internal attributes. [/Users/ivan/repos/xamarin/xamarin-macios/builds/downloads/dotnet-sdk-8.0.100-rc.1.23415.19/TrimTest/TrimTest.csproj]
resource ILLink.LinkAttributes.xml in System.Private.CoreLib(363,8): warning IL2049: System.Private.CoreLib: The internal attribute name 'RemoveAttributeInstances' being used in the xml is not supported by ILLink, check the spelling and the supported internal attributes. [/Users/ivan/repos/xamarin/xamarin-macios/builds/downloads/dotnet-sdk-8.0.100-rc.1.23415.19/TrimTest/TrimTest.csproj]
resource ILLink.LinkAttributes.xml in System.Private.CoreLib(370,8): warning IL2049: System.Private.CoreLib: The internal attribute name 'RemoveAttributeInstances' being used in the xml is not supported by ILLink, check the spelling and the supported internal attributes. [/Users/ivan/repos/xamarin/xamarin-macios/builds/downloads/dotnet-sdk-8.0.100-rc.1.23415.19/TrimTest/TrimTest.csproj]
/Users/ivan/repos/xamarin/xamarin-macios/src/ObjCRuntime/Runtime.CoreCLR.cs(171): Trim analysis warning IL2026: ObjCRuntime.Runtime.ResolvingEventHandler(AssemblyLoadContext,AssemblyName): Using member 'System.Runtime.Loader.AssemblyLoadContext.LoadFromAssemblyPath(String)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Types and members the loaded assembly depends on might be removed. [/Users/ivan/repos/xamarin/xamarin-macios/builds/downloads/dotnet-sdk-8.0.100-rc.1.23415.19/TrimTest/TrimTest.csproj]
/Users/ivan/repos/xamarin/xamarin-macios/src/ObjCRuntime/Runtime.CoreCLR.cs(267): Trim analysis warning IL2026: ObjCRuntime.Runtime.FindAssembly(IntPtr): Using member 'System.Reflection.Assembly.LoadFrom(String)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Types and members the loaded assembly depends on might be removed. [/Users/ivan/repos/xamarin/xamarin-macios/builds/downloads/dotnet-sdk-8.0.100-rc.1.23415.19/TrimTest/TrimTest.csproj]
/Users/ivan/repos/xamarin/xamarin-macios/builds/downloads/dotnet-sdk-8.0.100-rc.1.23415.19/TrimTest/obj/Release/net8.0-ios/ios-arm64/linked/Microsoft.iOS.dll : warning IL3053: Assembly 'Microsoft.iOS' produced AOT analysis warnings. [/Users/ivan/repos/xamarin/xamarin-macios/builds/downloads/dotnet-sdk-8.0.100-rc.1.23415.19/TrimTest/TrimTest.csproj]
/Users/ivan/repos/xamarin/xamarin-macios/builds/downloads/dotnet-sdk-8.0.100-rc.1.23415.19/TrimTest/obj/Release/net8.0-ios/ios-arm64/linked/Microsoft.iOS.dll : warning IL2104: Assembly 'Microsoft.iOS' produced trim warnings. For more information see https://aka.ms/dotnet-illink/libraries [/Users/ivan/repos/xamarin/xamarin-macios/builds/downloads/dotnet-sdk-8.0.100-rc.1.23415.19/TrimTest/TrimTest.csproj]
Created the package: bin/Release/net8.0-ios/ios-arm64/publish//TrimTest.ipa
```
---
Fixes: https://github.com/xamarin/xamarin-macios/issues/18571
---------
Co-authored-by: Ivan Povazan <ivan.povazan@gmail.com>
* Don't strip resource assemblies, there's no code in them to strip anyways.
* Use the relative path inside the app bundle when computing the intermediate
location for stripped assemblies, so that if we were to find two identically
named assemblies in different directories, they're handled correctly (by
putting them in different intermediate locations, instead of overwriting
eachother).
Fixes https://github.com/xamarin/xamarin-macios/issues/17262.
The gist is:
- If you enable `<PublishAot>true</PublishAot>` then the NativeAOT build targets get included.
- Unless `NativeCompilationDuringPublish` is disabled, the NativeAOT targets are chained through `BeforeTargets` attribute to some publish targets (computing the resolved publish paths). Xamarin runs those publish targets even for non-publish builds, so it brings the whole ILC compilation along. That's undesirable.
- The `RunILLink` property is set unconditionally by the NativeAOT build integration. If we don't fix it then ILLink never runs, and neither do all the custom steps to generate registrars and `main()`.
Update: Apparently, we still need to fix runtime pack resolution for iOS-like platforms with `PublishAotUsingRuntimePack=true`.
---------
Co-authored-by: Filip Navara <navara@emclient.com>
The .mobile.props file is a file created and written by the mobile VS
extension to store property values that needs to be read early enough in
the build chain, as in design time builds, and that can't be set by CPS
because of a limitation in the project system. See more information
here: https://github.com/xamarin/XamarinVS/pull/13606
Initially it was named .user.env file and then was renamed in another PR
as part of a feedback from the project system team. See more information
here: https://github.com/xamarin/XamarinVS/pull/13628
Because this file was saved in the intermediate output path, it was
meant to be imported automatically by MSBuild, however we recently
detected that this was not happening reliably. Because of this, some
things like C# Hot Reload for iOS stopped working because Roslyn was
reading incorrect values from the Design Time Builds.
For that reason and to avoid relying on the project system, I'm
importing this file explicitly (and removing old .user.env import), so
the values in the file are always available and the dependent properties
are calculated correctly and available for all the consumers (including
Roslyn).
This should fix the following bugs:
https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1822041https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1851677
It's possible to create a provisioning profile for Mac Catalyst that
doesn't allow dylibs in the app. It seems a significant number of people run
into this problem when publishing their apps, so avoid it by linking Mono and
Xamarin statically by default instead.
The downside is that build time might increase a little bit.
An upside however is that the app size might decrease somewhat.
Fixes https://github.com/xamarin/xamarin-macios/issues/14686.
If an assembly changes, then we must AOT compile that assembly again (which we already
did), in addition to any assembly that references the modified assembly (which we
didn't do).
So rework the AOTCompile target: remove the Inputs and Outputs (because the dependency
tracking is too complicated for MSBuild to resolve), and instead move the logic to
detect if an assembly must be AOT-compiled again into the AOTCompile task.
Note that this PR has a custom port to .NET 8: #18518.
Fixes https://github.com/xamarin/xamarin-macios/issues/17708.
---------
Co-authored-by: Alex Soto <alex@alexsoto.me>
If an assembly changes, then we must AOT compile that assembly again (which we already
did), in addition to any assembly that references the modified assembly (which we
didn't do).
So rework the AOTCompile target: remove the Inputs and Outputs (because the dependency
tracking is too complicated for MSBuild to resolve), and instead move the logic to
detect if an assembly must be AOT-compiled again into the AOTCompile task.
This is a port of the [original fix for main][1] to .NET 8, where we have to
take the dedup assembly into account too: if any assembly has changed, then we
must re-aot the dedup assembly as well.
Fixes https://github.com/xamarin/xamarin-macios/issues/17708.
[1]: https://github.com/xamarin/xamarin-macios/pull/18509
---------
Co-authored-by: Alex Soto <alex@alexsoto.me>
The `MicroBuildCodesignVerify@3` task has been added to validate the
signing status of the MSI files required for VS insertions. This will
allow us to identify any potential signing issues earlier.
Context: https://github.com/xamarin/yaml-templates/pull/274
Enables side by side workload manifest support when generating workload
MSIs.
This should only be enabled for builds shipping with .NET 8 Preview 7 or
later.
Co-authored-by: Alex Soto <alex@alexsoto.me>
In the current setup with NativeAOT, during app build we run both ILLink
and ILCompiler in cascade.
When `_AggressiveAttributeTrimming` feature switch is set to `true`
ILLink removes `IsTrimmable` attribute from assemblies, which means that
when we are also running in `TrimMode=partial` (which translates to
`--defaultrooting` ILC command-line arguments) ILC trimming is disabled
completely.
This PR disables `_AggressiveAttributeTrimming` in the first pass ie
during trimming by ILLink and enables it in the second trimming pass
performed by ILCompiler.
Additionally, to workaround ILCompiler incompatibility with
`Microsoft.iOS` (and friends) this platform assembly is explicitly
rooted when passed to ILCompiler for trimming (this will be fixed once
https://github.com/dotnet/runtime/issues/86649 is resolved).
Estimated savings: This change reduces the size of the application
bundle by `0,58Mb` (or ~4,3% compared to the baseline)
| MAUI ios app | Base | This PR | diff (%) |
|--------------|-----------|-----------|----------|
| SOD (Mb) | 41,93 | 40,5 | -3,4% |
| .ipa (Mb) | 13,43 | 12,85 | -4,3% |
Fixes: https://github.com/xamarin/xamarin-macios/issues/18479
---------
Co-authored-by: Alex Soto <alex@alexsoto.me>
Since NativeAOT generates native libraries and executables that do not
rely on assemblies they were compiled from, all managed assemblies can
be excluded from the application bundle.
This reduces the size of the application bundle by `3,17Mb` (or ~19%
compared to the baseline)
| MAUI ios app | Base | This PR | diff (%) |
|--------------|-----------|-----------|----------|
| SOD (Mb) | 50,13 | 41,93 | -16,3% |
| .ipa (Mb) | 16,59 | 13,43 | -19% |
Fixes: https://github.com/xamarin/xamarin-macios/issues/18472
This pull request updates the following dependencies
## Coherency Updates
The following updates ensure that dependencies with a *CoherentParentDependency*
attribute were produced in a build used as input to the parent dependency's build.
See [Dependency Description Format](https://github.com/dotnet/arcade/blob/master/Documentation/DependencyDescriptionFormat.md#dependency-description-overview)
- **Coherency Updates**:
- **Microsoft.NET.ILLink.Tasks**: from 8.0.0-preview.6.23316.3 to 8.0.0-preview.7.23325.2 (parent: Microsoft.Dotnet.Sdk.Internal)
- **Microsoft.AspNetCore.App.Ref**: from 8.0.0-preview.6.23316.5 to 8.0.0-preview.7.23324.1 (parent: Microsoft.Dotnet.Sdk.Internal)
- **Microsoft.NETCore.App.Ref**: from 8.0.0-preview.6.23316.3 to 8.0.0-preview.7.23325.2 (parent: Microsoft.Dotnet.Sdk.Internal)
- **Microsoft.NET.Workload.Emscripten.Current.Manifest-8.0.100.Transport**: from 8.0.0-preview.6.23312.1 to 8.0.0-preview.7.23321.3 (parent: Microsoft.NETCore.App.Ref)
- **Microsoft.NETCore.App.Ref**: from 8.0.0-preview.6.23316.3 to 8.0.0-preview.7.23325.2 (parent: Microsoft.Dotnet.Sdk.Internal)
- **Microsoft.DotNet.Cecil**: from 0.11.4-alpha.23312.1 to 0.11.4-alpha.23319.2 (parent: Microsoft.NETCore.App.Ref)
## From https://github.com/dotnet/installer
- **Subscription**: f9b68d84-9c90-4bd0-5499-08db4112d57e
- **Build**: 20230625.5
- **Date Produced**: June 26, 2023 6:19:18 AM UTC
- **Commit**: d2a244f560b9f89387a5e748c19adf3114153f89
- **Branch**: refs/heads/main
- **Updates**:
- **Microsoft.Dotnet.Sdk.Internal**: [from 8.0.100-preview.6.23320.7 to 8.0.100-preview.7.23325.5][14]
- **Microsoft.NET.ILLink.Tasks**: [from 8.0.0-preview.6.23316.3 to 8.0.0-preview.7.23325.2][15]
- **Microsoft.AspNetCore.App.Ref**: [from 8.0.0-preview.6.23316.5 to 8.0.0-preview.7.23324.1][16]
- **Microsoft.NETCore.App.Ref**: [from 8.0.0-preview.6.23316.3 to 8.0.0-preview.7.23325.2][15]
- **Microsoft.NET.Workload.Emscripten.Current.Manifest-8.0.100.Transport**: [from 8.0.0-preview.6.23312.1 to 8.0.0-preview.7.23321.3][17]
- **Microsoft.NETCore.App.Ref**: [from 8.0.0-preview.6.23316.3 to 8.0.0-preview.7.23325.2][15]
- **Microsoft.DotNet.Cecil**: [from 0.11.4-alpha.23312.1 to 0.11.4-alpha.23319.2][18]
[14]: 7a0bb9fd74...d2a244f560
[15]: 76da696f3f...eaa9717d90
[16]: 974d15e3b0...213eb282fc
[17]: 1640faa87e...e004a85d84
[18]: ad66dcb8a0...f449dc9923
Add support for using NativeAOT on all our platforms.
This contains numerous changes in a lot of places to add support for
NativeAOT:
* build logic
* runtime
* managed code
* tests
And it all pretty much consists of special-casing NativeAOT everywhere
we need to.
Note: NativeAOT doesn't work on macOS yet, because a dotnet/runtime fix
is required, and thus the corresponding test variations for
monotouch-test have been commented out.
This PR is best reviewed commit-by-commit.
This contributes towards https://github.com/xamarin/xamarin-macios/issues/17339.
Detect if we're using a non-stable Xcode, and in that case produce packages
that show an error if they're used and the EnablePreviewFeatures flag isn't
enabled.
Also add logic to set this flag for our own build, otherwise all our tests
would fail.
This is the same as Android does.
Contributes towards https://github.com/xamarin/xamarin-macios/issues/18343.
This is because NativeAOT contains swift code, and we'd have to add code to
embed the Swift libraries in any apps that target early OS versions. We could
eventually implement this, but let's wait and see if there's a demand first.
Currently, NativeAOT is implemented as a replacement (of sorts) for ILLink. However,
we need to execute both, and in order to do that, we force our own logic to execute
to determine what ILC does.
This might be improved in the future. Ref: https://github.com/dotnet/runtime/issues/87187.
It seems this target has more problems than at first I thought, so make
it easier to opt-out of it by just setting a property in the csproj.
More investigation is needed, but I'm keeping the target on by default
for now, since it solves a real-world problem as well.
Ref: https://github.com/xamarin/xamarin-macios/issues/18445
Add public targets to compute the mlaunch command lines for installing
and launching mobile apps.
These new targets are:
* ComputeMlaunchInstallArguments
* ComputeMlaunchRunArguments
As part of this change, also create a few new public properties:
* MlaunchPath
* MlaunchRunArguments
* MlaunchInstallArguments
* MlaunchRunScript
* MlaunchInstallScript
If the *Script variables are set, the corresponding target will create a
script file with the path to mlaunch + the corresponding arguments.
Otherwise, it's also possible to get the arguments directly from the
build log.
Fixes https://github.com/xamarin/xamarin-macios/issues/18359.
# Description
This PR reduces the application's SOD (size on disk) by making
`__LINKEDIT Export Info` section smaller in the stripped Mach-O
binaries.
The feature is controlled by `_ExportSymbolsExplicitly` MSBuild property
and can be disabled by specifying: `-p:_ExportSymbolsExplicitly=true`
Fixes#18332
# Initial problem
It has been noticed that during stripping, the strip tool does not
resize the export info section after it removes the symbols. Instead it
only zeroes out the entries (achieved by calling `prune_trie` function):
- https://github.com/apple-oss-distributions/cctools/blob/cctools-986/misc/strip.c
- https://github.com/apple-oss-distributions/ld64/blob/ld64-711/src/other/PruneTrie.cpp
Thanks @lambdageek for helping to track this down.
# Approach
As Xamarin build process already collects all the [required symbols][1] needed
for the application to run and preserves them during the strip phase, we can
use the same file to instruct clang toolchain to export only those symbols via
the command line options: `-exported_symbols_list <file>` ([source][2]).
This will make the export info section only include what is necessary for the
runtime - and at the same time eliminate the problem of the `strip` tool which
does not resize stripped symbols.
# Investigation setup
The issue is observable by building and inspecting the test application:
https://github.com/xamarin/xamarin-macios/blob/main/tests/dotnet/MySingleView/MySingleView.csproj
and targeting iOS platform in Release mode.
## Results:
| Measure | MySingleView - main | MySingleView - this PR | Diff (%) |
| :--- | ---: | ---: | ---: |
| SOD (bytes) | 13668940 | 13458476 | -1.5% |
| .ipa (bytes) | 4829368 | 4827928 | -0.03% |
Even though zeroes are compressed well, the SOD is still affected and
unused section takes around 1.5% of the most simplistic app size.
Much bigger impact has been noted when trying out a MAUI iOS template
app with NativeAOT where the `__LINKEDIT Export Info` zeroes take up to
20MB of the SOD, but also with the regular macOS applications:
https://github.com/dotnet/runtime/issues/86707
### Repro current state of MySingleView.app with stripped binary
1. Build the app (you can ignore the need to run the sample, I just did it to
make sure the changes do not break anything)
```bash
make run-device
```
2. Print the load commands - [load_cmds_strip.list][3]
```bash
otool -l bin/Release/net7.0-ios/ios-arm64/MySingleView.app/MySingleView > load_cmds_strip.list
```
- We are interested in the export info section:
```
cmd LC_DYLD_INFO_ONLY
...
export_off 5942960
export_size 207712
```
3. Create a hex dump of the export info section - [hex_dump_strip.list][4]
``` bash
xxd -s 5942960 -l 207712 bin/Release/net7.0-ios/ios-arm64/MySingleView.app/MySingleView > hex_dump_strip.list
```
- NOTE: Notice around ~200kb of zeroes from ~0x005ab490 to ~0x005dda00
4. Verify exported symbols are correct - [dyld_info_strip.list][5]
``` bash
dyld_info -exports bin/Release/net7.0-ios/ios-arm64/MySingleView.app/MySingleView > dyld_info_strip.list
```
### Repro current state of MySingleView.app with unstripped binary
1. Build the app (the make target preserves the symbols)
```bash
make run-device-no-strip
```
2. Print the load commands - [load_cmds_nostrip.list][6]
```bash
otool -l bin/Release/net7.0-ios/ios-arm64/MySingleView.app/MySingleView > load_cmds_nostrip.list
```
- We are interested in the export info section:
```
cmd LC_DYLD_INFO_ONLY
...
export_off 5942960
export_size 207712
```
3. Create a hex dump of the export info section - [hex_dump_nostrip.list][7]
``` bash
xxd -s 5942960 -l 207712 bin/Release/net7.0-ios/ios-arm64/MySingleView.app/MySingleView > hex_dump_nostrip.list
```
- Notice that the range: ~ 0x005ab490 to ~ 0x005dda00 now includes exported symbol entries
4. Verify exported symbols are correct - [dyld_info_nostrip.list][8]
``` bash
dyld_info -exports bin/Release/net7.0-ios/ios-arm64/MySingleView.app/MySingleView > dyld_info_nostrip.list
```
### Repro the new approach
1. Build the app (the make target uses the new approach)
```bash
make run-device-export-syms
```
2. Print the load commands - [load_cmds_export.list][9]
```bash
otool -l bin/Release/net7.0-ios/ios-arm64/MySingleView.app/MySingleView > load_cmds_export.list
```
- We are interested in the export info section ***notice the reduced size of the section***:
```
cmd LC_DYLD_INFO_ONLY
...
export_off 5942432
export_size 1048
```
3. Create a hex dump of the export info section - [hex_dump_export.list][10]
``` bash
xxd -s 5942432 -l 1048 bin/Release/net7.0-ios/ios-arm64/MySingleView.app/MySingleView > hex_dump_export.list
```
4. Verify exported symbols are correct - [dyld_info_export.list][11]
``` bash
dyld_info -exports bin/Release/net7.0-ios/ios-arm64/MySingleView.app/MySingleView > dyld_info_export.list
```
---
## Additional benefits
With this approach we could also switch the way strip tool is invoked to
always strip all debug and local symbols via `strip -S -x` instead of passing
the file with symbols to preserve. This would remove the warning that we are
currently getting (which is being ignored):
```
/Applications/Xcode_14.3.0.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/strip: warning: removing global symbols from a final linked no longer supported. Use -exported_symbols_list at link time when building...
```
## Other references:
- https://github.com/qyang-nj/llios/blob/main/exported_symbol/README.md
[1]: 11e7883da0/tools/dotnet-linker/Steps/GenerateReferencesStep.cs (L38-L44)
[2]: https://developer.apple.com/library/archive/documentation/DeveloperTools/Conceptual/DynamicLibraries/100-Articles/DynamicLibraryDesignGuidelines.html
[3]: https://gist.github.com/ivanpovazan/d53f8d10be5e4ea9f39a41ea540aa7fa
[4]: https://gist.github.com/ivanpovazan/60637422f3ff8cb5f437ddd06a21d9c1
[5]: https://gist.github.com/ivanpovazan/352595ad15c2ac02f38dcb3bd4130642
[6]: https://gist.github.com/ivanpovazan/bf700161f2f3691d1d7381c98d4fa0be
[7]: https://gist.github.com/ivanpovazan/44269e4fff5ebd58a4d181451e5c106f
[8]: https://gist.github.com/ivanpovazan/38c5afe076502d514a77420af0e10b01
[9]: https://gist.github.com/ivanpovazan/3f663c3c630005f5a578605d48ba807e
[10]: https://gist.github.com/ivanpovazan/0bb84f64281d05ab20438aeaed64f13c
[11]: https://gist.github.com/ivanpovazan/78b3ba2288f53a2316b9bc46964e7e4f
---------
Co-authored-by: Rolf Bjarne Kvinge <rolf@xamarin.com>
This property will be required when building for a net7.0-* target framework
using .NET 8 (preview 6 - preview 5 does not need this fix)
Backport of #18411