-
Notifications
You must be signed in to change notification settings - Fork 564
Make sure _GenerateJavaStubs always generates native assembly files
#9001
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
Conversation
_GenerateJavaStubs always generates native assembly_GenerateJavaStubs always generates native assembly files
jonathanpeppers
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This causes a test failure:
GenerateJavaStubsAndAssembly
_GenerateJavaStubs should be skipped!
Expected: True
But was: False
I think a build with no changes should be skipped:
https://github.com/xamarin/xamarin-android/blob/f5fcd4ddc5bacdb9699c50f6dad80627b80d72c8/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/IncrementalBuildTest.cs#L976
But it said:
Input file "obj/Debug/android/assets/armeabi-v7a/UnnamedProject.dll" is newer than output file "obj/Debug/android/typemaps.armeabi-v7a.ll".
If we took this change, I think we'd need to touch all the .ll files, too? Does it currently use some "copy if changed" logic?
|
@jonathanpeppers yep, it uses |
| </ItemGroup> | ||
|
|
||
| <Touch Files="$(_AndroidStampDirectory)_GenerateJavaStubs.stamp" AlwaysCreate="True" /> | ||
| <Touch Files="@(_TypeMapAssemblySource)" /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alternatively, do we know what deleted @(_TypeMapAssemblySource)? Are they missing from FileWrites?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's the problem, we have no idea why they are gone. The guess is that some earlier build deleted them (DTB perhaps?) which we don't have build logs for.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Regardless of what made the files disappear, I don't think a stamp file in Outputs is enough, at least in this case. The task inside the target produces files, and we must make sure that those files exist (whether they were removed by us for some reason, or by the developer) and so they must be part of the outputs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So I wonder if it is this.
Because the _TypeMapAssemblySource are generated via a Task. If the task does not run, the _TypeMapAssemblySource will be empty.
On a DTB is _GeneratedJavaStubs is skipped the task filling in the _TypeMapAssemblySource ItemGroup will be empty. As a result the FileWrites entry will not include the files.
In the case where the Task is not run, we need a way to populate the _TypeMapAssemblySource from the files on disk to make sure they are not deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have this chain of dependencies:
<Target Name="_PrepareNativeAssemblySources">
<PrepareAbiItems
BuildTargetAbis="@(_BuildTargetAbis)"
NativeSourcesDir="$(_NativeAssemblySourceDir)"
InstantRunEnabled="$(_InstantRunEnabled)"
Debug="$(AndroidIncludeDebugSymbols)"
Mode="typemap">
<Output TaskParameter="AssemblySources" ItemName="_TypeMapAssemblySource" />
<Output TaskParameter="AssemblyIncludes" ItemName="_TypeMapAssemblyInclude" />
</PrepareAbiItems>
</Target>
<PropertyGroup>
<_GenerateJavaStubsDependsOnTargets>
_SetLatestTargetFrameworkVersion;
_PrepareAssemblies;
_PrepareNativeAssemblySources;
$(_AfterPrepareAssemblies);
</_GenerateJavaStubsDependsOnTargets>
</PropertyGroup>
<Target Name="_GenerateJavaStubs"
DependsOnTargets="$(_GenerateJavaStubsDependsOnTargets);$(BeforeGenerateAndroidManifest)"
Inputs="@(_AndroidMSBuildAllProjects);@(_ResolvedUserMonoAndroidAssemblies);$(_AndroidManifestAbs);$(_AndroidBuildPropertiesCache);@(AndroidEnvironment);@(LibraryEnvironments)"
Outputs="$(_AndroidStampDirectory)_GenerateJavaStubs.stamp">Will _PrepareNativeAssemblySources be ignored when _GenerateJavaStubs Outputs are deemed up to date?
968baaf to
dc1bf55
Compare
dc1bf55 to
9fd777d
Compare
Fixes: #8967 For some reason, sometimes the `typemap*.ll` files are sometimes removed from the `obj/` directory which leads to build errors similar to: typemaps.x86_64.ll: error: Could not open input file: no such file or directory Files are generated by the `GenerateJavaStubs` tasks, which is invoked by the `_GenerateJavaStubs` target. However, the target doesn't specify the `*.ll` files in its `Outputs` parameter and, therefore, whenever the files are removed but the `_GenerateJavaStubs.stamp` file is newer than the items/files specified in the target's `Inputs` parameter, the native assembly files aren't regenerated leading to the above error. To fix this, we need to add the `typemap*.ll` files to the target's `Outputs` set, thus forcing their regeneration should they be no longer where they are expected to be.
9fd777d to
5b3cbd1
Compare
|
/azp run |
|
Azure Pipelines successfully started running 1 pipeline(s). |
Fixes: dotnet#8967 Context: dotnet#9001 You can cause a build error in .NET 8 by doing: * Start an x86 or x86_64 emulator * `dotnet build -t:Run` * Close the emulator, attach an arm or arm64 device * `dotnet build -t:Run` Emits the error: C:\Program Files\dotnet\packs\Microsoft.Android.Sdk.Windows\34.0.113\tools\Xamarin.Android.Common.targets(2063,3): error XA3006: Could not compile native assembly file: typemaps.x86_64.ll stderr | C:\Program Files\dotnet\packs\Microsoft.Android.Sdk.Windows\34.0.113\tools\binutils\bin\llc.exe: error: C:\Program Files\dotnet\packs\Microsoft.Android.Sdk.Windows\34.0.113\tools\binutils\bin\llc.exe: typemaps.x86_64.ll: error: Could not open input file: no such file or directory This works fine in Visual Studio, but not at the command-line. The underlying problem is due to `_GeneratePackageManagerJava` target running, while the `_GenerateJavaStubs` target *did not*: Skipping target "_GenerateJavaStubs" because all output files are up-to-date with respect to the input files. ... Input file "obj\Debug\net8.0-android\resolvedassemblies.hash" is newer than output file "obj\Debug\net8.0-android\stamp\_GeneratePackageManagerJava.stamp". These two targets should almost always run together, so we should ensure that they do. This problem also doesn't happen .NET 9, as both targets are invalidated for a different reason: Target Name=_LinkAssembliesNoShrink Project=UnnamedProject.csproj Building target "_LinkAssembliesNoShrink" completely. Output file "obj\Debug\android\assets\x86_64\UnnamedProject.dll" does not exist. Since, we build per-RID in .NET 9, `obj\Debug\android\assets\x86_64\UnnamedProject.dll` has an `x86_64` in the path, which is not present in the .NET 8 build. Reviewing the two sets of `Inputs`: <Target Name="_GenerateJavaStubs" ... Inputs="@(_AndroidMSBuildAllProjects);@(_ResolvedUserMonoAndroidAssemblies);$(_AndroidManifestAbs);$(_AndroidBuildPropertiesCache);@(AndroidEnvironment);@(LibraryEnvironments)" ... <Target Name="_GeneratePackageManagerJava" ... Inputs="@(_AndroidMSBuildAllProjects);$(_ResolvedUserAssembliesHashFile);$(MSBuildProjectFile);$(_AndroidBuildPropertiesCache);@(AndroidEnvironment);@(LibraryEnvironments)" Let's align them more closely by: * Track assembly changes in the exact same way: $(_ResolvedUserAssembliesHashFile);@(_ResolvedUserMonoAndroidAssemblies); This way if an assembly is added, removed, or timestamp changed: both targets are in sync. * Don't track `$(MSBuildProjectFile)`, this should already be in `@(_AndroidMSBuildAllProjects)`. With this change in place manually, I'm not able to reproduce the problem any longer. PR dotnet#9001 may also have fixed this issue, but it could cause targets to run on every incremental build -- a performance issue.
|
Closing in favor of #9174 |
…ets (#9174) Fixes: #8967 Context: #9001 You can cause a build error in .NET 8 by doing: * Start an x86 or x86_64 emulator * `dotnet build -t:Run` * Close the emulator, attach an arm or arm64 device * `dotnet build -t:Run` Emits the error: Xamarin.Android.Common.targets(2063,3): error XA3006: Could not compile native assembly file: typemaps.x86_64.ll stderr | C:\Program Files\dotnet\packs\Microsoft.Android.Sdk.Windows\34.0.113\tools\binutils\bin\llc.exe: error: C:\Program Files\dotnet\packs\Microsoft.Android.Sdk.Windows\34.0.113\tools\binutils\bin\llc.exe: typemaps.x86_64.ll: error: Could not open input file: no such file or directory This works fine in Visual Studio, but not at the command-line. The underlying problem is due to `_GeneratePackageManagerJava` target running, while the `_GenerateJavaStubs` target *did not*: Skipping target "_GenerateJavaStubs" because all output files are up-to-date with respect to the input files. ... Input file "obj\Debug\net8.0-android\resolvedassemblies.hash" is newer than output file "obj\Debug\net8.0-android\stamp\_GeneratePackageManagerJava.stamp". These two targets should almost always run together, so we should ensure that they do. This problem also doesn't happen .NET 9, as both targets are invalidated for a different reason: Target Name=_LinkAssembliesNoShrink Project=UnnamedProject.csproj Building target "_LinkAssembliesNoShrink" completely. Output file "obj\Debug\android\assets\x86_64\UnnamedProject.dll" does not exist. Since, we build per-RID in .NET 9, `obj\Debug\android\assets\x86_64\UnnamedProject.dll` has an `x86_64` in the path, which is not present in the .NET 8 build. Reviewing the two sets of `Inputs`: <Target Name="_GenerateJavaStubs" ... Inputs="@(_AndroidMSBuildAllProjects);@(_ResolvedUserMonoAndroidAssemblies);$(_AndroidManifestAbs);$(_AndroidBuildPropertiesCache);@(AndroidEnvironment);@(LibraryEnvironments)" ... <Target Name="_GeneratePackageManagerJava" ... Inputs="@(_AndroidMSBuildAllProjects);$(_ResolvedUserAssembliesHashFile);$(MSBuildProjectFile);$(_AndroidBuildPropertiesCache);@(AndroidEnvironment);@(LibraryEnvironments)" Let's align them more closely by: * Track assembly changes in the exact same way: $(_ResolvedUserAssembliesHashFile);@(_ResolvedUserMonoAndroidAssemblies); This way if an assembly is added, removed, or timestamp changed: both targets are in sync. * Don't track `$(MSBuildProjectFile)`, this should already be in `@(_AndroidMSBuildAllProjects)`. With this change in place manually, I'm not able to reproduce the problem any longer. PR #9001 may also have fixed this issue, but it could cause targets to run on every incremental build -- a performance issue.
…ets (#9174) Fixes: #8967 Context: #9001 You can cause a build error in .NET 8 by doing: * Start an x86 or x86_64 emulator * `dotnet build -t:Run` * Close the emulator, attach an arm or arm64 device * `dotnet build -t:Run` Emits the error: Xamarin.Android.Common.targets(2063,3): error XA3006: Could not compile native assembly file: typemaps.x86_64.ll stderr | C:\Program Files\dotnet\packs\Microsoft.Android.Sdk.Windows\34.0.113\tools\binutils\bin\llc.exe: error: C:\Program Files\dotnet\packs\Microsoft.Android.Sdk.Windows\34.0.113\tools\binutils\bin\llc.exe: typemaps.x86_64.ll: error: Could not open input file: no such file or directory This works fine in Visual Studio, but not at the command-line. The underlying problem is due to `_GeneratePackageManagerJava` target running, while the `_GenerateJavaStubs` target *did not*: Skipping target "_GenerateJavaStubs" because all output files are up-to-date with respect to the input files. ... Input file "obj\Debug\net8.0-android\resolvedassemblies.hash" is newer than output file "obj\Debug\net8.0-android\stamp\_GeneratePackageManagerJava.stamp". These two targets should almost always run together, so we should ensure that they do. This problem also doesn't happen .NET 9, as both targets are invalidated for a different reason: Target Name=_LinkAssembliesNoShrink Project=UnnamedProject.csproj Building target "_LinkAssembliesNoShrink" completely. Output file "obj\Debug\android\assets\x86_64\UnnamedProject.dll" does not exist. Since, we build per-RID in .NET 9, `obj\Debug\android\assets\x86_64\UnnamedProject.dll` has an `x86_64` in the path, which is not present in the .NET 8 build. Reviewing the two sets of `Inputs`: <Target Name="_GenerateJavaStubs" ... Inputs="@(_AndroidMSBuildAllProjects);@(_ResolvedUserMonoAndroidAssemblies);$(_AndroidManifestAbs);$(_AndroidBuildPropertiesCache);@(AndroidEnvironment);@(LibraryEnvironments)" ... <Target Name="_GeneratePackageManagerJava" ... Inputs="@(_AndroidMSBuildAllProjects);$(_ResolvedUserAssembliesHashFile);$(MSBuildProjectFile);$(_AndroidBuildPropertiesCache);@(AndroidEnvironment);@(LibraryEnvironments)" Let's align them more closely by: * Track assembly changes in the exact same way: $(_ResolvedUserAssembliesHashFile);@(_ResolvedUserMonoAndroidAssemblies); This way if an assembly is added, removed, or timestamp changed: both targets are in sync. * Don't track `$(MSBuildProjectFile)`, this should already be in `@(_AndroidMSBuildAllProjects)`. With this change in place manually, I'm not able to reproduce the problem any longer. PR #9001 may also have fixed this issue, but it could cause targets to run on every incremental build -- a performance issue.
Fixes: #8967
For some reason, sometimes the
typemap*.llfiles are sometimes removed from theobj/directory which leads to build errors similar to:Files are generated by the
GenerateJavaStubstasks, which is invoked by the_GenerateJavaStubstarget. However, the target doesn't specify the*.llfiles in itsOutputsparameter and, therefore, whenever the files are removed but the_GenerateJavaStubs.stampfile is newer than the items/files specified in the target'sInputsparameter, the native assembly files aren't regenerated leading to the above error.To fix this, we need to add the
typemap*.llfiles to the target'sOutputsset, thus forcing their regeneration should they be no longer where they are expected to be.