Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unable to use $(EnableLLVM) with Android AOT #56386

Closed
jonathanpeppers opened this issue Jul 27, 2021 · 3 comments
Closed

Unable to use $(EnableLLVM) with Android AOT #56386

jonathanpeppers opened this issue Jul 27, 2021 · 3 comments
Assignees
Milestone

Comments

@jonathanpeppers
Copy link
Member

jonathanpeppers commented Jul 27, 2021

Description

Context: xamarin/xamarin-android#5539

When using the new <MonoAOTCompiler/> task, it fails if you try to turn on $(EnableLLVM):

Microsoft.Android.Sdk.Aot.targets(65,5): Precompiling failed for C:\src\xamarin-android\bin\TestDebug\temp\NoSymbolsArgShouldReduceAppSize\obj\Release\android-arm64\linked\UnnamedProject.dll: '"C:\src\xamarin-android\bin\TestDebug\temp\SDK Ümläüts\ndk\toolchains\llvm\prebuilt\windows-x86_64\bin\opt"' is not recognized as an internal or external command,
operable program or batch file.
AOT of image UnnamedProject.dll failed.
Mono Ahead of Time compiler - compiling assembly C:\src\xamarin-android\bin\TestDebug\temp\NoSymbolsArgShouldReduceAppSize\obj\Release\android-arm64\linked\UnnamedProject.dll
AOTID 20266A52-3AA1-1A98-06EF-28AD91144013
Executing opt: "C:\src\xamarin-android\bin\TestDebug\temp\SDK Ümläüts\ndk\toolchains\llvm\prebuilt\windows-x86_64\bin\opt" -f -O2 -disable-tail-calls -place-safepoints -spp-all-backedges -o "mono_aot_a17176\temp.opt.bc" "mono_aot_a17176\temp.bc"

I also get a build warning about opt.exe:

Microsoft.Android.Sdk.Aot.targets(65,5): [UnnamedProject.dll] '"C:\src\xamarin-android\bin\TestDebug\temp\SDK Ümläüts\ndk\toolchains\llvm\prebuilt\windows-x86_64\bin\opt"' is not recognized as an internal or external command,

opt.exe seems to be present in the AOT pack, why is it using LLVMPath to look for opt?

image

The value passed in for LLVMPath, seems to be correct:

image

But opt isn't located here, it is in the Mono AOT pack.

Note the folder used here (odd characters) is on purpose for testing, so this might be also be related: #56163.

I might be doing something wrong. Let me know, thanks!

Configuration

dotnet --version
6.0.100-rc.1.21376.3

Regression?

No, AOT on Android is new.

Other information

Build log: msbuild.zip

/cc @steveisok @akoeplinger

@dotnet-issue-labeler dotnet-issue-labeler bot added area-Infrastructure-mono untriaged New issue has not been triaged by the area owner labels Jul 27, 2021
@ghost
Copy link

ghost commented Jul 27, 2021

Tagging subscribers to this area: @directhex
See info in area-owners.md if you want to be subscribed.

Issue Details

Description

Context: xamarin/xamarin-android#5539

When using the new <MonoAOTCompiler/> task, it fails if you try to turn on $(EnableLLVM):

Microsoft.Android.Sdk.Aot.targets(65,5): Precompiling failed for C:\src\xamarin-android\bin\TestDebug\temp\NoSymbolsArgShouldReduceAppSize\obj\Release\android-arm64\linked\UnnamedProject.dll: '"C:\src\xamarin-android\bin\TestDebug\temp\SDK Ümläüts\ndk\toolchains\llvm\prebuilt\windows-x86_64\bin\opt"' is not recognized as an internal or external command,
operable program or batch file.
AOT of image UnnamedProject.dll failed.
Mono Ahead of Time compiler - compiling assembly C:\src\xamarin-android\bin\TestDebug\temp\NoSymbolsArgShouldReduceAppSize\obj\Release\android-arm64\linked\UnnamedProject.dll
AOTID 20266A52-3AA1-1A98-06EF-28AD91144013
Executing opt: "C:\src\xamarin-android\bin\TestDebug\temp\SDK Ümläüts\ndk\toolchains\llvm\prebuilt\windows-x86_64\bin\opt" -f -O2 -disable-tail-calls -place-safepoints -spp-all-backedges -o "mono_aot_a17176\temp.opt.bc" "mono_aot_a17176\temp.bc"

I also get a build warning about opt.exe:

Microsoft.Android.Sdk.Aot.targets(65,5): [UnnamedProject.dll] '"C:\src\xamarin-android\bin\TestDebug\temp\SDK Ümläüts\ndk\toolchains\llvm\prebuilt\windows-x86_64\bin\opt"' is not recognized as an internal or external command,

opt.exe seems to be present in the AOT pack, why is it using LLVMPath to look for opt?

image

The value passed in for LLVMPath, seems to be correct:

image

But opt isn't located here, it is in the Mono AOT pack.

Note the folder used here (odd characters) is on purpose for testing, so this might be also be related: #56163.

Configuration

dotnet --version
6.0.100-rc.1.21376.3

Regression?

No, AOT on Android is new.

Other information

Build log: msbuild.zip

/cc @steveisok @akoeplinger

Author: jonathanpeppers
Assignees: -
Labels:

area-Infrastructure-mono, untriaged

Milestone: -

@ghost ghost added this to Untriaged in Infrastructure Backlog Jul 27, 2021
@steveisok steveisok removed the untriaged New issue has not been triaged by the area owner label Jul 27, 2021
jonathanpeppers added a commit to xamarin/xamarin-android that referenced this issue Jul 27, 2021
Fixes: #6052

Helpful reading:

* https://github.com/dotnet/runtime/blob/15dec9a2aa5a4236d6ba70de2e9c146867b9d2e0/src/tasks/AotCompilerTask/MonoAOTCompiler.cs
* https://github.com/dotnet/runtime/blob/15dec9a2aa5a4236d6ba70de2e9c146867b9d2e0/src/mono/netcore/nuget/Microsoft.NET.Runtime.MonoAOTCompiler.Task/README.md

To make this work, I moved the existing `<Aot/>` MSBuild task calls to
a new `_AndroidAot` MSBuild target in `Xamarin.Android.Legacy.targets`.

In the .NET 6 targets, there is a *different* `_AndroidAot` MSBuild
target that runs the new `<MonoAOTCompiler/>` MSBuild task. The
`_AndroidAot` target runs per `$(RuntimeIdentifier)` after the linker
completes. Native libraries are added to the
`@(ResolvedFileToPublish)` item group to be included in the final
`.apk`.

To follow convention with Blazor WASM:

https://devblogs.microsoft.com/aspnet/asp-net-core-updates-in-net-6-preview-4/#blazor-webassembly-ahead-of-time-aot-compilation

The `$(RunAOTCompilation)` MSBuild property enables AOT. To help with
backwards compatibility with "legacy" Xamarin.Android, I kept the
`$(AotAssemblies)` MSBuild property intact.

Unfortunately, we have to manually import things to support
`$(AotAssemblies)`:

    <ImportGroup Condition=" '$(MonoAOTCompilerTasksAssemblyPath)' == '' and '$(AotAssemblies)' == 'true' ">
      <Import Project="Sdk.props" Sdk="Microsoft.NET.Runtime.MonoAOTCompiler.Task" />
      <Import Project="Sdk.props" Sdk="Microsoft.NETCore.App.Runtime.AOT.Cross.android-x86" />
      <Import Project="Sdk.props" Sdk="Microsoft.NETCore.App.Runtime.AOT.Cross.android-x64" />
      <Import Project="Sdk.props" Sdk="Microsoft.NETCore.App.Runtime.AOT.Cross.android-arm" />
      <Import Project="Sdk.props" Sdk="Microsoft.NETCore.App.Runtime.AOT.Cross.android-arm64" />
    </ImportGroup>

Since, the default Mono workload does not support `$(AotAssemblies)`:

https://github.com/dotnet/runtime/blob/69711860262e44458bbe276393ea3eb9f7a2192a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/WorkloadManifest.targets.in#L20-L25

I think this is reasonable for now.

~~ Limitations ~~

* Profiled AOT is not implemented yet:

#6053

* `$(EnableLLVM)` fails when locating `opt`:

dotnet/runtime#56386

* `AndroidClientHandler` usage causes runtime crash:

dotnet/runtime#56315

* Use of folder names like `Build AndÜmläüts` fails:

dotnet/runtime#56163

~~ Results ~~

All tests were running on a Pixel 5.

Using the HelloAndroid app:

https://github.com/dotnet/maui-samples/tree/main/HelloAndroid

Defaults to two architectures: arm64 and x86

Average of 10 runs with `-c Release` and no AOT:

    Activity: Displayed     00:00:00.308

Apk size: 8367969

Average of 10 runs with `-c Release -p:RunAOTCompilation=true`:

    Activity: Displayed     00:00:00.209

Apk size: 12082123

Using the HelloMaui app:

https://github.com/dotnet/maui-samples/tree/main/HelloMaui

Defaults to two architectures: arm64 and x86

Average of 10 runs with `-c Release` and no AOT:

    Activity: Displayed     00:00:01.117

Apk size: 16272964

Average of 10 runs with `-c Release -p:RunAOTCompilation=true`:

    Activity: Displayed     00:00:00.568

Apk size: 42869016
jonpryor pushed a commit to xamarin/xamarin-android that referenced this issue Jul 28, 2021
Fixes: #6052

Helpful reading:

  * https://github.com/dotnet/runtime/blob/15dec9a2aa5a4236d6ba70de2e9c146867b9d2e0/src/tasks/AotCompilerTask/MonoAOTCompiler.cs
  * https://github.com/dotnet/runtime/blob/15dec9a2aa5a4236d6ba70de2e9c146867b9d2e0/src/mono/netcore/nuget/Microsoft.NET.Runtime.MonoAOTCompiler.Task/README.md

To make this work, I moved the existing `<Aot/>` MSBuild task calls to
a new `_AndroidAot` MSBuild target in `Xamarin.Android.Legacy.targets`.

In the .NET 6 targets, there is a *different* `_AndroidAot` MSBuild
target that runs the new `<MonoAOTCompiler/>` MSBuild task. The
`_AndroidAot` target runs once per `$(RuntimeIdentifier)`, after the
linker completes.

Native libraries are added to the `@(ResolvedFileToPublish)` item
group to be included in the final `.apk`.

To follow [convention with Blazor WASM][0], the `$(RunAOTCompilation)`
MSBuild property enables AOT.

To help with backwards compatibility with "legacy" Xamarin.Android, I
kept the `$(AotAssemblies)` MSBuild property intact.

Unfortunately, we have to manually import things to support
`$(AotAssemblies)`:

	<ImportGroup Condition=" '$(MonoAOTCompilerTasksAssemblyPath)' == '' and '$(AotAssemblies)' == 'true' ">
	  <Import Project="Sdk.props" Sdk="Microsoft.NET.Runtime.MonoAOTCompiler.Task" />
	  <Import Project="Sdk.props" Sdk="Microsoft.NETCore.App.Runtime.AOT.Cross.android-x86" />
	  <Import Project="Sdk.props" Sdk="Microsoft.NETCore.App.Runtime.AOT.Cross.android-x64" />
	  <Import Project="Sdk.props" Sdk="Microsoft.NETCore.App.Runtime.AOT.Cross.android-arm" />
	  <Import Project="Sdk.props" Sdk="Microsoft.NETCore.App.Runtime.AOT.Cross.android-arm64" />
	</ImportGroup>

as the [default Mono workload does not support `$(AotAssemblies)`][1].
I think this is reasonable for now.


~~ Limitations ~~

Profiled AOT is not implemented yet:

  * #6053

`$(EnableLLVM)` fails when locating `opt`:

  * dotnet/runtime#56386

`$(AndroidClientHandler)` usage causes runtime crash:

  * dotnet/runtime#56315

Use of folder names like `Build AndÜmläüts` fails:

  * dotnet/runtime#56163


~~ Results ~~

All tests:

 1. Were running on a [Google Pixel 5][2], and
 2. Enabled two architectures, arm64 and x86, and
 3. **JIT time** was average of 10 runs with `-c Release`, with the
    `Activity: Displayed` time, and
 4. **AOT time** was average of 10 runs with
    `-c Release -p:RunAOTCompilation=true` with the
    `Activity: Displayed` time.
 5. Δ values are (AOT / JIT)*100.

| Test                |      JIT time |      AOT time |  Δ time |  JIT apk size |  AOT apk size | Δ size |
| ------------------- | ------------: | ------------: | ------: | ------------: | ------------: | -----: |
| [HelloAndroid][3]   |  00:00:00.308 |  00:00:00.209 |     68% |     8,367,969 |    12,082,123 | 144.4% |
| [HelloMaui][4]      |  00:00:01.117 |  00:00:00.568 |     51% |    16,272,964 |    42,869,016 | 263.4% |

[0]: https://devblogs.microsoft.com/aspnet/asp-net-core-updates-in-net-6-preview-4/#blazor-webassembly-ahead-of-time-aot-compilation
[1]: https://github.com/dotnet/runtime/blob/69711860262e44458bbe276393ea3eb9f7a2192a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/WorkloadManifest.targets.in#L20-L25
[2]: https://store.google.com/us/product/pixel_5_specs?hl=en-US
[3]: https://github.com/dotnet/maui-samples/tree/714460431541f40570e91225e8ba4bc1fe08025f/HelloAndroid
[4]: https://github.com/dotnet/maui-samples/tree/714460431541f40570e91225e8ba4bc1fe08025f/HelloMaui
jonpryor pushed a commit to xamarin/xamarin-android that referenced this issue Jul 28, 2021
Fixes: #6052

Helpful reading:

  * https://github.com/dotnet/runtime/blob/15dec9a2aa5a4236d6ba70de2e9c146867b9d2e0/src/tasks/AotCompilerTask/MonoAOTCompiler.cs
  * https://github.com/dotnet/runtime/blob/15dec9a2aa5a4236d6ba70de2e9c146867b9d2e0/src/mono/netcore/nuget/Microsoft.NET.Runtime.MonoAOTCompiler.Task/README.md

To make this work, I moved the existing `<Aot/>` MSBuild task calls to
a new `_AndroidAot` MSBuild target in `Xamarin.Android.Legacy.targets`.

In the .NET 6 targets, there is a *different* `_AndroidAot` MSBuild
target that runs the new `<MonoAOTCompiler/>` MSBuild task. The
`_AndroidAot` target runs once per `$(RuntimeIdentifier)`, after the
linker completes.

Native libraries are added to the `@(ResolvedFileToPublish)` item
group to be included in the final `.apk`.

To follow [convention with Blazor WASM][0], the `$(RunAOTCompilation)`
MSBuild property enables AOT.

To help with backwards compatibility with "legacy" Xamarin.Android, I
kept the `$(AotAssemblies)` MSBuild property intact.

Unfortunately, we have to manually import things to support
`$(AotAssemblies)`:

	<ImportGroup Condition=" '$(MonoAOTCompilerTasksAssemblyPath)' == '' and '$(AotAssemblies)' == 'true' ">
	  <Import Project="Sdk.props" Sdk="Microsoft.NET.Runtime.MonoAOTCompiler.Task" />
	  <Import Project="Sdk.props" Sdk="Microsoft.NETCore.App.Runtime.AOT.Cross.android-x86" />
	  <Import Project="Sdk.props" Sdk="Microsoft.NETCore.App.Runtime.AOT.Cross.android-x64" />
	  <Import Project="Sdk.props" Sdk="Microsoft.NETCore.App.Runtime.AOT.Cross.android-arm" />
	  <Import Project="Sdk.props" Sdk="Microsoft.NETCore.App.Runtime.AOT.Cross.android-arm64" />
	</ImportGroup>

as the [default Mono workload does not support `$(AotAssemblies)`][1].
I think this is reasonable for now.


~~ Limitations ~~

Profiled AOT is not implemented yet:

  * #6053

`$(EnableLLVM)` fails when locating `opt`:

  * dotnet/runtime#56386

`$(AndroidClientHandler)` usage causes runtime crash:

  * dotnet/runtime#56315

Use of folder names like `Build AndÜmläüts` fails:

  * dotnet/runtime#56163


~~ Results ~~

All tests:

 1. Were running on a [Google Pixel 5][2], and
 2. Enabled two architectures, arm64 and x86, and
 3. **JIT time** was average of 10 runs with `-c Release`, with the
    `Activity: Displayed` time, and
 4. **AOT time** was average of 10 runs with
    `-c Release -p:RunAOTCompilation=true` with the
    `Activity: Displayed` time.
 5. Δ values are (AOT / JIT)*100.

| Test                |      JIT time |      AOT time |  Δ time |  JIT apk size |  AOT apk size | Δ size |
| ------------------- | ------------: | ------------: | ------: | ------------: | ------------: | -----: |
| [HelloAndroid][3]   |  00:00:00.308 |  00:00:00.209 |     68% |     8,367,969 |    12,082,123 | 144.4% |
| [HelloMaui][4]      |  00:00:01.117 |  00:00:00.568 |     51% |    16,272,964 |    42,869,016 | 263.4% |

[0]: https://devblogs.microsoft.com/aspnet/asp-net-core-updates-in-net-6-preview-4/#blazor-webassembly-ahead-of-time-aot-compilation
[1]: https://github.com/dotnet/runtime/blob/69711860262e44458bbe276393ea3eb9f7a2192a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/WorkloadManifest.targets.in#L20-L25
[2]: https://store.google.com/us/product/pixel_5_specs?hl=en-US
[3]: https://github.com/dotnet/maui-samples/tree/714460431541f40570e91225e8ba4bc1fe08025f/HelloAndroid
[4]: https://github.com/dotnet/maui-samples/tree/714460431541f40570e91225e8ba4bc1fe08025f/HelloMaui
@ViktorHofer ViktorHofer moved this from Untriaged to 6.0.0 in Infrastructure Backlog Jul 28, 2021
@ViktorHofer ViktorHofer added this to the 6.0.0 milestone Jul 28, 2021
@steveisok
Copy link
Member

@jonathanpeppers Unsure if this is right, but you should try pointing at opt / llc in the cross runtime pack of the current architecture.

@jonathanpeppers
Copy link
Member Author

The original problem here was usage of the <MonoAOTCompiler/> MSBuild task.

I believe I have this working now with the changes here: xamarin/xamarin-android#6157

There may be other problems here, but I will file a new issue.

Infrastructure Backlog automation moved this from 6.0.0 to Done Aug 2, 2021
@ghost ghost locked as resolved and limited conversation to collaborators Sep 1, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

4 participants