xamarin-macios/dotnet/targets/Xamarin.Shared.Sdk.props

125 строки
8.9 KiB
Plaintext
Исходник Обычный вид История

<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!-- Version information -->
<Import Project="Microsoft.$(_PlatformName).Sdk.Versions.props" />
<!-- This contains the OS versions we support for target platform -->
<Import Project="Microsoft.$(_PlatformName).Sdk.SupportedTargetPlatforms.props" />
<Import Project="Xamarin.Shared.Sdk.TargetFrameworkInference.props" />
<!-- Imports the .user.env file if exists and the build is from VS -->
<Import Project="$(MSBuildProjectFullPath).user.env" Condition="Exists('$(MSBuildProjectFullPath).user.env') And '$(BuildingInsideVisualStudio)' == 'true'" />
<PropertyGroup>
<!-- Set to true when using the Microsoft.<platform>.Sdk NuGet. This is used by pre-existing/shared targets to tweak behavior depending on build system -->
<UsingAppleNETSdk>true</UsingAppleNETSdk>
<!-- This is the location of the Microsoft.<platform>.Sdk NuGet (/usr/local/share/dotnet/sdk/<version>/Sdks/Microsoft.[iOS/tvOS/watchOS/macOS].Sdk) on the platform the build is running from (Mac or Win) -->
<_XamarinSdkRootDirectory>$([MSBuild]::NormalizePath('$(MSBuildThisFileDirectory)', '..'))\</_XamarinSdkRootDirectory>
<!-- This is the location of the Microsoft.<platform>.Sdk NuGet on macOS, this value will be overriden from Windows -->
<_XamarinSdkRootDirectoryOnMac>$(_XamarinSdkRootDirectory)</_XamarinSdkRootDirectoryOnMac>
<_XamarinTaskAssembly Condition="'$(_PlatformName)' != 'macOS'">$(_XamarinSdkRootDirectory)\tools\msbuild\iOS\Xamarin.iOS.Tasks.dll</_XamarinTaskAssembly>
<_XamarinTaskAssembly Condition="'$(_PlatformName)' == 'macOS'">$(_XamarinSdkRootDirectory)\tools\msbuild\macOS\Xamarin.Mac.Tasks.dll</_XamarinTaskAssembly>
<SuppressTrimAnalysisWarnings Condition=" '$(SuppressTrimAnalysisWarnings)' == '' ">true</SuppressTrimAnalysisWarnings>
<AfterMicrosoftNETSdkTargets>$(AfterMicrosoftNETSdkTargets);$(MSBuildThisFileDirectory)Microsoft.$(_PlatformName).Sdk.targets</AfterMicrosoftNETSdkTargets>
<!-- _XamarinSdkRoot is used by the existing MSBuild targets files -->
<_XamarinSdkRoot Condition="'$(_XamarinSdkRoot)' == ''">$(_XamarinSdkRootDirectory)</_XamarinSdkRoot>
<!-- _XamarinSdkRootOnMac this should be passed to tasks that need to access the Xamarin Sdk dir on the Mac, this value will be overriden from Windows -->
<_XamarinSdkRootOnMac>$(_XamarinSdkRoot)</_XamarinSdkRootOnMac>
<!-- We don't need any dependency files -->
<GenerateDependencyFile Condition="'$(GenerateDependencyFile)' == ''">false</GenerateDependencyFile>
<!-- MSBuild will discard the 'PublishFolderType' metadata on items unless we set these properties -->
<MSBuildDisableGetCopyToOutputDirectoryItemsOptimization>true</MSBuildDisableGetCopyToOutputDirectoryItemsOptimization>
<MSBuildDisableGetCopyToPublishDirectoryItemsOptimization>true</MSBuildDisableGetCopyToPublishDirectoryItemsOptimization>
<!-- Do we need a RuntimeIdentifier? For apps and app extensions we do -->
<_RuntimeIdentifierIsRequired Condition="'$(OutputType)' == 'Exe' Or '$(IsAppExtension)' == 'true'">true</_RuntimeIdentifierIsRequired>
<!-- The logic to compute the default value for GenerateSatelliteAssembliesForCore is wrong when building inside Visual Studio (Windows), so make sure it defaults to the correct value -->
<!-- Ref: https://github.com/xamarin/xamarin-macios/issues/16193 -->
<!-- Ref: https://github.com/dotnet/sdk/issues/28419 -->
<GenerateSatelliteAssembliesForCore Condition="'$(GenerateSatelliteAssembliesForCore)' == ''">true</GenerateSatelliteAssembliesForCore>
[dotnet] Ensure any trimmer components are restored properly. (#17227) .NET 8 will load the ILLink component based on the target framework of the project file - so if .NET 8 is building a net7.0-ios app, the build will restore and use the ILLink component from .NET 7. There is a problem however: * The inclusion of the ILLink component is dpendent on the PublishTrimmed property - if PublishTrimmed is true, then the ILLink component is restored (which makes sense, why restore it if it's not going to be used?). * We always PublishTrimmed, because the linker must always be executed for our projects. So far so good - we can just always enable PublishTrimmed, right? * Nope, when building on Windows, we only enable PublishTrimmed when connected to a Mac, because that's where the ILLink target must be executed (and if we're not connected to a Mac, we can't run the ILLink target, and things fall apart - so just disable PublishTrimmed in that, since it won't work anyway). * Early on in the build we have no idea if we're connected to a Mac or not, which means we can only enable PublishTrimmed in a target, and not as an early-on default value. This is *way* to late for the ILLink component, which needs PublishTrimmed set quite early in the build process. * Fortunately, the ILLink inclusion is actually gated on a different variable (_IsTrimmingEnabled) - which is initialized from PublishTrimmed if it's not set. So the way out here is to set _IsTrimmingEnabled early enough, and now the ILLink component is included and restored. * The additional hurdle is that we need to set _IsTrimmingEnabled in our .NET 6 and .NET 7 workloads as well, it's not enough to set it in our .NET 8 workload (which isn't even loaded when building an earlier TFM).
2023-01-16 10:21:09 +03:00
<!-- This will ensure any trimmer components are restored by the framework reference logic. As such it must happen before Microsoft.NET.Publish.targets is included.
Ref:
* https://github.com/dotnet/sdk/pull/29441
* https://github.com/dotnet/sdk/blob/c5a58bc6c3eb2b236b314e6d17a89a537459890c/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Publish.targets#L20-L21
* https://github.com/dotnet/sdk/blob/c5a58bc6c3eb2b236b314e6d17a89a537459890c/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Sdk.FrameworkReferenceResolution.targets#L102
-->
<_IsTrimmingEnabled>true</_IsTrimmingEnabled>
<!-- The GRCF property is contingent upon the HasRuntimeOutput property, which is only defined for executable projects. So, explicitly define GRCF for extension projects to avoid warnings at build time. -->
<GenerateRuntimeConfigurationFiles Condition="'$(IsAppExtension)' == 'true'">true</GenerateRuntimeConfigurationFiles>
<!-- Setting _RequiresILLinkPack to true so that the ILLink pack is always restored. -->
<_RequiresILLinkPack Condition="'$(_RequiresILLinkPack)' == ''">true</_RequiresILLinkPack>
Reduce the size of `__LINKEDIT Export Info` section in stripped binaries (#18408) # 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]: https://github.com/xamarin/xamarin-macios/blob/11e7883da04d80c59e4ffbbc955a3e0e0060ff90/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>
2023-06-12 14:45:38 +03:00
<!-- Explicitly export symbols using clang command-line option "-exported_symbols_list export_list" -->
<_ExportSymbolsExplicitly Condition="'$(_ExportSymbolsExplicitly)' == ''">true</_ExportSymbolsExplicitly>
<!--
Some runtime libraries feature switches defaults that need to be set early
Available feature switches: https://github.com/dotnet/runtime/blob/master/docs/workflow/trimming/feature-switches.md
-->
<!-- AutoreleasePoolSupport needs to be set earlier than other switches, so that illink doesn't override it - https://github.com/dotnet/runtime/pull/86753 - so it's set here, instead of in Xamarin.Shared.Sdk.targets -->
<AutoreleasePoolSupport Condition="'$(AutoreleasePoolSupport)' == ''">true</AutoreleasePoolSupport>
</PropertyGroup>
<!-- Set the default RuntimeIdentifier if not already specified. -->
<PropertyGroup Condition="'$(_RuntimeIdentifierIsRequired)' == 'true' And '$(RuntimeIdentifier)' == '' And '$(RuntimeIdentifiers)' == '' ">
<!-- The _<platform>RuntimeIdentifier values are set from the IDE -->
<RuntimeIdentifier Condition="'$(_PlatformName)' == 'iOS'">$(_iOSRuntimeIdentifier)</RuntimeIdentifier>
<RuntimeIdentifier Condition="'$(_PlatformName)' == 'tvOS'">$(_tvOSRuntimeIdentifier)</RuntimeIdentifier>
<RuntimeIdentifier Condition="'$(_PlatformName)' == 'macOS'">$(_macOSRuntimeIdentifier)</RuntimeIdentifier>
<RuntimeIdentifier Condition="'$(_PlatformName)' == 'MacCatalyst'">$(_MacCatalystRuntimeIdentifier)</RuntimeIdentifier>
<_XamarinUsingDefaultRuntimeIdentifier Condition="'$(RuntimeIdentifier)' == ''">true</_XamarinUsingDefaultRuntimeIdentifier>
<RuntimeIdentifier Condition="'$(RuntimeIdentifier)' == '' And '$(_PlatformName)' == 'iOS'">iossimulator-x64</RuntimeIdentifier>
<RuntimeIdentifier Condition="'$(RuntimeIdentifier)' == '' And '$(_PlatformName)' == 'tvOS'">tvossimulator-x64</RuntimeIdentifier>
<!-- For release desktop builds we default to universal apps in .NET 7+ -->
<RuntimeIdentifier Condition="'$(RuntimeIdentifier)' == '' And '$(Configuration)' != 'Release' And '$(_PlatformName)' == 'macOS'">osx-x64</RuntimeIdentifier>
<RuntimeIdentifier Condition="'$(RuntimeIdentifier)' == '' And '$(Configuration)' != 'Release' And '$(_PlatformName)' == 'MacCatalyst'">maccatalyst-x64</RuntimeIdentifier>
<RuntimeIdentifiers Condition="'$(RuntimeIdentifier)' == '' And '$(Configuration)' == 'Release' And '$(_PlatformName)' == 'macOS'">osx-x64;osx-arm64</RuntimeIdentifiers>
<RuntimeIdentifiers Condition="'$(RuntimeIdentifier)' == '' And '$(Configuration)' == 'Release' And '$(_PlatformName)' == 'MacCatalyst'">maccatalyst-x64;maccatalyst-arm64</RuntimeIdentifiers>
</PropertyGroup>
<!-- We're never using any app hosts -->
<PropertyGroup>
<_RuntimeIdentifierUsesAppHost>false</_RuntimeIdentifierUsesAppHost>
<UseAppHost>false</UseAppHost>
</PropertyGroup>
[net8.0] Update dependencies from dotnet/installer (#18271) 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.5.23252.13 to 8.0.0-preview.5.23260.3 (parent: Microsoft.Dotnet.Sdk.Internal) - **Microsoft.AspNetCore.App.Ref**: from 8.0.0-preview.5.23252.26 to 8.0.0-preview.5.23262.1 (parent: Microsoft.Dotnet.Sdk.Internal) - **Microsoft.NETCore.App.Ref**: from 8.0.0-preview.5.23252.13 to 8.0.0-preview.5.23260.3 (parent: Microsoft.Dotnet.Sdk.Internal) - **Microsoft.NET.Workload.Emscripten.Current.Manifest-8.0.100.Transport**: from 8.0.0-preview.5.23225.2 to 8.0.0-preview.5.23252.1 (parent: Microsoft.NETCore.App.Ref) - **Microsoft.NETCore.App.Ref**: from 8.0.0-preview.5.23252.13 to 8.0.0-preview.5.23260.3 (parent: Microsoft.Dotnet.Sdk.Internal) ## From https://github.com/dotnet/installer - **Subscription**: f9b68d84-9c90-4bd0-5499-08db4112d57e - **Build**: 20230517.7 - **Date Produced**: May 17, 2023 9:29:46 PM UTC - **Commit**: dda516cbd77ab9dc3c6048a1893b4321cdcda195 - **Branch**: refs/heads/main - **Updates**: - **Microsoft.Dotnet.Sdk.Internal**: [from 8.0.100-preview.5.23258.8 to 8.0.100-preview.5.23267.7][29] - **Microsoft.NET.ILLink.Tasks**: [from 8.0.0-preview.5.23252.13 to 8.0.0-preview.5.23260.3][30] - **Microsoft.AspNetCore.App.Ref**: [from 8.0.0-preview.5.23252.26 to 8.0.0-preview.5.23262.1][31] - **Microsoft.NETCore.App.Ref**: [from 8.0.0-preview.5.23252.13 to 8.0.0-preview.5.23260.3][30] - **Microsoft.NET.Workload.Emscripten.Current.Manifest-8.0.100.Transport**: [from 8.0.0-preview.5.23225.2 to 8.0.0-preview.5.23252.1][32] - **Microsoft.NETCore.App.Ref**: [from 8.0.0-preview.5.23252.13 to 8.0.0-preview.5.23260.3][30] [29]: https://github.com/dotnet/installer/compare/1ab664ce1c...dda516cbd7 [30]: https://github.com/dotnet/runtime/compare/bc9dad2351...888bac3044 [31]: https://github.com/dotnet/aspnetcore/compare/730dac21a5...059939bda4 [32]: https://github.com/dotnet/emsdk/compare/81590b9b84...ab09b0b8d6
2023-05-19 08:33:48 +03:00
<!-- If a runtime identifier is required, and we have a runtime identifier, then we must be self contained.
This of course begs the question: when could we have a runtime identifier and such a thing would not be required?
The answer is: library projects may end up with a RuntimeIdentifier when building a referencing executable project
from the command line, and that command line specifies a RuntimeIdentifier -->
<PropertyGroup Condition="'$(_RuntimeIdentifierIsRequired)' == 'true' And '$(RuntimeIdentifier)' != ''">
<SelfContained>true</SelfContained>
</PropertyGroup>
<!--
Enable LLVM by default for mobile release builds.
At this point we don't necessarily know yet whether we're building for device or simulator,
but the MtouchUseLlvm value is ignored when using the simulator, so it doesn't matter
if we set it in all cases.
-->
<PropertyGroup Condition="'$(MtouchUseLlvm)' == '' And '$(Configuration)' == 'Release' And ('$(_PlatformName)' == 'iOS' Or '$(_PlatformName)' == 'tvOS')">
<MtouchUseLlvm>true</MtouchUseLlvm>
</PropertyGroup>
<!-- Various options when using NativeAOT -->
<PropertyGroup Condition="'$(PublishAot)' == 'true'">
<!-- Disable our own assembly IL stripping logic, because ILC does that already -->
<EnableAssemblyILStripping>false</EnableAssemblyILStripping>
<!-- We're using our own native main function when using NativeAOT -->
<CustomNativeMain>true</CustomNativeMain>
</PropertyGroup>
</Project>