-
Notifications
You must be signed in to change notification settings - Fork 536
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
[XABT] Make assembly compression incremental. #9704
base: main
Are you sure you want to change the base?
Conversation
/// <summary> | ||
/// Returns true if the input file is newer than the output file. | ||
/// </summary> | ||
public static bool IsFileOutOfDate (string input, string output) |
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.
Is this logic in a separate target? We could use MSBuild's Inputs and Outputs to do this instead?
And then could test it with this helper method:
Line 237 in ad6cc1b
b.Output.AssertTargetIsPartiallyBuilt ("_CompileResources"); |
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.
I initially did it this way, but I didn't like that it calls the target X00 individual times. This flooded the binlog making it a lot harder to read.
From reading the docs, I had thought it would call the target once, providing an ItemGroup of inputs that needed to be updated, but that was not the case.
The other downside is that it needed 3 targets to do it this way:
- Target to set up the Input ItemGroup with Destination metadata
- The incremental target
- Target to figure out which compressions were successful so that the APK building task knew whether to use the compressed file or the uncompressed file
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.
MSBuild is definitely arcane, but you can make a target build partially and not "batch". <LinkAssembliesNoShrink/>
is an example that runs the task once:
android/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets
Lines 1429 to 1447 in 7454deb
<Target Name="_LinkAssembliesNoShrink" DependsOnTargets="_LinkAssembliesNoShrinkInputs" Condition="'$(AndroidLinkMode)' == 'None'" Inputs="@(ResolvedAssemblies);$(_AndroidBuildPropertiesCache)" Outputs="@(ResolvedAssemblies->'$(MonoAndroidIntermediateAssemblyDir)%(DestinationSubPath)')"> <LinkAssembliesNoShrink ResolvedAssemblies="@(_AllResolvedAssemblies)" SourceFiles="@(ResolvedAssemblies)" DestinationFiles="@(ResolvedAssemblies->'$(MonoAndroidIntermediateAssemblyDir)%(DestinationSubPath)')" TargetName="$(TargetName)" AddKeepAlives="$(AndroidAddKeepAlives)" UseDesignerAssembly="$(AndroidUseDesignerAssembly)" Deterministic="$(Deterministic)" ReadSymbols="$(_AndroidLinkAssembliesReadSymbols)" /> <ItemGroup> <FileWrites Include="$(MonoAndroidIntermediateAssemblyDir)**" /> </ItemGroup> </Target>
If it's easier to write C# code that is ok, if it has enough logging to know files changed.
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.
Interesting, _LinkAssembliesNoShrink
does appear to do exactly what I wanted to do:
Here's what I was using and I don't understand why it works differently:
<Target Name="_CompressAssemblies"
DependsOnTargets="_CollectAssembliesToCompress"
Inputs="@(_AssembliesToCompress)"
Outputs="@(_AssembliesToCompress->%(DestinationPath))"
Condition="'$(EmbedAssembliesIntoApk)' == 'True'">
<CompressAssembly
AssembliesToCompress="@(_AssembliesToCompress)">
<Output TaskParameter="CompressionFailedAssemblies" ItemName="_CompressionFailedAssemblies" />
</CompressAssembly>
</Target>
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.
I would normally put single quote around: Outputs="@(_AssembliesToCompress->'%(DestinationPath)')"
Other than that, maybe it's the <Output/>
that makes it behave differently?
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.
d217bf1
to
679a43e
Compare
679a43e
to
c097ec2
Compare
case CompressionResult.EncodingFailed: | ||
log.LogMessage ($"Failed to compress {sourceAssembly}"); | ||
break; | ||
case CompressionResult.InputTooBig: |
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.
Reviewing the full code file this does not seem to be enabled anymore? The code which raised this issue is commented out.
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.
I don't know why that error condition is disabled in the existing code, but I think it's fine to ensure we log it properly if it ever gets reenabled.
If using
$(AndroidEnableAssemblyCompression)
today, we do not compress assemblies incrementally. That is, we always compress every assembly even if they haven't changed since the previous build.Update the
CompressAssemblies
task to check if the input is newer than the output, and skip recompressing if the input has not changed.This is most visible with the following test case:
CompressAssemblies
tasks)ChangeCSharpJLO
should be similarly reduced, however something earlier in the build process is causingMono.Android.dll
to get touched so it is getting recompressed. We'll leave that as an investigation for another day.