Skip to content

Commit 255faba

Browse files
[WIP] rework .NET 6 AOT support
This mainly addresses project names like `foo Ümläüts`. I committed a locally built `MonoAOTCompiler.dll` with changes.
1 parent 513f613 commit 255faba

10 files changed

Lines changed: 108 additions & 76 deletions

File tree

build-tools/create-packs/Microsoft.Android.Sdk.proj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@ core workload SDK packs imported by WorkloadManifest.targets.
6767
<!-- Microsoft.Android.Sdk.ILLink output -->
6868
<_PackageFiles Include="$(XAInstallPrefix)xbuild\Xamarin\Android\Microsoft.Android.Sdk.ILLink.dll" PackagePath="tools" />
6969
<_PackageFiles Include="$(XAInstallPrefix)xbuild\Xamarin\Android\Microsoft.Android.Sdk.ILLink.pdb" PackagePath="tools" />
70+
<!--TODO: Remove this -->
71+
<_PackageFiles Include="$(XAInstallPrefix)xbuild\Xamarin\Android\MonoAOTCompiler.dll" PackagePath="tools" />
7072
<_PackageFiles Include="$(XAInstallPrefix)xbuild\Xamarin\Android\%(_LocalizationLanguages.Identity)\Microsoft.Android.Sdk.ILLink.resources.dll" PackagePath="tools\%(_LocalizationLanguages.Identity)" />
7173
<_PackageFiles Include="$(ToolsSourceDir)**" PackagePath="tools" />
7274
<_PackageFiles Include="$(NetCoreAppToolsSourceDir)generator.dll" PackagePath="tools" />

src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.Aot.targets

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,21 @@ They run in a context of an inner build with a single $(RuntimeIdentifier).
2323
https://github.com/dotnet/runtime/blob/69711860262e44458bbe276393ea3eb9f7a2192a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/WorkloadManifest.targets.in#L20-L25
2424
-->
2525
<ImportGroup Condition=" '$(MonoAOTCompilerTasksAssemblyPath)' == '' and '$(AotAssemblies)' == 'true' ">
26-
<Import Project="Sdk.props" Sdk="Microsoft.NET.Runtime.MonoAOTCompiler.Task" />
26+
<!--TODO: Put this back -->
27+
<!-- <Import Project="Sdk.props" Sdk="Microsoft.NET.Runtime.MonoAOTCompiler.Task" /> -->
2728
<Import Project="Sdk.props" Sdk="Microsoft.NETCore.App.Runtime.AOT.Cross.android-x86" />
2829
<Import Project="Sdk.props" Sdk="Microsoft.NETCore.App.Runtime.AOT.Cross.android-x64" />
2930
<Import Project="Sdk.props" Sdk="Microsoft.NETCore.App.Runtime.AOT.Cross.android-arm" />
3031
<Import Project="Sdk.props" Sdk="Microsoft.NETCore.App.Runtime.AOT.Cross.android-arm64" />
3132
</ImportGroup>
3233

34+
<!--TODO: Remove this -->
35+
<PropertyGroup>
36+
<MonoAOTCompilerTasksAssemblyPath>$(MSBuildThisFileDirectory)..\tools\MonoAOTCompiler.dll</MonoAOTCompilerTasksAssemblyPath>
37+
</PropertyGroup>
38+
<UsingTask TaskName="MonoAOTCompiler" AssemblyFile="$(MonoAOTCompilerTasksAssemblyPath)" />
39+
<!--TODO: End removal -->
40+
3341
<UsingTask TaskName="Xamarin.Android.Tasks.GetAotAssemblies" AssemblyFile="$(_XamarinAndroidBuildTasksAssembly)" />
3442

3543
<Target Name="_AndroidAotInputs">
@@ -53,14 +61,17 @@ They run in a context of an inner build with a single $(RuntimeIdentifier).
5361
AndroidApiLevel="$(_AndroidApiLevel)"
5462
MinimumSupportedApiLevel="$(AndroidMinimumSupportedApiLevel)"
5563
AndroidSequencePointsMode="$(_SequencePointsMode)"
56-
AotAdditionalArguments="$(AndroidAotAdditionalArguments)"
5764
TargetName="$(TargetName)"
5865
ResolvedAssemblies="@(_AndroidAotInputs)"
5966
AotOutputDirectory="$(_AndroidAotBinDirectory)"
6067
RuntimeIdentifier="$(RuntimeIdentifier)"
6168
EnableLLVM="$(EnableLLVM)"
62-
UsingAndroidNETSdk="true"
6369
Profiles="@(AndroidAotProfile)">
70+
<Output PropertyName="_Triple" TaskParameter="Triple" />
71+
<Output PropertyName="_ToolPrefix" TaskParameter="ToolPrefix" />
72+
<Output PropertyName="_MsymPath" TaskParameter="MsymPath" />
73+
<Output PropertyName="_LdName" TaskParameter="LdName" />
74+
<Output PropertyName="_LdFlags" TaskParameter="LdFlags" />
6475
<Output ItemName="_MonoAOTAssemblies" TaskParameter="ResolvedAssemblies" />
6576
</GetAotAssemblies>
6677
<PropertyGroup>
@@ -69,7 +80,10 @@ They run in a context of an inner build with a single $(RuntimeIdentifier).
6980
</PropertyGroup>
7081
<MakeDir Directories="$(IntermediateOutputPath)aot\" />
7182
<MonoAOTCompiler
72-
Assemblies="@(_MonoAOTAssemblies->'%(FullPath)')"
83+
Triple="$(_Triple)"
84+
ToolPrefix="$(_ToolPrefix)"
85+
MsymPath="$(_MsymPath)"
86+
Assemblies="@(_MonoAOTAssemblies)"
7387
CompilerBinaryPath="$(_MonoAOTCompilerPath)"
7488
DisableParallelAot="$(_DisableParallelAot)"
7589
IntermediateOutputPath="$(IntermediateOutputPath)"
@@ -79,7 +93,11 @@ They run in a context of an inner build with a single $(RuntimeIdentifier).
7993
OutputType="Library"
8094
UseAotDataFile="false"
8195
UseLLVM="$(EnableLLVM)"
82-
LLVMPath="$(_LLVMPath)">
96+
LLVMPath="$(_LLVMPath)"
97+
LdName="$(_LdName)"
98+
LdFlags="$(_LdFlags)"
99+
WorkingDirectory="$(MSBuildProjectDirectory)"
100+
AotArguments="$(AndroidAotAdditionalArguments)">
83101
<Output TaskParameter="CompiledAssemblies" ItemName="_AotCompiledAssemblies" />
84102
<Output TaskParameter="FileWrites" ItemName="FileWrites" />
85103
</MonoAOTCompiler>
41 KB
Binary file not shown.

src/Xamarin.Android.Build.Tasks/Tasks/Aot.cs

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ public class Aot : GetAotArguments
4545

4646
public string ExtraAotOptions { get; set; }
4747

48+
public string AotAdditionalArguments { get; set; }
49+
4850
[Output]
4951
public string[] NativeLibrariesReferences { get; set; }
5052

@@ -137,11 +139,24 @@ IEnumerable<Config> GetAotConfigs (NdkTools ndk)
137139
string tempDir = Path.Combine (outdir, Path.GetFileName (assembly.ItemSpec));
138140
Directory.CreateDirectory (tempDir);
139141

140-
var aotOptions = GetAotOptions (ndk, arch, level, outdir, mtriple, toolPrefix);
142+
GetAotOptions (ndk, arch, level, outdir, toolPrefix);
141143
// NOTE: ordering seems to matter on Windows
142-
aotOptions.Insert (0, $"outfile={outputFile}");
143-
aotOptions.Insert (0, $"llvm-path={SdkBinDirectory}");
144-
aotOptions.Insert (0, $"temp-path={tempDir}");
144+
var aotOptions = new List<string> ();
145+
aotOptions.Add ("asmwriter");
146+
aotOptions.Add ($"mtriple={mtriple}");
147+
aotOptions.Add ($"tool-prefix={toolPrefix}");
148+
aotOptions.Add ($"outfile={outputFile}");
149+
aotOptions.Add ($"llvm-path={SdkBinDirectory}");
150+
aotOptions.Add ($"temp-path={tempDir}");
151+
if (!string.IsNullOrEmpty (AotAdditionalArguments)) {
152+
aotOptions.Add (AotAdditionalArguments);
153+
}
154+
if (!string.IsNullOrEmpty (LdName)) {
155+
aotOptions.Add ($"ld-name={LdName}");
156+
}
157+
if (!string.IsNullOrEmpty (LdFlags)) {
158+
aotOptions.Add ($"ld-flags={LdFlags}");
159+
}
145160
if (Profiles != null && Profiles.Length > 0) {
146161
if (Path.GetFileNameWithoutExtension (assembly.ItemSpec) == TargetName) {
147162
LogDebugMessage ($"Not using profile(s) for main assembly: {assembly.ItemSpec}");

src/Xamarin.Android.Build.Tasks/Tasks/GetAotArguments.cs

Lines changed: 21 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -51,13 +51,24 @@ public abstract class GetAotArguments : AndroidAsyncTask
5151

5252
public ITaskItem [] Profiles { get; set; } = Array.Empty<ITaskItem> ();
5353

54-
public bool UsingAndroidNETSdk { get; set; }
55-
56-
public string AotAdditionalArguments { get; set; } = "";
57-
5854
[Required, Output]
5955
public ITaskItem [] ResolvedAssemblies { get; set; } = Array.Empty<ITaskItem> ();
6056

57+
[Output]
58+
public string? Triple { get; set; }
59+
60+
[Output]
61+
public string? ToolPrefix { get; set; }
62+
63+
[Output]
64+
public string? MsymPath { get; set; }
65+
66+
[Output]
67+
public string? LdName { get; set; }
68+
69+
[Output]
70+
public string? LdFlags { get; set; }
71+
6172
protected AotMode AotMode;
6273
protected SequencePointsMode SequencePointsMode;
6374
protected string SdkBinDirectory = "";
@@ -208,22 +219,12 @@ int GetNdkApiLevel (NdkTools ndk, AndroidTargetArch arch)
208219
}
209220

210221
/// <summary>
211-
/// Returns a list of parameters to pass to the --aot switch
222+
/// Fills [Output] parameters to pass to the --aot switch
212223
/// </summary>
213-
protected List<string> GetAotOptions (NdkTools ndk, AndroidTargetArch arch, int level, string outdir, string mtriple, string toolPrefix)
224+
protected void GetAotOptions (NdkTools ndk, AndroidTargetArch arch, int level, string outdir, string toolPrefix)
214225
{
215-
List<string> aotOptions = new List<string> ();
216-
217-
if (!string.IsNullOrEmpty (AotAdditionalArguments))
218-
aotOptions.Add (AotAdditionalArguments);
219226
if (SequencePointsMode == SequencePointsMode.Offline)
220-
aotOptions.Add ($"msym-dir={outdir}");
221-
if (AotMode != AotMode.Normal)
222-
aotOptions.Add (AotMode.ToString ().ToLowerInvariant ());
223-
224-
aotOptions.Add ("asmwriter");
225-
aotOptions.Add ($"mtriple={mtriple}");
226-
aotOptions.Add ($"tool-prefix={toolPrefix}");
227+
MsymPath = outdir;
227228

228229
string ldName;
229230
if (EnableLLVM) {
@@ -238,16 +239,12 @@ protected List<string> GetAotOptions (NdkTools ndk, AndroidTargetArch arch, int
238239
ldName = "ld";
239240
}
240241
string ldFlags = GetLdFlags (ndk, arch, level, toolPrefix);
241-
242-
// MUST be before `ld-flags`, otherwise Mono fails to parse it on Windows
243242
if (!string.IsNullOrEmpty (ldName)) {
244-
aotOptions.Add ($"ld-name={ldName}");
243+
LdName = ldName;
245244
}
246245
if (!string.IsNullOrEmpty (ldFlags)) {
247-
aotOptions.Add ($"ld-flags={ldFlags}");
246+
LdFlags = ldFlags;
248247
}
249-
250-
return aotOptions;
251248
}
252249

253250
string GetLdFlags(NdkTools ndk, AndroidTargetArch arch, int level, string toolPrefix)
@@ -292,13 +289,7 @@ string GetLdFlags(NdkTools ndk, AndroidTargetArch arch, int level, string toolPr
292289
libs.Add (Path.Combine (androidLibPath, "libc.so"));
293290
libs.Add (Path.Combine (androidLibPath, "libm.so"));
294291

295-
if (UsingAndroidNETSdk) {
296-
// NOTE: in .NET 6+ use space for the delimiter and escape spaces in paths
297-
var escaped = libs.Select (l => l.Replace (" ", "\\ "));
298-
ldFlags = string.Join (" ", escaped);
299-
} else {
300-
ldFlags = $"\\\"{string.Join ("\\\";\\\"", libs)}\\\"";
301-
}
292+
ldFlags = $"\\\"{string.Join ("\\\";\\\"", libs)}\\\"";
302293
}
303294
return ldFlags;
304295
}

src/Xamarin.Android.Build.Tasks/Tasks/GetAotAssemblies.cs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,10 @@ public override Task RunTaskAsync ()
4242
}
4343

4444
(_, string outdir, string mtriple, AndroidTargetArch arch) = GetAbiSettings (abi);
45-
string toolPrefix = GetToolPrefix (ndk, arch, out int level);
45+
Triple = mtriple;
46+
ToolPrefix = GetToolPrefix (ndk, arch, out int level);
4647

47-
var aotOptions = GetAotOptions (ndk, arch, level, outdir, mtriple, toolPrefix);
48+
GetAotOptions (ndk, arch, level, outdir, ToolPrefix);
4849

4950
var aotProfiles = new StringBuilder ();
5051
if (Profiles != null && Profiles.Length > 0) {
@@ -56,15 +57,16 @@ public override Task RunTaskAsync ()
5657
}
5758
}
5859

59-
var arguments = string.Join (",", aotOptions);
6060
foreach (var assembly in ResolvedAssemblies) {
61-
var temp = Path.GetFullPath (Path.Combine (outdir, Path.GetFileNameWithoutExtension (assembly.ItemSpec)));
61+
var temp = Path.Combine (outdir, Path.GetFileNameWithoutExtension (assembly.ItemSpec));
6262
Directory.CreateDirectory (temp);
6363
if (Path.GetFileNameWithoutExtension (assembly.ItemSpec) == TargetName) {
64-
LogDebugMessage ($"Not using profile(s) for main assembly: {assembly.ItemSpec}");
65-
assembly.SetMetadata ("AotArguments", $"{arguments},temp-path={temp}");
64+
if (Profiles != null && Profiles.Length > 0) {
65+
LogDebugMessage ($"Not using profile(s) for main assembly: {assembly.ItemSpec}");
66+
}
67+
assembly.SetMetadata ("AotArguments", $"asmwriter,temp-path={temp}");
6668
} else {
67-
assembly.SetMetadata ("AotArguments", $"{arguments},temp-path={temp}{aotProfiles}");
69+
assembly.SetMetadata ("AotArguments", $"asmwriter,temp-path={temp}{aotProfiles}");
6870
}
6971
}
7072

src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AotTests.cs

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,6 @@ public void BuildBasicApplicationReleaseProfiledAotWithoutDefaultProfile ()
169169

170170
[Test]
171171
[TestCaseSource (nameof (AotChecks))]
172-
[Category ("DotNetIgnore")] // Not currently working, see: https://github.com/dotnet/runtime/issues/56163
173172
public void BuildAotApplicationAndÜmläüts (string supportedAbis, bool enableLLVM, bool expectedResult, bool usesAssemblyBlobs)
174173
{
175174
var path = Path.Combine ("temp", string.Format ("BuildAotApplication AndÜmläüts_{0}_{1}_{2}_{3}", supportedAbis, enableLLVM, expectedResult, usesAssemblyBlobs));
@@ -218,12 +217,13 @@ public void BuildAotApplicationAndÜmläüts (string supportedAbis, bool enableL
218217
}
219218
}
220219
foreach (var abi in supportedAbis.Split (new char [] { ';' })) {
221-
var libapp = Path.Combine (Root, b.ProjectDirectory, proj.IntermediateOutputPath,
222-
"bundles", abi, "libmonodroid_bundle_app.so");
223-
Assert.IsFalse (File.Exists (libapp), abi + " libmonodroid_bundle_app.so should not exist");
224-
var assemblies = Path.Combine (Root, b.ProjectDirectory, proj.IntermediateOutputPath,
225-
"aot", abi, "libaot-UnnamedProject.dll.so");
226-
Assert.IsTrue (File.Exists (assemblies), "{0} libaot-UnnamedProject.dll.so does not exist", abi);
220+
var intermediate = Path.Combine (Root, b.ProjectDirectory, proj.IntermediateOutputPath);
221+
var libapp = Path.Combine (intermediate, "bundles", abi, "libmonodroid_bundle_app.so");
222+
FileAssert.DoesNotExist (libapp);
223+
var aotNativeLibrary = Builder.UseDotNet ?
224+
Path.Combine (intermediate, AbiUtils.AbiToRuntimeIdentifier (abi), "aot", "UnnamedProject.dll.so") :
225+
Path.Combine (intermediate, "aot", abi, "libaot-UnnamedProject.dll.so");
226+
FileAssert.Exists (aotNativeLibrary);
227227
var apk = Path.Combine (Root, b.ProjectDirectory,
228228
proj.OutputPath, $"{proj.PackageName}-Signed.apk");
229229

@@ -248,7 +248,6 @@ public void BuildAotApplicationAndÜmläüts (string supportedAbis, bool enableL
248248
[Test]
249249
[TestCaseSource (nameof (AotChecks))]
250250
[Category ("Minor"), Category ("MkBundle")]
251-
[Category ("DotNetIgnore")] // Not currently working, see: https://github.com/dotnet/runtime/issues/56163
252251
public void BuildAotApplicationAndBundleAndÜmläüts (string supportedAbis, bool enableLLVM, bool expectedResult, bool usesAssemblyBlobs)
253252
{
254253
var path = Path.Combine ("temp", string.Format ("BuildAotApplicationAndBundle AndÜmläüts_{0}_{1}_{2}_{3}", supportedAbis, enableLLVM, expectedResult, usesAssemblyBlobs));
@@ -449,10 +448,6 @@ public static void Foo () {
449448
[Category ("LLVM")]
450449
public void NoSymbolsArgShouldReduceAppSize ([Values ("", "Hybrid")] string androidAotMode)
451450
{
452-
if (Builder.UseDotNet) {
453-
Assert.Ignore ("https://github.com/dotnet/runtime/issues/57800");
454-
}
455-
456451
AssertAotModeSupported (androidAotMode);
457452

458453
var proj = new XamarinAndroidApplicationProject () {
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
using System;
2+
3+
namespace Xamarin.ProjectTools
4+
{
5+
public static class AbiUtils
6+
{
7+
public static string AbiToRuntimeIdentifier (string androidAbi)
8+
{
9+
if (androidAbi == "armeabi-v7a") {
10+
return "android-arm";
11+
} else if (androidAbi == "arm64-v8a") {
12+
return "android-arm64";
13+
} else if (androidAbi == "x86") {
14+
return "android-x86";
15+
} else if (androidAbi == "x86_64") {
16+
return "android-x64";
17+
}
18+
throw new InvalidOperationException ($"Unknown abi: {androidAbi}");
19+
}
20+
}
21+
}

src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Utilities/ProjectExtensions.cs

Lines changed: 2 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -31,30 +31,14 @@ public static void SetAndroidSupportedAbis (this IShortFormProject project, stri
3131

3232
public static void SetRuntimeIdentifier (this IShortFormProject project, string androidAbi)
3333
{
34-
if (androidAbi == "armeabi-v7a") {
35-
project.SetProperty (KnownProperties.RuntimeIdentifier, "android-arm");
36-
} else if (androidAbi == "arm64-v8a") {
37-
project.SetProperty (KnownProperties.RuntimeIdentifier, "android-arm64");
38-
} else if (androidAbi == "x86") {
39-
project.SetProperty (KnownProperties.RuntimeIdentifier, "android-x86");
40-
} else if (androidAbi == "x86_64") {
41-
project.SetProperty (KnownProperties.RuntimeIdentifier, "android-x64");
42-
}
34+
project.SetProperty (KnownProperties.RuntimeIdentifier, AbiUtils.AbiToRuntimeIdentifier (androidAbi));
4335
}
4436

4537
public static void SetRuntimeIdentifiers (this IShortFormProject project, string [] androidAbis)
4638
{
4739
var abis = new List<string> ();
4840
foreach (var androidAbi in androidAbis) {
49-
if (androidAbi == "armeabi-v7a") {
50-
abis.Add ("android-arm");
51-
} else if (androidAbi == "arm64-v8a") {
52-
abis.Add ("android-arm64");
53-
} else if (androidAbi == "x86") {
54-
abis.Add ("android-x86");
55-
} else if (androidAbi == "x86_64") {
56-
abis.Add ("android-x64");
57-
}
41+
abis.Add (AbiUtils.AbiToRuntimeIdentifier (androidAbi));
5842
}
5943
project.SetProperty (KnownProperties.RuntimeIdentifiers, string.Join (";", abis));
6044
}

src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.csproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -371,6 +371,10 @@
371371
<None Include="startup-xf.aotprofile">
372372
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
373373
</None>
374+
<!--TODO: remove later -->
375+
<None Include="MonoAOTCompiler.dll">
376+
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
377+
</None>
374378
</ItemGroup>
375379

376380
<ItemGroup>

0 commit comments

Comments
 (0)