From cc8e9ba3760183754108821bc57e77825d626afd Mon Sep 17 00:00:00 2001 From: Simon Rozsival Date: Mon, 25 May 2026 01:34:02 +0200 Subject: [PATCH 1/2] Define empty compressed assembly symbols Emit all compressed assembly native symbols even when assembly compression is disabled so the CoreCLR app host can link and load libmonodroid successfully. Add regression coverage to the CoreCLR ReadyToRun build test, which already builds with AndroidEnableAssemblyCompression=false. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../Xamarin.Android.Build.Tests/BuildTest2.cs | 8 ++++++++ ...pressedAssembliesNativeAssemblyGenerator.cs | 18 ++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest2.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest2.cs index 8a519e8e365..c26eb290d35 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest2.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest2.cs @@ -148,6 +148,14 @@ public void BasicApplicationPublishReadyToRun ([Values] bool isComposite, [Value using var peReader = new System.Reflection.PortableExecutable.PEReader (stream); Assert.IsTrue (peReader.PEHeaders.CorHeader.ManagedNativeHeaderDirectory.Size > 0, $"ReadyToRun image not found in {assemblyName}.dll! ManagedNativeHeaderDirectory should not be empty!"); + + var compressedAssembliesSource = Path.Combine (Root, b.ProjectDirectory, proj.IntermediateOutputPath, "android", $"compressed_assemblies.{abi}.ll"); + FileAssert.Exists (compressedAssembliesSource); + var compressedAssembliesSourceText = File.ReadAllText (compressedAssembliesSource); + StringAssert.Contains ("@compressed_assembly_count", compressedAssembliesSourceText); + StringAssert.Contains ("@compressed_assembly_descriptors", compressedAssembliesSourceText); + StringAssert.Contains ("@uncompressed_assemblies_data_size", compressedAssembliesSourceText); + StringAssert.Contains ("@uncompressed_assemblies_data_buffer", compressedAssembliesSourceText); } [Test] diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/CompressedAssembliesNativeAssemblyGenerator.cs b/src/Xamarin.Android.Build.Tasks/Utilities/CompressedAssembliesNativeAssemblyGenerator.cs index b2a27fa31cf..4aa1428b02c 100644 --- a/src/Xamarin.Android.Build.Tasks/Utilities/CompressedAssembliesNativeAssemblyGenerator.cs +++ b/src/Xamarin.Android.Build.Tasks/Utilities/CompressedAssembliesNativeAssemblyGenerator.cs @@ -134,6 +134,24 @@ out List? buffers ); if (archData.Count == 0) { + var emptyCountVar = new LlvmIrGlobalVariable (typeof(uint), CompressedAssemblyCountSymbolName) { + Options = LlvmIrVariableOptions.GlobalConstant, + Value = 0u, + }; + module.Add (emptyCountVar); + + var emptyDescriptorsVar = new LlvmIrGlobalVariable (typeof(List>), DescriptorsArraySymbolName) { + Options = LlvmIrVariableOptions.GlobalWritable, + Value = new List> (), + }; + module.Add (emptyDescriptorsVar); + + var emptyBufferSizeVar = new LlvmIrGlobalVariable (typeof(uint), UncompressedAssembliesBufferSizeSymbolName) { + Options = LlvmIrVariableOptions.GlobalConstant, + Value = 0u, + }; + module.Add (emptyBufferSizeVar); + var emptyBufferVar = new LlvmIrGlobalVariable (typeof(List), UncompressedAssembliesBufferSymbolName, LlvmIrVariableOptions.GlobalWritable) { ArrayItemCount = 0, ZeroInitializeArray = true, From 9b40a3da914332855185e57fb38c73e85521347b Mon Sep 17 00:00:00 2001 From: Simon Rozsival Date: Mon, 25 May 2026 12:08:58 +0200 Subject: [PATCH 2/2] Strengthen compressed assemblies test Assert the exact empty compressed assemblies LLVM IR definitions when assembly compression is disabled for CoreCLR ReadyToRun publishes. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../Tests/Xamarin.Android.Build.Tests/BuildTest2.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest2.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest2.cs index c26eb290d35..746764e24bb 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest2.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest2.cs @@ -149,13 +149,13 @@ public void BasicApplicationPublishReadyToRun ([Values] bool isComposite, [Value Assert.IsTrue (peReader.PEHeaders.CorHeader.ManagedNativeHeaderDirectory.Size > 0, $"ReadyToRun image not found in {assemblyName}.dll! ManagedNativeHeaderDirectory should not be empty!"); - var compressedAssembliesSource = Path.Combine (Root, b.ProjectDirectory, proj.IntermediateOutputPath, "android", $"compressed_assemblies.{abi}.ll"); + var compressedAssembliesSource = Path.Combine (Root, b.ProjectDirectory, proj.IntermediateOutputPath, rid, "android", $"compressed_assemblies.{abi}.ll"); FileAssert.Exists (compressedAssembliesSource); var compressedAssembliesSourceText = File.ReadAllText (compressedAssembliesSource); - StringAssert.Contains ("@compressed_assembly_count", compressedAssembliesSourceText); - StringAssert.Contains ("@compressed_assembly_descriptors", compressedAssembliesSourceText); - StringAssert.Contains ("@uncompressed_assemblies_data_size", compressedAssembliesSourceText); - StringAssert.Contains ("@uncompressed_assemblies_data_buffer", compressedAssembliesSourceText); + StringAssert.Contains ("@compressed_assembly_count = dso_local local_unnamed_addr constant i32 0, align 4", compressedAssembliesSourceText); + StringAssert.Contains ("@compressed_assembly_descriptors = dso_local local_unnamed_addr global [0 x %struct.CompressedAssemblyDescriptor] zeroinitializer, align 4", compressedAssembliesSourceText); + StringAssert.Contains ("@uncompressed_assemblies_data_size = dso_local local_unnamed_addr constant i32 0, align 4", compressedAssembliesSourceText); + StringAssert.Contains ("@uncompressed_assemblies_data_buffer = dso_local local_unnamed_addr global [0 x i8] zeroinitializer, align 1", compressedAssembliesSourceText); } [Test]