Skip to content

Commit

Permalink
Add support for using NativeAOT. (#17374)
Browse files Browse the repository at this point in the history
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 #17339.
  • Loading branch information
rolfbjarne authored Jun 22, 2023
2 parents 1893fc0 + b4e3361 commit 9b72a75
Show file tree
Hide file tree
Showing 36 changed files with 600 additions and 108 deletions.
4 changes: 2 additions & 2 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,15 @@
[submodule "external/Touch.Unit"]
path = external/Touch.Unit
url = ../../spouliot/Touch.Unit.git
branch = main
branch = net8.0
[submodule "external/Xamarin.MacDev"]
path = external/Xamarin.MacDev
url = ../../xamarin/Xamarin.MacDev
branch = main
[submodule "external/MonoTouch.Dialog"]
path = external/MonoTouch.Dialog
url = ../../migueldeicaza/MonoTouch.Dialog
branch = dotnet
branch = net8.0
[submodule "api-tools"]
path = external/api-tools
url = ../../rolfbjarne/api-tools
Expand Down
10 changes: 10 additions & 0 deletions Make.config
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,12 @@ DOTNET_MIN_TVOS_SDK_VERSION=11.0
DOTNET_MIN_MACCATALYST_SDK_VERSION=13.1
DOTNET_MIN_MACOS_SDK_VERSION=10.15

# Minimum OS versions when using NativeOAT - these are at least the general min versions above (but may be higher).
DOTNET_MIN_NATIVEAOT_IOS_SDK_VERSION=12.2
DOTNET_MIN_NATIVEAOT_TVOS_SDK_VERSION=12.2
DOTNET_MIN_NATIVEAOT_MACCATALYST_SDK_VERSION=13.1
DOTNET_MIN_NATIVEAOT_MACOS_SDK_VERSION=10.15

# The min simulator version available in the Xcode we're using
MIN_IOS_SIMULATOR_VERSION=13.7
MIN_WATCHOS_SIMULATOR_VERSION=7.0
Expand Down Expand Up @@ -712,6 +718,7 @@ DOTNET_PLATFORMS=
ifdef INCLUDE_IOS
DOTNET_PLATFORMS+=iOS
DOTNET_IOS_BITNESSES+=64
DOTNET_NATIVEAOT_PLATFORMS+=iOS

# 32-bit architectures
ifdef IOS_SUPPORTS_32BIT_ARCHITECTURES
Expand All @@ -735,6 +742,7 @@ endif # INCLUDE_IOS
ifdef INCLUDE_TVOS
DOTNET_PLATFORMS+=tvOS
DOTNET_TVOS_BITNESSES+=64
DOTNET_NATIVEAOT_PLATFORMS+=tvOS
ifdef INCLUDE_DEVICE
DOTNET_TVOS_RUNTIME_IDENTIFIERS=tvos-arm64 tvossimulator-x64 tvossimulator-arm64
else
Expand All @@ -758,6 +766,7 @@ endif
ifdef INCLUDE_MACCATALYST
DOTNET_PLATFORMS+=MacCatalyst
DOTNET_MACCATALYST_BITNESSES+=64
DOTNET_NATIVEAOT_PLATFORMS+=MacCatalyst
DOTNET_MACCATALYST_RUNTIME_IDENTIFIERS=maccatalyst-x64 maccatalyst-arm64
DOTNET_MACCATALYST_RUNTIME_IDENTIFIERS_64+=$(DOTNET_MACCATALYST_RUNTIME_IDENTIFIERS)
endif
Expand All @@ -766,6 +775,7 @@ ifdef INCLUDE_MAC
DOTNET_PLATFORMS+=macOS
DOTNET_CORECLR_PLATFORMS+=macOS
DOTNET_MACOS_BITNESSES+=64
DOTNET_NATIVEAOT_PLATFORMS+=macOS
DOTNET_MACOS_RUNTIME_IDENTIFIERS=osx-x64 osx-arm64
DOTNET_MACOS_RUNTIME_IDENTIFIERS_64=$(DOTNET_MACOS_RUNTIME_IDENTIFIERS)
endif
Expand Down
20 changes: 16 additions & 4 deletions dotnet/generate-target-platforms.csharp
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,16 @@ var doc = new XmlDocument ();
doc.Load (plistPath);
var nodes = doc.SelectNodes ($"/plist/dict/key[text()='KnownVersions']/following-sibling::dict[1]/key[text()='{platform}']/following-sibling::array[1]/string");

var allLines = File.ReadAllLines ("../Make.config");

var minSdkVersionName = $"DOTNET_MIN_{platform.ToUpper ()}_SDK_VERSION";
var minSdkVersionString = File.ReadAllLines ("../Make.config").Single (v => v.StartsWith (minSdkVersionName + "=", StringComparison.Ordinal)).Substring (minSdkVersionName.Length + 1);
var minSdkVersionString = allLines.Single (v => v.StartsWith (minSdkVersionName + "=", StringComparison.Ordinal)).Substring (minSdkVersionName.Length + 1);
var minSdkVersion = Version.Parse (minSdkVersionString);

var minNativeAotSdkVersionName = $"DOTNET_MIN_NATIVEAOT_{platform.ToUpper ()}_SDK_VERSION";
var minNativeAotSdkVersionString = allLines.Single (v => v.StartsWith (minNativeAotSdkVersionName + "=", StringComparison.Ordinal)).Substring (minNativeAotSdkVersionName.Length + 1);
var minNativeAotSdkVersion = Version.Parse (minNativeAotSdkVersionString);

using (TextWriter writer = new StreamWriter (outputPath)) {
writer.WriteLine ($"<!-- This file contains a generated list of the {platform} platform versions that are supported for this SDK -->");
writer.WriteLine ($"<!-- Generation script: https://github.com/xamarin/xamarin-macios/blob/main/dotnet/generate-target-platforms.csharp -->");
Expand All @@ -36,17 +42,23 @@ using (TextWriter writer = new StreamWriter (outputPath)) {

foreach (XmlNode n in nodes) {
var version = n.InnerText;
if (Version.Parse (version) < minSdkVersion)
var parsedVersion = Version.Parse (version);
if (parsedVersion < minSdkVersion)
continue;
writer.WriteLine ($"\t\t<{platform}SdkSupportedTargetPlatformVersion Include=\"{n.InnerText}\" />");
if (parsedVersion < minNativeAotSdkVersion) {
writer.WriteLine ($"\t\t<{platform}SdkSupportedTargetPlatformVersion Include=\"{n.InnerText}\" Condition=\"!('$(PublishAot)' == 'true' And '$(_IsPublishing)' == 'true')\" />");
} else {
writer.WriteLine ($"\t\t<{platform}SdkSupportedTargetPlatformVersion Include=\"{n.InnerText}\" />");
}
}

writer.WriteLine ("\t</ItemGroup>");
writer.WriteLine ("\t<ItemGroup>");
writer.WriteLine ($"\t\t<SdkSupportedTargetPlatformVersion Condition=\"'$(TargetPlatformIdentifier)' == '{platform}'\" Include=\"@({platform}SdkSupportedTargetPlatformVersion)\" />");
writer.WriteLine ("\t</ItemGroup>");
writer.WriteLine ("\t<PropertyGroup>");
writer.WriteLine ($"\t\t<{platform}MinSupportedOSPlatformVersion>{minSdkVersionString}</{platform}MinSupportedOSPlatformVersion>");
writer.WriteLine ($"\t\t<{platform}MinSupportedOSPlatformVersion Condition=\"!('$(PublishAot)' == 'true' And '$(_IsPublishing)' == 'true')\">{minSdkVersionString}</{platform}MinSupportedOSPlatformVersion>");
writer.WriteLine ($"\t\t<{platform}MinSupportedOSPlatformVersion Condition=\"'$(PublishAot)' == 'true' And '$(_IsPublishing)' == 'true'\">{minNativeAotSdkVersionString}</{platform}MinSupportedOSPlatformVersion>");
writer.WriteLine ("\t</PropertyGroup>");
writer.WriteLine ("</Project>");
}
Expand Down
11 changes: 10 additions & 1 deletion dotnet/targets/Xamarin.Shared.Sdk.DefaultItems.targets
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,17 @@
<EnableDefaultmacOSItems Condition=" '$(_PlatformName)' == 'macOS' And '$(EnableDefaultmacOSItems)' == '' ">$(EnableDefaultItems)</EnableDefaultmacOSItems>
<EnableDefaultMacCatalystItems Condition=" '$(_PlatformName)' == 'MacCatalyst' And '$(EnableDefaultMacCatalystItems)' == '' ">$(EnableDefaultItems)</EnableDefaultMacCatalystItems>

<UseMonoRuntime Condition=" '$(UseMonoRuntime)' == '' And '$(_PlatformName)' != 'macOS'">true</UseMonoRuntime>
<!--
PublishAot should only take effect when doing 'dotnet publish', not when doing 'dotnet build'. We distinguish these cases using the '_IsPublishing' property,
but it's rather annoying to always have to check both PublishAot and _IsPublishing to see if we're using NativeAOT, so introduce a third property that's
only set to true if both PublishAot=true and _IsPublishing=true
-->
<_UseNativeAot Condition="'$(PublishAot)' == 'true' And '$(_IsPublishing)' == 'true'">true</_UseNativeAot>

<UseMonoRuntime Condition=" '$(UseMonoRuntime)' == '' And '$(_PlatformName)' == 'macOS'">false</UseMonoRuntime>
<UseMonoRuntime Condition=" '$(UseMonoRuntime)' == '' And '$(_UseNativeAot)' == 'true'">false</UseMonoRuntime>
<UseMonoRuntime Condition=" '$(UseMonoRuntime)' == ''">true</UseMonoRuntime>

</PropertyGroup>

<ItemGroup>
Expand Down
39 changes: 39 additions & 0 deletions dotnet/targets/Xamarin.Shared.Sdk.props
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,13 @@

<!-- 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. -->
Expand Down Expand Up @@ -95,6 +102,20 @@
<SelfContained>true</SelfContained>
</PropertyGroup>

<!--
SelfContained is automatically enabled if PublishAot is true, and that
doesn't work properly (restore fails because RuntimeIdentifier is not
set) when doing the outer build of a universal apps (when
RuntimeIdentifier=''), so manually disable SelfContained in that case.
This might not be necessary after: https://github.com/dotnet/sdk/pull/33229
-->
<PropertyGroup Condition="'$(PublishAot)' == 'true' And '$(_IsPublishing)' == 'true' And '$(RuntimeIdentifiers)' != '' And '$(RuntimeIdentifier)' == '' And '$(SelfContained)' == ''">
<SelfContained>false</SelfContained>
</PropertyGroup>

<!--
Enable LLVM by default for mobile release builds.
Expand All @@ -105,4 +126,22 @@
<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' And '$(_IsPublishing)' == '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>

<!-- We must find the BCL libraries using the runtime pack instead of using the built-in NativeAOT BCL -->
<PublishAotUsingRuntimePack>true</PublishAotUsingRuntimePack>

<!-- This turns off some NativeAOT logic we don't want nor need -->
<NativeCompilationDuringPublish>false</NativeCompilationDuringPublish>

<!-- This works around an issue in NativeAOT: https://github.com/dotnet/runtime/issues/86186 -->
<IlcKeepManagedDebuggerSupport>true</IlcKeepManagedDebuggerSupport>
</PropertyGroup>
</Project>
Loading

6 comments on commit 9b72a75

@vs-mobiletools-engineering-service2

This comment was marked as outdated.

@vs-mobiletools-engineering-service2

This comment was marked as outdated.

@vs-mobiletools-engineering-service2

This comment was marked as outdated.

@vs-mobiletools-engineering-service2

This comment was marked as outdated.

@vs-mobiletools-engineering-service2

This comment was marked as outdated.

@vs-mobiletools-engineering-service2

This comment was marked as outdated.

Please sign in to comment.