NativeAOT: Enable building app extensions with NativeAOT (#20872)
### Description
This PR enables building app extensions with NativeAOT.
App extensions are class libraries and to build them with NativeAOT we
must not specify `CustomNativeMain=true`. If we do, ILC would expect
that the input assembly has a managed Main as the module entry point.
Additionally, when building class libraries (with the absence of a
managed Main entry point), our static reference from:
2e5ef1eb1c/runtime/nativeaot-bridge.m (L39)
requires build-time symbol resolution. To avoid linking errors, we
generate an empty `__managed__Main`
in the native bootstrapping code of the app extension (e.g., in
`main.arm64.mm`).
### Testing
The unit tests have been introduced to test building app extensions with
both Mono and NativeAOT.
Executing an iOS app TodayExtension built with NativeAOT has been
verified manually on an actual device.
---
Fixes: https://github.com/xamarin/xamarin-macios/issues/20653
This commit is contained in:
Родитель
e1290d2f15
Коммит
374e902075
|
@ -229,7 +229,12 @@
|
|||
<!-- 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're using our own native main function when using NativeAOT.
|
||||
This is true for both: managed executables and app extensions (which are libraries).
|
||||
Since ILC expects to find a managed main function whenever NativeLib=static and CustomNativeMain=true,
|
||||
we are only setting this flag when we are building executables. (Class libraries do not have a managed Main)
|
||||
-->
|
||||
<CustomNativeMain Condition="'$(OutputType)' == 'Exe'">true</CustomNativeMain>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
|
|
|
@ -3,7 +3,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00
|
|||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.30114.105
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MySimpleApp", "MySimpleApp.csproj", "{23664512-6B06-4135-9A94-C012BDA93CB1}"
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ExtensionConsumer", "ExtensionConsumer.csproj", "{23664512-6B06-4135-9A94-C012BDA93CB1}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ExtensionProject", "..\..\ExtensionProject\iOS\ExtensionProject.csproj", "{8A72DB8F-4C30-4462-9F7A-6095E41D5D46}"
|
||||
EndProject
|
||||
|
|
|
@ -3,7 +3,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00
|
|||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.30114.105
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MySimpleApp", "MySimpleApp.csproj", "{B7C29D40-0079-416C-8507-FE9EE82FBD4F}"
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ExtensionConsumer", "ExtensionConsumer.csproj", "{B7C29D40-0079-416C-8507-FE9EE82FBD4F}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ExtensionProject", "..\..\ExtensionProject\macOS\ExtensionProject.csproj", "{C32EB68F-1FF7-42DE-ABD8-C0151497595A}"
|
||||
EndProject
|
||||
|
|
|
@ -3,7 +3,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00
|
|||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.30114.105
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MySimpleApp", "MySimpleApp.csproj", "{D8448FDC-1002-432B-A3A7-CCFCB833F292}"
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ExtensionConsumer", "ExtensionConsumer.csproj", "{D8448FDC-1002-432B-A3A7-CCFCB833F292}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ExtensionProject", "..\..\ExtensionProject\tvOS\ExtensionProject.csproj", "{CD69BE1D-FF1B-4B6A-AB6E-5259E65B515E}"
|
||||
EndProject
|
||||
|
|
|
@ -1063,22 +1063,36 @@ namespace Xamarin.Tests {
|
|||
}
|
||||
|
||||
|
||||
[TestCase (ApplePlatform.iOS)]
|
||||
[TestCase (ApplePlatform.TVOS)]
|
||||
[TestCase (ApplePlatform.MacOSX)]
|
||||
[TestCase (ApplePlatform.iOS, "ios-arm64", false)]
|
||||
[TestCase (ApplePlatform.iOS, "ios-arm64", true)]
|
||||
[TestCase (ApplePlatform.iOS, "iossimulator-x64", false)]
|
||||
[TestCase (ApplePlatform.iOS, "iossimulator-x64", true)]
|
||||
[TestCase (ApplePlatform.TVOS, "tvossimulator-x64", false)]
|
||||
[TestCase (ApplePlatform.TVOS, "tvossimulator-x64", true)]
|
||||
[TestCase (ApplePlatform.MacOSX, "osx-x64", false)]
|
||||
[TestCase (ApplePlatform.MacOSX, "osx-x64", true)]
|
||||
[TestCase (ApplePlatform.MacOSX, "osx-x64;osx-arm64", false)]
|
||||
// [TestCase (ApplePlatform.MacOSX, "osx-x64;osx-arm64", true)] See: https://github.com/xamarin/xamarin-macios/issues/20903
|
||||
// [TestCase ("MacCatalyst", "")] - No extension support yet
|
||||
public void BuildProjectsWithExtensions (ApplePlatform platform)
|
||||
public void BuildProjectsWithExtensions (ApplePlatform platform, string runtimeIdentifier, bool isNativeAot)
|
||||
{
|
||||
Configuration.IgnoreIfIgnoredPlatform (platform);
|
||||
var consumingProjectDir = GetProjectPath ("ExtensionConsumer", platform: platform);
|
||||
var consumingProjectDir = GetProjectPath ("ExtensionConsumer", runtimeIdentifier, platform, out var appPath);
|
||||
var extensionProjectDir = GetProjectPath ("ExtensionProject", platform: platform);
|
||||
|
||||
Clean (extensionProjectDir);
|
||||
Clean (consumingProjectDir);
|
||||
|
||||
DotNet.AssertBuild (consumingProjectDir, verbosity);
|
||||
var properties = GetDefaultProperties (runtimeIdentifier);
|
||||
|
||||
var extensionPath = Path.Combine (Path.GetDirectoryName (consumingProjectDir)!, "bin", "Debug", platform.ToFramework (), GetDefaultRuntimeIdentifier (platform), "MySimpleApp.app", GetPlugInsRelativePath (platform), "ExtensionProject.appex");
|
||||
if (isNativeAot) {
|
||||
properties ["PublishAot"] = "true";
|
||||
properties ["_IsPublishing"] = "true";
|
||||
}
|
||||
|
||||
DotNet.AssertBuild (consumingProjectDir, properties);
|
||||
|
||||
var extensionPath = Path.Combine (appPath, GetPlugInsRelativePath (platform), "ExtensionProject.appex");
|
||||
Assert.That (Directory.Exists (extensionPath), $"App extension directory does not exist: {extensionPath}");
|
||||
|
||||
var pathToSearch = Path.Combine (Path.GetDirectoryName (consumingProjectDir)!, "bin", "Debug");
|
||||
|
@ -1086,23 +1100,34 @@ namespace Xamarin.Tests {
|
|||
Assert.AreNotEqual (0, configFiles.Length, "runtimeconfig.json file does not exist");
|
||||
}
|
||||
|
||||
[TestCase (ApplePlatform.iOS)]
|
||||
[TestCase (ApplePlatform.TVOS)]
|
||||
[TestCase (ApplePlatform.MacOSX)]
|
||||
[TestCase (ApplePlatform.iOS, "iossimulator-x64", false)]
|
||||
[TestCase (ApplePlatform.iOS, "iossimulator-x64", true)]
|
||||
[TestCase (ApplePlatform.TVOS, "tvossimulator-x64", false)]
|
||||
[TestCase (ApplePlatform.TVOS, "tvossimulator-x64", true)]
|
||||
[TestCase (ApplePlatform.MacOSX, "osx-x64", false)]
|
||||
[TestCase (ApplePlatform.MacOSX, "osx-x64", true)]
|
||||
[TestCase (ApplePlatform.MacOSX, "osx-x64;osx-arm64", false)]
|
||||
// [TestCase (ApplePlatform.MacOSX, "osx-x64;osx-arm64", true)] See: https://github.com/xamarin/xamarin-macios/issues/20903
|
||||
// [TestCase ("MacCatalyst", "")] - No extension support yet
|
||||
public void BuildProjectsWithExtensionsAndFrameworks (ApplePlatform platform)
|
||||
public void BuildProjectsWithExtensionsAndFrameworks (ApplePlatform platform, string runtimeIdentifier, bool isNativeAot)
|
||||
{
|
||||
Configuration.IgnoreIfIgnoredPlatform (platform);
|
||||
var runtimeIdentifiers = GetDefaultRuntimeIdentifier (platform);
|
||||
var consumingProjectDir = GetProjectPath ("ExtensionConsumerWithFrameworks", runtimeIdentifiers: runtimeIdentifiers, platform: platform, out var appPath);
|
||||
var consumingProjectDir = GetProjectPath ("ExtensionConsumerWithFrameworks", runtimeIdentifiers: runtimeIdentifier, platform: platform, out var appPath);
|
||||
var extensionProjectDir = GetProjectPath ("ExtensionProjectWithFrameworks", platform: platform);
|
||||
|
||||
Clean (extensionProjectDir);
|
||||
Clean (consumingProjectDir);
|
||||
|
||||
DotNet.AssertBuild (consumingProjectDir, verbosity);
|
||||
var properties = GetDefaultProperties (runtimeIdentifier);
|
||||
|
||||
var extensionPath = Path.Combine (Path.GetDirectoryName (consumingProjectDir)!, "bin", "Debug", platform.ToFramework (), GetDefaultRuntimeIdentifier (platform), "ExtensionConsumerWithFrameworks.app", GetPlugInsRelativePath (platform), "ExtensionProjectWithFrameworks.appex");
|
||||
if (isNativeAot) {
|
||||
properties ["PublishAot"] = "true";
|
||||
properties ["_IsPublishing"] = "true";
|
||||
}
|
||||
|
||||
DotNet.AssertBuild (consumingProjectDir, properties);
|
||||
|
||||
var extensionPath = Path.Combine (appPath, GetPlugInsRelativePath (platform), "ExtensionProjectWithFrameworks.appex");
|
||||
Assert.That (Directory.Exists (extensionPath), $"App extension directory does not exist: {extensionPath}");
|
||||
var extensionFrameworksPath = Path.Combine (extensionPath, GetFrameworksRelativePath (platform));
|
||||
Assert.IsFalse (Directory.Exists (extensionFrameworksPath), $"App extension framework directory exists when it shouldn't: {extensionFrameworksPath}");
|
||||
|
@ -1119,7 +1144,7 @@ namespace Xamarin.Tests {
|
|||
Assert.That (File.Exists (Path.Combine (appFrameworksPath, "UnknownE.framework", "UnknownE")), "UnknownE");
|
||||
|
||||
var appExecutable = GetNativeExecutable (platform, appPath);
|
||||
ExecuteWithMagicWordAndAssert (platform, runtimeIdentifiers, appExecutable);
|
||||
ExecuteWithMagicWordAndAssert (platform, runtimeIdentifier, appExecutable);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -897,6 +897,13 @@ namespace Xamarin.Bundler {
|
|||
sw.WriteLine ("\treturn rv;");
|
||||
sw.WriteLine ("}");
|
||||
|
||||
// Add an empty __managed__Main function when building class lib app extensions with NativeAOT to workaround static reference to this symbol from nativeaot-bridge.m
|
||||
if (app.IsExtension && app.XamarinRuntime == XamarinRuntime.NativeAOT) {
|
||||
sw.WriteLine ();
|
||||
sw.Write ("extern \"C\" int __managed__Main (int argc, const char** argv) { return 0; } ");
|
||||
sw.WriteLine ();
|
||||
}
|
||||
|
||||
string extension_main = null;
|
||||
if (app.Platform == ApplePlatform.WatchOS && app.IsWatchExtension) {
|
||||
// We're building a watch extension, and we have multiple scenarios, depending on the watchOS version we're executing on:
|
||||
|
|
|
@ -87,7 +87,7 @@ namespace Xamarin {
|
|||
if (app.IsTVExtension) {
|
||||
extensionlib = "libtvextension-dotnet.a";
|
||||
} else if (app.IsExtension) {
|
||||
if (app.XamarinRuntime == Bundler.XamarinRuntime.CoreCLR) {
|
||||
if (app.XamarinRuntime == Bundler.XamarinRuntime.CoreCLR || (app.XamarinRuntime == Bundler.XamarinRuntime.NativeAOT && app.Platform == Xamarin.Utils.ApplePlatform.MacOSX)) {
|
||||
extensionlib = "libextension-dotnet-coreclr.a";
|
||||
} else {
|
||||
extensionlib = "libextension-dotnet.a";
|
||||
|
|
Загрузка…
Ссылка в новой задаче