-
Notifications
You must be signed in to change notification settings - Fork 4.9k
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
.NET 6 Android AOT fails on certain folder names #56163
Comments
I couldn't figure out the best area label to add to this issue. If you have write-permissions please help me learn by adding exactly one area label. |
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
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
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
@steveisok @vargaz - any update ? |
Can someone who is on windows look at this ? |
I think we've seen some other strange failures with encoding of filenames on windows in the build. |
I know about this one #52108. It is happening during runtime though. |
Removing the area-Codegen-AOT-mono label. |
Tagging subscribers to 'arch-android': @steveisok, @akoeplinger Issue DetailsDescriptionCreate a Build with
A screenshot of the Logs: msbuild.zip Configuration
I believe this would also happen in Preview 7. Regression?No, Android AOT is a new feature.
|
@lewing @steveisok - this is something we can discuss on Monday, not too certain if this is a release blocking or a 7.0 issue at the moment. |
I think this is something we should try to fix for 6.0. This isn't exclusive to Android, right? |
I'm pretty sure this is the AOT compiler assuming something that isn't always true about the character encoding of the filesystem on windows so I doubt this is android specific. |
@jonathanpeppers what locale is your system using? |
I'm using I saw it fail on CI as well as locally. I think we have this test because usernames could commonly have special characters, and VS puts new projects in |
So this used to work in xamarin.android on windows ? |
Yes, these tests still pass for legacy Xamarin.Android on Windows. We setup a symbolic link named Neither were working with .NET 6 yet. |
I am able to reproduce it with our samples. Building the bench sample in
|
Fix dotnet#56163 The getcwd call is returning the string encoded in system character encoding instead of utf-8. Use native GetCurrentDirectoryW call instead and convert to utf-8.
The non-utf8 path is being created in the I didn't checked the legacy xamarin.android on windows. IIRC it was built with mingw though, so that might have different |
Fix #56163 The getcwd call is returning the string encoded in system character encoding instead of utf-8. Use native GetCurrentDirectoryW call instead and convert to utf-8.
Fix #56163 The getcwd call is returning the string encoded in system character encoding instead of utf-8. Use native GetCurrentDirectoryW call instead and convert to utf-8.
Fixes: dotnet#56163 PR dotnet#58523 fixed something on Windows, but it didn't actually address our issues on Android. A directory name like `foo Ümläüts` fails: * `mkdir 'foo Ümläüts' ; cd 'foo Ümläüts'` * `dotnet new android` * `dotnet build -c Release -p:RunAOTCompilation=true` (adding `-p:EnableLLVM=true` complicates further) The error: Precompiling failed for C:\src\foo Ümläüts\obj\Release\android-arm64\linked\System.Private.CoreLib.dll: Error: Loaded assembly 'C:\src\foo ├£ml├ñ├╝ts\obj\Release\android-arm64\linked\System.Private.CoreLib.dll' doesn't match original file name 'C:\foo ▄mlΣⁿts\obj\Release\android-arm64\linked\System.Private.CoreLib.dll'. Set MONO_PATH to the assembly's location. Reviewing the existing AOT implementation in Xamarin.Android, I found out *why* Xamarin.Android works: [AOT] response file obj\Release\120\aot\arm64-v8a\App36.dll\response.txt: --llvm "--aot=temp-path=obj\Release\120\aot\arm64-v8a\App36.dll,llvm-path=C:\Program Files\Microsoft Visual Studio\2022\Preview\MSBuild\Xamarin\Android,outfile=obj\Release\120\aot\arm64-v8a\libaot-App36.dll.so,msym-dir=obj\Release\120\aot\arm64-v8a,asmwriter,mtriple=aarch64-linux-android,tool-prefix=C:\Program Files (x86)\Android\android-sdk\ndk-bundle\toolchains\llvm\prebuilt\windows-x86_64\bin\aarch64-linux-android-,ld-name=ld.EXE,ld-flags=\"-LC:\Program Files (x86)\Android\android-sdk\ndk-bundle\toolchains\llvm\prebuilt\windows-x86_64\lib\gcc\aarch64-linux-android\4.9.x\";\"-LC:\Program Files (x86)\Android\android-sdk\ndk-bundle\platforms\android-21\arch-arm64\usr\lib\";\"C:\Program Files (x86)\Android\android-sdk\ndk-bundle\toolchains\llvm\prebuilt\windows-x86_64\lib\gcc\aarch64-linux-android\4.9.x\libgcc.a\";\"C:\Program Files (x86)\Android\android-sdk\ndk-bundle\platforms\android-21\arch-arm64\usr\lib\libc.so\";\"C:\Program Files (x86)\Android\android-sdk\ndk-bundle\platforms\android-21\arch-arm64\usr\lib\libm.so\"" C:\Users\jopepper\source\repos\App36\App36\obj\Release\120\android\assets\shrunk\App36.dll 1. Xamarin.Android passes *relative* paths. The `foo Ümläüts` directory name doesn't even come into play for some arguments. 2. With LLVM, `ld-flags` contains a `;`. The existing code splits on `;` and joins on `,`: https://github.com/dotnet/runtime/blob/25c207351c4f57cf2daa98caaf327a8b8d83edb8/src/tasks/AotCompilerTask/MonoAOTCompiler.cs#L505-L509 So we lose any `;` delimiters for the `ld-flags` value, they get replaced by `,`. I think the solution here is: 1. Add several missing properties to `<MonoAOTCompiler/>` so we don't have to rely on the `%(AotArguments)` item metadata. No splitting on `;` would be required, `ld-flags` can be passed in and used as-is. 2. Add a new `WorkingDirectory` property. When this is set, assume paths passed in might be relative -- and don't transform paths by calling `Path.GetFullPath()`. Lastly, I fixed a place where the UTF8 encoding wasn't passed when MSBuild logging the response file. These changes I tried to make in a way where this shouldn't break other .NET workloads like wasm. If existing MSBuild targets call this task (not using the new properties), the behavior should remain unchanged. I tested these changes by commiting a modified `MonoAOTCompiler.dll`: dotnet/android#6562 I'm able to enable several AOT tests related to dotnet#56163.
This isn't actually fixed in |
Fixes: #56163 PR #58523 fixed something on Windows, but it didn't actually address our issues on Android. A directory name like `foo Ümläüts` fails: * `mkdir 'foo Ümläüts' ; cd 'foo Ümläüts'` * `dotnet new android` * `dotnet build -c Release -p:RunAOTCompilation=true` (adding `-p:EnableLLVM=true` complicates further) The error: Precompiling failed for C:\src\foo Ümläüts\obj\Release\android-arm64\linked\System.Private.CoreLib.dll: Error: Loaded assembly 'C:\src\foo ├£ml├ñ├╝ts\obj\Release\android-arm64\linked\System.Private.CoreLib.dll' doesn't match original file name 'C:\foo ▄mlΣⁿts\obj\Release\android-arm64\linked\System.Private.CoreLib.dll'. Set MONO_PATH to the assembly's location. Reviewing the existing AOT implementation in Xamarin.Android, I found out *why* Xamarin.Android works: [AOT] response file obj\Release\120\aot\arm64-v8a\App36.dll\response.txt: --llvm "--aot=temp-path=obj\Release\120\aot\arm64-v8a\App36.dll,llvm-path=C:\Program Files\Microsoft Visual Studio\2022\Preview\MSBuild\Xamarin\Android,outfile=obj\Release\120\aot\arm64-v8a\libaot-App36.dll.so,msym-dir=obj\Release\120\aot\arm64-v8a,asmwriter,mtriple=aarch64-linux-android,tool-prefix=C:\Program Files (x86)\Android\android-sdk\ndk-bundle\toolchains\llvm\prebuilt\windows-x86_64\bin\aarch64-linux-android-,ld-name=ld.EXE,ld-flags=\"-LC:\Program Files (x86)\Android\android-sdk\ndk-bundle\toolchains\llvm\prebuilt\windows-x86_64\lib\gcc\aarch64-linux-android\4.9.x\";\"-LC:\Program Files (x86)\Android\android-sdk\ndk-bundle\platforms\android-21\arch-arm64\usr\lib\";\"C:\Program Files (x86)\Android\android-sdk\ndk-bundle\toolchains\llvm\prebuilt\windows-x86_64\lib\gcc\aarch64-linux-android\4.9.x\libgcc.a\";\"C:\Program Files (x86)\Android\android-sdk\ndk-bundle\platforms\android-21\arch-arm64\usr\lib\libc.so\";\"C:\Program Files (x86)\Android\android-sdk\ndk-bundle\platforms\android-21\arch-arm64\usr\lib\libm.so\"" C:\Users\jopepper\source\repos\App36\App36\obj\Release\120\android\assets\shrunk\App36.dll 1. Xamarin.Android passes *relative* paths. The `foo Ümläüts` directory name doesn't even come into play for some arguments. 2. With LLVM, `ld-flags` contains a `;`. The existing code splits on `;` and joins on `,`: https://github.com/dotnet/runtime/blob/25c207351c4f57cf2daa98caaf327a8b8d83edb8/src/tasks/AotCompilerTask/MonoAOTCompiler.cs#L505-L509 So we lose any `;` delimiters for the `ld-flags` value, they get replaced by `,`. I think the solution here is: 1. Add several missing properties to `<MonoAOTCompiler/>` so we don't have to rely on the `%(AotArguments)` item metadata. No splitting on `;` would be required, `ld-flags` can be passed in and used as-is. 2. Add a new `WorkingDirectory` property. When this is set, assume paths passed in might be relative -- and don't transform paths by calling `Path.GetFullPath()`. Lastly, I fixed a place where the UTF8 encoding wasn't passed when MSBuild logging the response file. These changes I tried to make in a way where this shouldn't break other .NET workloads like wasm. If existing MSBuild targets call this task (not using the new properties), the behavior should remain unchanged. I tested these changes by commiting a modified `MonoAOTCompiler.dll`: dotnet/android#6562 I'm able to enable several AOT tests related to #56163.
Fixes: #56163 PR #58523 fixed something on Windows, but it didn't actually address our issues on Android. A directory name like `foo Ümläüts` fails: * `mkdir 'foo Ümläüts' ; cd 'foo Ümläüts'` * `dotnet new android` * `dotnet build -c Release -p:RunAOTCompilation=true` (adding `-p:EnableLLVM=true` complicates further) The error: Precompiling failed for C:\src\foo Ümläüts\obj\Release\android-arm64\linked\System.Private.CoreLib.dll: Error: Loaded assembly 'C:\src\foo ├£ml├ñ├╝ts\obj\Release\android-arm64\linked\System.Private.CoreLib.dll' doesn't match original file name 'C:\foo ▄mlΣⁿts\obj\Release\android-arm64\linked\System.Private.CoreLib.dll'. Set MONO_PATH to the assembly's location. Reviewing the existing AOT implementation in Xamarin.Android, I found out *why* Xamarin.Android works: [AOT] response file obj\Release\120\aot\arm64-v8a\App36.dll\response.txt: --llvm "--aot=temp-path=obj\Release\120\aot\arm64-v8a\App36.dll,llvm-path=C:\Program Files\Microsoft Visual Studio\2022\Preview\MSBuild\Xamarin\Android,outfile=obj\Release\120\aot\arm64-v8a\libaot-App36.dll.so,msym-dir=obj\Release\120\aot\arm64-v8a,asmwriter,mtriple=aarch64-linux-android,tool-prefix=C:\Program Files (x86)\Android\android-sdk\ndk-bundle\toolchains\llvm\prebuilt\windows-x86_64\bin\aarch64-linux-android-,ld-name=ld.EXE,ld-flags=\"-LC:\Program Files (x86)\Android\android-sdk\ndk-bundle\toolchains\llvm\prebuilt\windows-x86_64\lib\gcc\aarch64-linux-android\4.9.x\";\"-LC:\Program Files (x86)\Android\android-sdk\ndk-bundle\platforms\android-21\arch-arm64\usr\lib\";\"C:\Program Files (x86)\Android\android-sdk\ndk-bundle\toolchains\llvm\prebuilt\windows-x86_64\lib\gcc\aarch64-linux-android\4.9.x\libgcc.a\";\"C:\Program Files (x86)\Android\android-sdk\ndk-bundle\platforms\android-21\arch-arm64\usr\lib\libc.so\";\"C:\Program Files (x86)\Android\android-sdk\ndk-bundle\platforms\android-21\arch-arm64\usr\lib\libm.so\"" C:\Users\jopepper\source\repos\App36\App36\obj\Release\120\android\assets\shrunk\App36.dll 1. Xamarin.Android passes *relative* paths. The `foo Ümläüts` directory name doesn't even come into play for some arguments. 2. With LLVM, `ld-flags` contains a `;`. The existing code splits on `;` and joins on `,`: https://github.com/dotnet/runtime/blob/25c207351c4f57cf2daa98caaf327a8b8d83edb8/src/tasks/AotCompilerTask/MonoAOTCompiler.cs#L505-L509 So we lose any `;` delimiters for the `ld-flags` value, they get replaced by `,`. I think the solution here is: 1. Add several missing properties to `<MonoAOTCompiler/>` so we don't have to rely on the `%(AotArguments)` item metadata. No splitting on `;` would be required, `ld-flags` can be passed in and used as-is. 2. Add a new `WorkingDirectory` property. When this is set, assume paths passed in might be relative -- and don't transform paths by calling `Path.GetFullPath()`. Lastly, I fixed a place where the UTF8 encoding wasn't passed when MSBuild logging the response file. These changes I tried to make in a way where this shouldn't break other .NET workloads like wasm. If existing MSBuild targets call this task (not using the new properties), the behavior should remain unchanged. I tested these changes by commiting a modified `MonoAOTCompiler.dll`: dotnet/android#6562 I'm able to enable several AOT tests related to #56163.
Fixes: #56163 PR #58523 fixed something on Windows, but it didn't actually address our issues on Android. A directory name like `foo Ümläüts` fails: * `mkdir 'foo Ümläüts' ; cd 'foo Ümläüts'` * `dotnet new android` * `dotnet build -c Release -p:RunAOTCompilation=true` (adding `-p:EnableLLVM=true` complicates further) The error: Precompiling failed for C:\src\foo Ümläüts\obj\Release\android-arm64\linked\System.Private.CoreLib.dll: Error: Loaded assembly 'C:\src\foo ├£ml├ñ├╝ts\obj\Release\android-arm64\linked\System.Private.CoreLib.dll' doesn't match original file name 'C:\foo ▄mlΣⁿts\obj\Release\android-arm64\linked\System.Private.CoreLib.dll'. Set MONO_PATH to the assembly's location. Reviewing the existing AOT implementation in Xamarin.Android, I found out *why* Xamarin.Android works: [AOT] response file obj\Release\120\aot\arm64-v8a\App36.dll\response.txt: --llvm "--aot=temp-path=obj\Release\120\aot\arm64-v8a\App36.dll,llvm-path=C:\Program Files\Microsoft Visual Studio\2022\Preview\MSBuild\Xamarin\Android,outfile=obj\Release\120\aot\arm64-v8a\libaot-App36.dll.so,msym-dir=obj\Release\120\aot\arm64-v8a,asmwriter,mtriple=aarch64-linux-android,tool-prefix=C:\Program Files (x86)\Android\android-sdk\ndk-bundle\toolchains\llvm\prebuilt\windows-x86_64\bin\aarch64-linux-android-,ld-name=ld.EXE,ld-flags=\"-LC:\Program Files (x86)\Android\android-sdk\ndk-bundle\toolchains\llvm\prebuilt\windows-x86_64\lib\gcc\aarch64-linux-android\4.9.x\";\"-LC:\Program Files (x86)\Android\android-sdk\ndk-bundle\platforms\android-21\arch-arm64\usr\lib\";\"C:\Program Files (x86)\Android\android-sdk\ndk-bundle\toolchains\llvm\prebuilt\windows-x86_64\lib\gcc\aarch64-linux-android\4.9.x\libgcc.a\";\"C:\Program Files (x86)\Android\android-sdk\ndk-bundle\platforms\android-21\arch-arm64\usr\lib\libc.so\";\"C:\Program Files (x86)\Android\android-sdk\ndk-bundle\platforms\android-21\arch-arm64\usr\lib\libm.so\"" C:\Users\jopepper\source\repos\App36\App36\obj\Release\120\android\assets\shrunk\App36.dll 1. Xamarin.Android passes *relative* paths. The `foo Ümläüts` directory name doesn't even come into play for some arguments. 2. With LLVM, `ld-flags` contains a `;`. The existing code splits on `;` and joins on `,`: https://github.com/dotnet/runtime/blob/25c207351c4f57cf2daa98caaf327a8b8d83edb8/src/tasks/AotCompilerTask/MonoAOTCompiler.cs#L505-L509 So we lose any `;` delimiters for the `ld-flags` value, they get replaced by `,`. I think the solution here is: 1. Add several missing properties to `<MonoAOTCompiler/>` so we don't have to rely on the `%(AotArguments)` item metadata. No splitting on `;` would be required, `ld-flags` can be passed in and used as-is. 2. Add a new `WorkingDirectory` property. When this is set, assume paths passed in might be relative -- and don't transform paths by calling `Path.GetFullPath()`. Lastly, I fixed a place where the UTF8 encoding wasn't passed when MSBuild logging the response file. These changes I tried to make in a way where this shouldn't break other .NET workloads like wasm. If existing MSBuild targets call this task (not using the new properties), the behavior should remain unchanged. I tested these changes by commiting a modified `MonoAOTCompiler.dll`: dotnet/android#6562 I'm able to enable several AOT tests related to #56163. Co-authored-by: Jonathan Peppers <jonathan.peppers@microsoft.com>
Description
Create a
dotnet new android
project in a folder named such asBuildAotApplicationAndBundle AndÜmläüts_arm64-v8a_False_True
.Build with
-c Release -p:RunAOTCompilation=true
, and you get the error:A screenshot of the
.binlog
viewer shows odd characters as well:Logs: msbuild.zip
Configuration
I believe this would also happen in Preview 7.
Regression?
No, Android AOT is a new feature.
/cc @akoeplinger @steveisok
The text was updated successfully, but these errors were encountered: