Skip to content

Commit b4975e2

Browse files
authored
Fix non-NativeAOT builds with PublishAot=true in the project file (#18727)
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 <[email protected]>
1 parent c9032f2 commit b4975e2

File tree

3 files changed

+47
-6
lines changed

3 files changed

+47
-6
lines changed

dotnet/targets/Xamarin.Shared.Sdk.props

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,10 @@
145145
</PropertyGroup>
146146

147147
<!-- Various options when using NativeAOT -->
148+
<PropertyGroup Condition="'$(PublishAot)' == 'true'">
149+
<!-- This turns off some NativeAOT logic we don't want nor need -->
150+
<NativeCompilationDuringPublish>false</NativeCompilationDuringPublish>
151+
</PropertyGroup>
148152
<PropertyGroup Condition="'$(PublishAot)' == 'true' And '$(_IsPublishing)' == 'true'">
149153
<!-- Disable our own assembly IL stripping logic, because ILC does that already -->
150154
<EnableAssemblyILStripping>false</EnableAssemblyILStripping>
@@ -154,8 +158,5 @@
154158

155159
<!-- We must find the BCL libraries using the runtime pack instead of using the built-in NativeAOT BCL -->
156160
<PublishAotUsingRuntimePack>true</PublishAotUsingRuntimePack>
157-
158-
<!-- This turns off some NativeAOT logic we don't want nor need -->
159-
<NativeCompilationDuringPublish>false</NativeCompilationDuringPublish>
160161
</PropertyGroup>
161162
</Project>

dotnet/targets/Xamarin.Shared.Sdk.targets

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -464,13 +464,36 @@
464464
<IlcCompileDependsOn>Compile;_ComputeLinkerArguments;_ComputeManagedAssemblyToLink;SetupOSSpecificProps;PrepareForILLink;_XamarinComputeIlcCompileInputs</IlcCompileDependsOn>
465465
</PropertyGroup>
466466

467+
<!--
468+
Workaround for SDK issue where setting PublishAot=true during build cannot resolve correct
469+
runtime pack and IL compiler pack.
470+
471+
Setting PublishAotUsingRuntimePack=true unconditionally results in the runtime pack label to
472+
be updated to "NativeAOT" instead of "Mono" and trying to build against NativeAOT runtime
473+
pack instead of the Mono one.
474+
475+
Setting PublishAotUsingRuntimePack=false causes the NuGet resolution to check for known
476+
ILCompiler packs and these don't exist for iOS-like platforms.
477+
478+
The workaround ensure that PublishAotUsingRuntimePack is false when SDK updates the runtime
479+
pack labels, and thus the "Mono" label is used. We then set it to true right before
480+
ProcessFrameworkReferences target to skip downloading the target ILCompiler pack.
481+
-->
482+
<Target Name="_WorkaroundAotRuntimePackResolution" BeforeTargets="ProcessFrameworkReferences" Condition="'$(PublishAot)' == 'true' And '$(_UseNativeAot)' != 'true'">
483+
<PropertyGroup>
484+
<PublishAotUsingRuntimePack>true</PublishAotUsingRuntimePack>
485+
</PropertyGroup>
486+
</Target>
487+
467488
<Target Name="_ComputeLinkerFeatures">
489+
<PropertyGroup Condition="'$(PublishAot)' == 'true'">
490+
<!-- Yep, we want to run ILLink as well, because we need our custom steps to run (NativeAOT sets this to false, so set it back to true) -->
491+
<RunILLink>true</RunILLink>
492+
</PropertyGroup>
493+
468494
<PropertyGroup Condition="'$(_UseNativeAot)' == 'true'">
469495
<!-- The one and only registrar is 'managed-static' when using NativeAOT -->
470496
<Registrar Condition="'$(Registrar)' == ''">managed-static</Registrar>
471-
472-
<!-- Yep, we want to run ILLink as well, because we need our custom steps to run (NativeAOT sets this to false, so set it back to true) -->
473-
<RunILLink>true</RunILLink>
474497
</PropertyGroup>
475498

476499
<PropertyGroup>

tests/dotnet/UnitTests/ProjectTest.cs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1345,6 +1345,23 @@ public void BuildAndExecuteAppWithWinExeOutputType (ApplePlatform platform, stri
13451345
Assert.AreEqual ($"WinExe is not a valid output type for macOS", errors [0].Message, "Error message");
13461346
}
13471347

1348+
[Test]
1349+
[TestCase (ApplePlatform.iOS, "iossimulator-x64")]
1350+
[TestCase (ApplePlatform.MacOSX, "osx-arm64")]
1351+
[TestCase (ApplePlatform.MacCatalyst, "maccatalyst-x64")]
1352+
public void PublishAotDuringBuild (ApplePlatform platform, string runtimeIdentifiers)
1353+
{
1354+
var project = "MySimpleApp";
1355+
Configuration.IgnoreIfIgnoredPlatform (platform);
1356+
Configuration.AssertRuntimeIdentifiersAvailable (platform, runtimeIdentifiers);
1357+
1358+
var project_path = GetProjectPath (project, runtimeIdentifiers: runtimeIdentifiers, platform: platform, out var appPath);
1359+
Clean (project_path);
1360+
var properties = GetDefaultProperties (runtimeIdentifiers);
1361+
properties ["PublishAot"] = "true";
1362+
DotNet.AssertBuild (project_path, properties);
1363+
}
1364+
13481365
void AssertThatDylibExistsAndIsReidentified (string appPath, string dylibRelPath)
13491366
{
13501367
var dylibPath = Path.Join (appPath, "Contents", "MonoBundle", dylibRelPath);

0 commit comments

Comments
 (0)