From f3dfe900362a56d253d3ed8a1d060c372be37a18 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Thu, 3 Oct 2024 21:53:13 +0200 Subject: [PATCH 01/60] Embed some data files in `libxamarin-app.so` --- .../Tasks/GeneratePackageManagerJava.cs | 359 +++++++++++++++++- .../Utilities/DSOWrapperGenerator.cs | 2 +- .../Utilities/MonoAndroidHelper.cs | 21 +- .../Xamarin.Android.Common.targets | 33 +- 4 files changed, 387 insertions(+), 28 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/GeneratePackageManagerJava.cs b/src/Xamarin.Android.Build.Tasks/Tasks/GeneratePackageManagerJava.cs index a82c4c0408f..91e5e21ab27 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/GeneratePackageManagerJava.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/GeneratePackageManagerJava.cs @@ -30,10 +30,242 @@ public override bool RunTask () pkgmgr.WriteLine ("public class MonoPackageManager_Resources {"); pkgmgr.WriteLine ("\tpublic static String[] Assemblies = new String[]{"); - pkgmgr.WriteLine ("\t\t/* We need to ensure that \"{0}\" comes first in this list. */", mainFileName); - pkgmgr.WriteLine ("\t\t\"" + mainFileName + "\","); - foreach (var assembly in ResolvedUserAssemblies) { - if (string.Compare (Path.GetFileName (assembly.ItemSpec), mainFileName, StringComparison.OrdinalIgnoreCase) == 0) + public ITaskItem[] NativeLibraries { get; set; } + + public ITaskItem[] MonoComponents { get; set; } + + public ITaskItem[] SatelliteAssemblies { get; set; } + + public bool UseAssemblyStore { get; set; } + + [Required] + public string OutputDirectory { get; set; } + + [Required] + public string EnvironmentOutputDirectory { get; set; } + + [Required] + public string MainAssembly { get; set; } + + [Required] + public string TargetFrameworkVersion { get; set; } + + [Required] + public string Manifest { get; set; } + + [Required] + public string [] SupportedAbis { get; set; } + + [Required] + public string AndroidPackageName { get; set; } + + [Required] + public bool EnablePreloadAssembliesDefault { get; set; } + + [Required] + public string AndroidBinUtilsDirectory { get; set; } + + public bool EnableMarshalMethods { get; set; } + public string RuntimeConfigBinFilePath { get; set; } + public string BoundExceptionType { get; set; } + + public string PackageNamingPolicy { get; set; } + public string Debug { get; set; } + public ITaskItem[] Environments { get; set; } + public string AndroidAotMode { get; set; } + public bool AndroidAotEnableLazyLoad { get; set; } + public bool EnableLLVM { get; set; } + public string HttpClientHandlerType { get; set; } + public string TlsProvider { get; set; } + public string AndroidSequencePointsMode { get; set; } + public bool EnableSGenConcurrent { get; set; } + public string? CustomBundleConfigFile { get; set; } + + bool _Debug { + get { + return string.Equals (Debug, "true", StringComparison.OrdinalIgnoreCase); + } + } + + public override bool RunTask () + { + var doc = AndroidAppManifest.Load (Manifest, MonoAndroidHelper.SupportedVersions); + int minApiVersion = doc.MinSdkVersion == null ? 4 : (int) doc.MinSdkVersion; + // We need to include any special assemblies in the Assemblies list + var mainFileName = Path.GetFileName (MainAssembly); + + using (var pkgmgr = MemoryStreamPool.Shared.CreateStreamWriter ()) { + pkgmgr.WriteLine ("package mono;"); + + // Write all the user assemblies + pkgmgr.WriteLine ("public class MonoPackageManager_Resources {"); + pkgmgr.WriteLine ("\tpublic static String[] Assemblies = new String[]{"); + + pkgmgr.WriteLine ("\t\t/* We need to ensure that \"{0}\" comes first in this list. */", mainFileName); + pkgmgr.WriteLine ("\t\t\"" + mainFileName + "\","); + foreach (var assembly in ResolvedUserAssemblies) { + if (string.Compare (Path.GetFileName (assembly.ItemSpec), mainFileName, StringComparison.OrdinalIgnoreCase) == 0) + continue; + pkgmgr.WriteLine ("\t\t\"" + Path.GetFileName (assembly.ItemSpec) + "\","); + } + foreach (var assembly in MonoAndroidHelper.GetFrameworkAssembliesToTreatAsUserAssemblies (ResolvedAssemblies)) { + if (string.Compare (Path.GetFileName (assembly.ItemSpec), mainFileName, StringComparison.OrdinalIgnoreCase) == 0) + continue; + pkgmgr.WriteLine ("\t\t\"" + Path.GetFileName (assembly.ItemSpec) + "\","); + } + + // Write the assembly dependencies + pkgmgr.WriteLine ("\t};"); + pkgmgr.WriteLine ("\tpublic static String[] Dependencies = new String[]{"); + + //foreach (var assembly in assemblies.Except (args.Assemblies)) { + // if (args.SharedRuntime && !Toolbox.IsInSharedRuntime (assembly)) + // pkgmgr.WriteLine ("\t\t\"" + Path.GetFileName (assembly) + "\","); + //} + + pkgmgr.WriteLine ("\t};"); + + pkgmgr.WriteLine ("}"); + pkgmgr.Flush (); + + // Only copy to the real location if the contents actually changed + var dest = Path.GetFullPath (Path.Combine (OutputDirectory, "MonoPackageManager_Resources.java")); + + Files.CopyIfStreamChanged (pkgmgr.BaseStream, dest); + } + + AddEnvironment (); + + return !Log.HasLoggedErrors; + } + + static internal AndroidTargetArch GetAndroidTargetArchForAbi (string abi) => MonoAndroidHelper.AbiToTargetArch (abi); + + static readonly string[] defaultLogLevel = {"MONO_LOG_LEVEL", "info"}; + static readonly string[] defaultMonoDebug = {"MONO_DEBUG", "gen-compact-seq-points"}; + static readonly string[] defaultHttpMessageHandler = {"XA_HTTP_CLIENT_HANDLER_TYPE", "System.Net.Http.HttpClientHandler, System.Net.Http"}; + static readonly string[] defaultTlsProvider = {"XA_TLS_PROVIDER", "btls"}; + + void AddEnvironment () + { + bool usesMonoAOT = false; + var environmentVariables = new Dictionary (StringComparer.Ordinal); + var systemProperties = new Dictionary (StringComparer.Ordinal); + + if (!Enum.TryParse (PackageNamingPolicy, out PackageNamingPolicy pnp)) { + pnp = PackageNamingPolicyEnum.LowercaseCrc64; + } + + AotMode aotMode = AotMode.None; + if (!string.IsNullOrEmpty (AndroidAotMode) && Aot.GetAndroidAotMode (AndroidAotMode, out aotMode) && aotMode != AotMode.None) { + usesMonoAOT = true; + } + + SequencePointsMode sequencePointsMode; + if (!Aot.TryGetSequencePointsMode (AndroidSequencePointsMode, out sequencePointsMode)) + sequencePointsMode = SequencePointsMode.None; + + // Even though environment files were potentially parsed in GenerateJavaStubs, we need to do it here again because we might have additional environment + // files (generated by us) which weren't present by the time GeneratJavaStubs ran. + var environmentParser = new EnvironmentFilesParser { + BrokenExceptionTransitions = false, + UsesAssemblyPreload = EnablePreloadAssembliesDefault, + }; + environmentParser.Parse (Environments, sequencePointsMode, Log); + + foreach (string line in environmentParser.EnvironmentVariableLines) { + AddEnvironmentVariableLine (line); + } + + if (_Debug && !environmentParser.HaveLogLevel) { + AddEnvironmentVariable (defaultLogLevel[0], defaultLogLevel[1]); + } + + if (sequencePointsMode != SequencePointsMode.None && !environmentParser.HaveMonoDebug) { + AddEnvironmentVariable (defaultMonoDebug[0], defaultMonoDebug[1]); + } + + if (!environmentParser.HaveHttpMessageHandler) { + if (HttpClientHandlerType == null) + AddEnvironmentVariable (defaultHttpMessageHandler[0], defaultHttpMessageHandler[1]); + else + AddEnvironmentVariable ("XA_HTTP_CLIENT_HANDLER_TYPE", HttpClientHandlerType.Trim ()); + } + + if (!environmentParser.HaveMonoGCParams) { + if (EnableSGenConcurrent) + AddEnvironmentVariable ("MONO_GC_PARAMS", "major=marksweep-conc"); + else + AddEnvironmentVariable ("MONO_GC_PARAMS", "major=marksweep"); + } + + global::Android.Runtime.BoundExceptionType boundExceptionType; + if (String.IsNullOrEmpty (BoundExceptionType) || String.Compare (BoundExceptionType, "System", StringComparison.OrdinalIgnoreCase) == 0) { + boundExceptionType = global::Android.Runtime.BoundExceptionType.System; + } else if (String.Compare (BoundExceptionType, "Java", StringComparison.OrdinalIgnoreCase) == 0) { + boundExceptionType = global::Android.Runtime.BoundExceptionType.Java; + } else { + throw new InvalidOperationException ($"Unsupported BoundExceptionType value '{BoundExceptionType}'"); + } + + int assemblyNameWidth = 0; + Encoding assemblyNameEncoding = Encoding.UTF8; + + Action updateNameWidth = (ITaskItem assembly) => { + if (UseAssemblyStore) { + return; + } + + string assemblyName = Path.GetFileName (assembly.ItemSpec); + int nameBytes = assemblyNameEncoding.GetBytes (assemblyName).Length; + if (nameBytes > assemblyNameWidth) { + assemblyNameWidth = nameBytes; + } + }; + + int assemblyCount = 0; + bool enableMarshalMethods = EnableMarshalMethods; + HashSet archAssemblyNames = null; + HashSet uniqueAssemblyNames = new HashSet (StringComparer.OrdinalIgnoreCase); + Action updateAssemblyCount = (ITaskItem assembly) => { + string? culture = MonoAndroidHelper.GetAssemblyCulture (assembly); + string fileName = Path.GetFileName (assembly.ItemSpec); + string assemblyName; + + if (String.IsNullOrEmpty (culture)) { + assemblyName = fileName; + } else { + assemblyName = $"{culture}/{fileName}"; + } + + if (!uniqueAssemblyNames.Contains (assemblyName)) { + uniqueAssemblyNames.Add (assemblyName); + } + + string abi = MonoAndroidHelper.GetAssemblyAbi (assembly); + archAssemblyNames ??= new HashSet (StringComparer.OrdinalIgnoreCase); + + if (!archAssemblyNames.Contains (assemblyName)) { + assemblyCount++; + archAssemblyNames.Add (assemblyName); + } + }; + + if (SatelliteAssemblies != null) { + foreach (ITaskItem assembly in SatelliteAssemblies) { + updateNameWidth (assembly); + updateAssemblyCount (assembly); + } + } + + int android_runtime_jnienv_class_token = -1; + int jnienv_initialize_method_token = -1; + int jnienv_registerjninatives_method_token = -1; + foreach (var assembly in ResolvedAssemblies) { + updateNameWidth (assembly); + updateAssemblyCount (assembly); + + if (android_runtime_jnienv_class_token != -1) { continue; pkgmgr.WriteLine ("\t\t\"" + Path.GetFileName (assembly.ItemSpec) + "\","); } @@ -55,7 +287,124 @@ public override bool RunTask () // Only copy to the real location if the contents actually changed var dest = Path.GetFullPath (Path.Combine (OutputDirectory, "MonoPackageManager_Resources.java")); - Files.CopyIfStreamChanged (pkgmgr.BaseStream, dest); + bool haveRuntimeConfigBlob = !String.IsNullOrEmpty (RuntimeConfigBinFilePath) && File.Exists (RuntimeConfigBinFilePath); + if (haveRuntimeConfigBlob) { + List objectFilePaths = ELFEmbeddingHelper.EmbedBinary ( + Log, + SupportedAbis, + AndroidBinUtilsDirectory, + RuntimeConfigBinFilePath, + ELFEmbeddingHelper.KnownEmbedItems.RuntimeConfig, + EnvironmentOutputDirectory + ); + } + + var jniRemappingNativeCodeInfo = BuildEngine4.GetRegisteredTaskObjectAssemblyLocal (ProjectSpecificTaskObjectKey (GenerateJniRemappingNativeCode.JniRemappingNativeCodeInfoKey), RegisteredTaskObjectLifetime.Build); + var appConfigAsmGen = new ApplicationConfigNativeAssemblyGenerator (environmentVariables, systemProperties, Log) { + UsesMonoAOT = usesMonoAOT, + UsesMonoLLVM = EnableLLVM, + UsesAssemblyPreload = environmentParser.UsesAssemblyPreload, + MonoAOTMode = aotMode.ToString ().ToLowerInvariant (), + AotEnableLazyLoad = AndroidAotEnableLazyLoad, + AndroidPackageName = AndroidPackageName, + BrokenExceptionTransitions = environmentParser.BrokenExceptionTransitions, + PackageNamingPolicy = pnp, + BoundExceptionType = boundExceptionType, + JniAddNativeMethodRegistrationAttributePresent = NativeCodeGenState.Template != null ? NativeCodeGenState.Template.JniAddNativeMethodRegistrationAttributePresent : false, + HaveRuntimeConfigBlob = haveRuntimeConfigBlob, + NumberOfAssembliesInApk = assemblyCount, + BundledAssemblyNameWidth = assemblyNameWidth, + MonoComponents = (MonoComponent)monoComponents, + NativeLibraries = uniqueNativeLibraries, + HaveAssemblyStore = UseAssemblyStore, + AndroidRuntimeJNIEnvToken = android_runtime_jnienv_class_token, + JNIEnvInitializeToken = jnienv_initialize_method_token, + JNIEnvRegisterJniNativesToken = jnienv_registerjninatives_method_token, + JniRemappingReplacementTypeCount = jniRemappingNativeCodeInfo == null ? 0 : jniRemappingNativeCodeInfo.ReplacementTypeCount, + JniRemappingReplacementMethodIndexEntryCount = jniRemappingNativeCodeInfo == null ? 0 : jniRemappingNativeCodeInfo.ReplacementMethodIndexEntryCount, + MarshalMethodsEnabled = EnableMarshalMethods, + IgnoreSplitConfigs = ShouldIgnoreSplitConfigs (), + }; + LLVMIR.LlvmIrModule appConfigModule = appConfigAsmGen.Construct (); + + foreach (string abi in SupportedAbis) { + string targetAbi = abi.ToLowerInvariant (); + string environmentBaseAsmFilePath = Path.Combine (EnvironmentOutputDirectory, $"environment.{targetAbi}"); + string marshalMethodsBaseAsmFilePath = Path.Combine (EnvironmentOutputDirectory, $"marshal_methods.{targetAbi}"); + string environmentLlFilePath = $"{environmentBaseAsmFilePath}.ll"; + string marshalMethodsLlFilePath = $"{marshalMethodsBaseAsmFilePath}.ll"; + AndroidTargetArch targetArch = GetAndroidTargetArchForAbi (abi); + + using var appConfigWriter = MemoryStreamPool.Shared.CreateStreamWriter (); + try { + appConfigAsmGen.Generate (appConfigModule, targetArch, appConfigWriter, environmentLlFilePath); + } catch { + throw; + } finally { + appConfigWriter.Flush (); + Files.CopyIfStreamChanged (appConfigWriter.BaseStream, environmentLlFilePath); + } + + MarshalMethodsNativeAssemblyGenerator marshalMethodsAsmGen; + if (enableMarshalMethods) { + marshalMethodsAsmGen = new MarshalMethodsNativeAssemblyGenerator ( + Log, + assemblyCount, + uniqueAssemblyNames, + EnsureCodeGenState (targetArch) + ); + } else { + marshalMethodsAsmGen = new MarshalMethodsNativeAssemblyGenerator ( + Log, + targetArch, + assemblyCount, + uniqueAssemblyNames + ); + } + + LLVMIR.LlvmIrModule marshalMethodsModule = marshalMethodsAsmGen.Construct (); + using var marshalMethodsWriter = MemoryStreamPool.Shared.CreateStreamWriter (); + try { + marshalMethodsAsmGen.Generate (marshalMethodsModule, targetArch, marshalMethodsWriter, marshalMethodsLlFilePath); + } catch { + throw; + } finally { + marshalMethodsWriter.Flush (); + Files.CopyIfStreamChanged (marshalMethodsWriter.BaseStream, marshalMethodsLlFilePath); + } + } + + NativeCodeGenState EnsureCodeGenState (AndroidTargetArch targetArch) + { + if (nativeCodeGenStates == null || !nativeCodeGenStates.TryGetValue (targetArch, out NativeCodeGenState? state)) { + throw new InvalidOperationException ($"Internal error: missing native code generation state for architecture '{targetArch}'"); + } + + return state; + } + + void AddEnvironmentVariable (string name, string value) + { + if (Char.IsUpper(name [0]) || !Char.IsLetter(name [0])) + environmentVariables [ValidAssemblerString (name)] = ValidAssemblerString (value); + else + systemProperties [ValidAssemblerString (name)] = ValidAssemblerString (value); + } + + void AddEnvironmentVariableLine (string l) + { + string line = l?.Trim (); + if (String.IsNullOrEmpty (line) || line [0] == '#') + return; + + string[] nv = line.Split (new char[]{'='}, 2); + AddEnvironmentVariable (nv[0].Trim (), nv.Length < 2 ? String.Empty : nv[1].Trim ()); + } + + string ValidAssemblerString (string s) + { + return s.Replace ("\"", "\\\""); + } } return !Log.HasLoggedErrors; diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/DSOWrapperGenerator.cs b/src/Xamarin.Android.Build.Tasks/Utilities/DSOWrapperGenerator.cs index 3dd7b1863cb..8ad37974dd1 100644 --- a/src/Xamarin.Android.Build.Tasks/Utilities/DSOWrapperGenerator.cs +++ b/src/Xamarin.Android.Build.Tasks/Utilities/DSOWrapperGenerator.cs @@ -102,7 +102,7 @@ public static string WrapIt (TaskLoggingHelper log, Config config, AndroidTarget File.Copy (stubPath, outputFile, overwrite: true); string quotedOutputFile = MonoAndroidHelper.QuoteFileNameArgument (outputFile); - string objcopy = Path.Combine (config.AndroidBinUtilsDirectory, MonoAndroidHelper.GetExecutablePath (config.AndroidBinUtilsDirectory, "llvm-objcopy")); + string objcopy = MonoAndroidHelper.GetLlvmObjcopyPath (config.AndroidBinUtilsDirectory);; var args = new List { "--add-section", $"payload={MonoAndroidHelper.QuoteFileNameArgument (payloadFilePath)}", diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/MonoAndroidHelper.cs b/src/Xamarin.Android.Build.Tasks/Utilities/MonoAndroidHelper.cs index 518477d9ec4..7937192bf79 100644 --- a/src/Xamarin.Android.Build.Tasks/Utilities/MonoAndroidHelper.cs +++ b/src/Xamarin.Android.Build.Tasks/Utilities/MonoAndroidHelper.cs @@ -783,26 +783,9 @@ public static string QuoteFileNameArgument (string? fileName) return builder.ToString (); } - public static AndroidRuntime ParseAndroidRuntime (string androidRuntime) + public static string GetLlvmObjcopyPath (string androidBinUtilsDirectory) { - if (string.Equals (androidRuntime, "CoreCLR", StringComparison.OrdinalIgnoreCase)) - return AndroidRuntime.CoreCLR; - if (string.Equals (androidRuntime, "NativeAOT", StringComparison.OrdinalIgnoreCase)) - return AndroidRuntime.NativeAOT; - - // Default runtime is MonoVM - return AndroidRuntime.MonoVM; - } - - public static JavaPeerStyle ParseCodeGenerationTarget (string codeGenerationTarget) - { - if (Enum.TryParse (codeGenerationTarget, ignoreCase: true, out JavaPeerStyle style)) - return style; - - // Default is XAJavaInterop1 - return JavaPeerStyle.XAJavaInterop1; + return Path.Combine (androidBinUtilsDirectory, MonoAndroidHelper.GetExecutablePath (androidBinUtilsDirectory, "llvm-objcopy")); } - - public static object GetProjectBuildSpecificTaskObjectKey (object key, string workingDirectory, string intermediateOutputPath) => (key, workingDirectory, intermediateOutputPath); } } diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets index 6421833e60e..b1a1c14e7c0 100644 --- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets +++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets @@ -1880,9 +1880,36 @@ because xbuild doesn't support framework reference assemblies. + ResolvedAssemblies="@(_ResolvedAssemblies)" + ResolvedUserAssemblies="@(_ResolvedUserAssemblies)" + SatelliteAssemblies="@(_AndroidResolvedSatellitePaths)" + NativeLibraries="@(AndroidNativeLibrary);@(EmbeddedNativeLibrary);@(FrameworkNativeLibrary)" + MonoComponents="@(_MonoComponent)" + MainAssembly="$(TargetPath)" + OutputDirectory="$(_AndroidIntermediateJavaSourceDirectory)mono" + EnvironmentOutputDirectory="$(IntermediateOutputPath)android" + TargetFrameworkVersion="$(TargetFrameworkVersion)" + Manifest="$(IntermediateOutputPath)android\AndroidManifest.xml" + Environments="@(_EnvironmentFiles)" + AndroidAotMode="$(AndroidAotMode)" + AndroidAotEnableLazyLoad="$(AndroidAotEnableLazyLoad)" + EnableLLVM="$(EnableLLVM)" + HttpClientHandlerType="$(AndroidHttpClientHandlerType)" + TlsProvider="$(AndroidTlsProvider)" + Debug="$(AndroidIncludeDebugSymbols)" + AndroidSequencePointsMode="$(_SequencePointsMode)" + EnableSGenConcurrent="$(AndroidEnableSGenConcurrent)" + SupportedAbis="@(_BuildTargetAbis)" + AndroidPackageName="$(_AndroidPackage)" + EnablePreloadAssembliesDefault="$(_AndroidEnablePreloadAssembliesDefault)" + PackageNamingPolicy="$(AndroidPackageNamingPolicy)" + BoundExceptionType="$(AndroidBoundExceptionType)" + RuntimeConfigBinFilePath="$(_BinaryRuntimeConfigPath)" + UseAssemblyStore="$(AndroidUseAssemblyStore)" + EnableMarshalMethods="$(_AndroidUseMarshalMethods)" + CustomBundleConfigFile="$(AndroidBundleConfigurationFile)" + AndroidBinUtilsDirectory="$(AndroidBinUtilsDirectory)" + > Date: Mon, 7 Oct 2024 21:48:51 +0200 Subject: [PATCH 02/60] Use llvm-mc to embed the binary, this way we have full control --- .../Tasks/GeneratePackageManagerJava.cs | 7 + .../Utilities/ELFEmbeddingHelper.cs | 191 ++++++++++++++++++ .../Utilities/MonoAndroidHelper.cs | 7 +- .../Xamarin.Android.Common.targets | 3 + src/native/mono/monodroid/monodroid-glue.cc | 5 + .../xamarin-app-stub/application_dso_stub.cc | 3 + .../mono/xamarin-app-stub/xamarin-app.hh | 5 +- 7 files changed, 216 insertions(+), 5 deletions(-) create mode 100644 src/Xamarin.Android.Build.Tasks/Utilities/ELFEmbeddingHelper.cs diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/GeneratePackageManagerJava.cs b/src/Xamarin.Android.Build.Tasks/Tasks/GeneratePackageManagerJava.cs index 91e5e21ab27..53225aa1557 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/GeneratePackageManagerJava.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/GeneratePackageManagerJava.cs @@ -65,6 +65,9 @@ public override bool RunTask () [Required] public string AndroidBinUtilsDirectory { get; set; } + [Output] + public ITaskItem[] EmbeddedObjectFiles { get; set; } + public bool EnableMarshalMethods { get; set; } public string RuntimeConfigBinFilePath { get; set; } public string BoundExceptionType { get; set; } @@ -297,6 +300,10 @@ void AddEnvironment () ELFEmbeddingHelper.KnownEmbedItems.RuntimeConfig, EnvironmentOutputDirectory ); + + EmbeddedObjectFiles = objectFilePaths.ToArray (); + } else { + EmbeddedObjectFiles = Array.Empty (); } var jniRemappingNativeCodeInfo = BuildEngine4.GetRegisteredTaskObjectAssemblyLocal (ProjectSpecificTaskObjectKey (GenerateJniRemappingNativeCode.JniRemappingNativeCodeInfoKey), RegisteredTaskObjectLifetime.Build); diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/ELFEmbeddingHelper.cs b/src/Xamarin.Android.Build.Tasks/Utilities/ELFEmbeddingHelper.cs new file mode 100644 index 00000000000..5195c4b2d17 --- /dev/null +++ b/src/Xamarin.Android.Build.Tasks/Utilities/ELFEmbeddingHelper.cs @@ -0,0 +1,191 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; + +using Microsoft.Build.Framework; +using Microsoft.Build.Utilities; +using Xamarin.Android.Tools; + +namespace Xamarin.Android.Tasks; + +class ELFEmbeddingHelper +{ + public sealed class EmbedItem + { + public readonly string SymbolName; + public readonly string BaseFileName; + + public EmbedItem (string symbolName, string baseFileName) + { + SymbolName = symbolName; + BaseFileName = baseFileName; + } + } + + public static class KnownEmbedItems + { + public static readonly EmbedItem RuntimeConfig = new ("embedded_runtime_config", "runtime_config"); + } + + sealed class LlvmMcTargetConfig + { + public readonly string TargetArch; + public readonly string TripleArch; + public readonly string TripleApiPrefix; + public readonly string AssemblerDirectivePrefix; + public readonly string SizeType; + public readonly uint WordSize; + + public LlvmMcTargetConfig (string targetArch, string tripleArch, string tripleApiPrefix, string assemblerDirectivePrefix, string sizeType, uint wordSize) + { + TargetArch = targetArch; + TripleArch = tripleArch; + TripleApiPrefix = tripleApiPrefix; + AssemblerDirectivePrefix = assemblerDirectivePrefix; + SizeType = sizeType; + WordSize = wordSize; + } + } + + static readonly Dictionary llvmMcConfigs = new () { + { AndroidTargetArch.Arm64, new ("aarch64", "aarch64", "android", "@", ".xword", 8) }, + { AndroidTargetArch.Arm, new ("arm", "armv7a", "androideabi", "%", ".long", 4) }, + { AndroidTargetArch.X86_64, new ("x86-64", "x86_64", "android", "@", ".quad", 8) }, + { AndroidTargetArch.X86, new ("x86", "i686", "android", "@", ".long", 4) }, + }; + + static readonly Encoding asmFileEncoding = new UTF8Encoding (false); + + public static List EmbedBinary ( + TaskLoggingHelper log, + ICollection supportedAbis, + string androidBinUtilsDirectory, + string inputFile, + EmbedItem embedItem, + string outputDirectory) + { + if (supportedAbis.Count < 1) { + throw new ArgumentException ("At least one target ABI must be present", nameof (supportedAbis)); + } + + string llvmMcPath = GetLlvmMcPath (androidBinUtilsDirectory); + var ret = new List (); + foreach (string abi in supportedAbis) { + EmbedBinary ( + log, + ret, + llvmMcPath, + abi, + inputFile, + outputDirectory, + embedItem + ); + } + + return ret; + } + + public static List EmbedBinary ( + TaskLoggingHelper log, + string abi, + string androidBinUtilsDirectory, + string inputFile, + EmbedItem embedItem, + string outputDirectory) + { + if (String.IsNullOrEmpty (abi)) { + throw new ArgumentException ("Must be a supported ABI name", nameof (abi)); + } + + var ret = new List (); + EmbedBinary ( + log, + ret, + GetLlvmMcPath (androidBinUtilsDirectory), + abi, + inputFile, + outputDirectory, + embedItem + ); + return ret; + } + + static void EmbedBinary ( + TaskLoggingHelper log, + List resultItems, + string llvmMcPath, + string abi, + string inputFile, + string outputDirectory, + EmbedItem embedItem) + { + string outputFile = Path.Combine (outputDirectory, $"embed_{embedItem.BaseFileName}.{abi.ToLowerInvariant ()}.o"); + DoEmbed (log, MonoAndroidHelper.AbiToTargetArch (abi), llvmMcPath, inputFile, outputFile, embedItem); + if (!File.Exists (outputFile)) { + return; + } + + var taskItem = new TaskItem (outputFile); + taskItem.SetMetadata ("Abi", abi); + taskItem.SetMetadata ("RuntimeIdentifier", MonoAndroidHelper.AbiToRid (abi)); + resultItems.Add (taskItem); + } + + static void DoEmbed ( + TaskLoggingHelper log, + AndroidTargetArch arch, + string llvmMcPath, + string inputFile, + string outputFile, + EmbedItem item) + { + if (!llvmMcConfigs.TryGetValue (arch, out LlvmMcTargetConfig cfg)) { + throw new NotSupportedException ($"Internal error: unsupported target arch '{arch}'"); + } + + var fi = new FileInfo (inputFile); + long inputFileSize = fi.Length; + string asmInputFile = Path.ChangeExtension (outputFile, ".s"); + + using var fs = File.Open (asmInputFile, FileMode.Create, FileAccess.Write, FileShare.Read); + using var sw = new StreamWriter (fs, asmFileEncoding); + + string symbolName = item.SymbolName; + sw.WriteLine ($".section .rodata,\"a\",{cfg.AssemblerDirectivePrefix}progbits"); + sw.WriteLine (".p2align 3, 0x00"); // Put the data at 4k boundary + sw.WriteLine (); + sw.WriteLine ($".global {symbolName}"); + sw.WriteLine ($".type {symbolName},{cfg.AssemblerDirectivePrefix}object"); + sw.WriteLine ($"{symbolName}:"); + sw.WriteLine ($"\t.incbin \"{inputFile}\""); + sw.WriteLine ($"\t.size {symbolName}, {inputFileSize}"); + sw.WriteLine (); + + symbolName += "_size"; + sw.WriteLine ($".global {symbolName}"); + sw.WriteLine ($"{symbolName}:"); + sw.WriteLine ($"\t{cfg.SizeType}\t{inputFileSize}"); + sw.WriteLine ($"\t.size {symbolName}, {cfg.WordSize}"); + + sw.Flush (); + sw.Close (); + + var args = new List { + $"--arch={cfg.TargetArch}", + "--assemble", + "--filetype=obj", + "-g", + $"--triple={cfg.TripleArch}-linux-{cfg.TripleApiPrefix}{XABuildConfig.AndroidMinimumDotNetApiLevel}", + "-o", MonoAndroidHelper.QuoteFileNameArgument (outputFile), + MonoAndroidHelper.QuoteFileNameArgument (asmInputFile), + }; + + int ret = MonoAndroidHelper.RunProcess (llvmMcPath, String.Join (" ", args), log); + if (ret != 0) { + return; + } + } + + static string GetLlvmMcPath (string androidBinUtilsDirectory) => MonoAndroidHelper.GetLlvmMcPath (androidBinUtilsDirectory); +} diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/MonoAndroidHelper.cs b/src/Xamarin.Android.Build.Tasks/Utilities/MonoAndroidHelper.cs index 7937192bf79..9276ba600ca 100644 --- a/src/Xamarin.Android.Build.Tasks/Utilities/MonoAndroidHelper.cs +++ b/src/Xamarin.Android.Build.Tasks/Utilities/MonoAndroidHelper.cs @@ -783,9 +783,12 @@ public static string QuoteFileNameArgument (string? fileName) return builder.ToString (); } - public static string GetLlvmObjcopyPath (string androidBinUtilsDirectory) + public static string GetLlvmObjcopyPath (string androidBinUtilsDirectory) => GetBinUtilsToolPath (androidBinUtilsDirectory, "llvm-objcopy"); + public static string GetLlvmMcPath (string androidBinUtilsDirectory) => GetBinUtilsToolPath (androidBinUtilsDirectory, "llvm-mc"); + + static string GetBinUtilsToolPath (string androidBinUtilsDirectory, string toolName) { - return Path.Combine (androidBinUtilsDirectory, MonoAndroidHelper.GetExecutablePath (androidBinUtilsDirectory, "llvm-objcopy")); + return Path.Combine (androidBinUtilsDirectory, MonoAndroidHelper.GetExecutablePath (androidBinUtilsDirectory, toolName)); } } } diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets index b1a1c14e7c0..bd4487759e1 100644 --- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets +++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets @@ -1869,6 +1869,7 @@ because xbuild doesn't support framework reference assemblies. <_GeneratePackageManagerJavaInputs Include="@(_GenerateJavaStubsInputs)" /> + <_GeneratePackageManagerJavaInputs Include="$(_BinaryRuntimeConfigPath)" /> @@ -1910,6 +1911,7 @@ because xbuild doesn't support framework reference assemblies. CustomBundleConfigFile="$(AndroidBundleConfigurationFile)" AndroidBinUtilsDirectory="$(AndroidBinUtilsDirectory)" > + + diff --git a/src/native/mono/monodroid/monodroid-glue.cc b/src/native/mono/monodroid/monodroid-glue.cc index d8c722f48f2..7ad85eddf1b 100644 --- a/src/native/mono/monodroid/monodroid-glue.cc +++ b/src/native/mono/monodroid/monodroid-glue.cc @@ -1406,6 +1406,11 @@ MonodroidRuntime::Java_mono_android_Runtime_initInternal (JNIEnv *env, jclass kl Logger::init_logging_categories (mono_log_mask_raw, mono_log_level_raw); + log_warn (LOG_DEFAULT, "Embedded runtime config size: %zu", embedded_runtime_config_size); + if (embedded_runtime_config_size > 0) { + log_warn (LOG_DEFAULT, "First byte of embedded runtime config: 0x%x", embedded_runtime_config[0]); + } + std::unique_ptr mono_log_mask (mono_log_mask_raw); std::unique_ptr mono_log_level (mono_log_level_raw); diff --git a/src/native/mono/xamarin-app-stub/application_dso_stub.cc b/src/native/mono/xamarin-app-stub/application_dso_stub.cc index 0316a55408b..2e3253e7213 100644 --- a/src/native/mono/xamarin-app-stub/application_dso_stub.cc +++ b/src/native/mono/xamarin-app-stub/application_dso_stub.cc @@ -305,3 +305,6 @@ const JniRemappingTypeReplacementEntry jni_remapping_type_replacements[] = { .replacement = "another/replacement/java/type", }, }; + +size_t embedded_runtime_config_size = 0; +uint8_t embedded_runtime_config[0]; diff --git a/src/native/mono/xamarin-app-stub/xamarin-app.hh b/src/native/mono/xamarin-app-stub/xamarin-app.hh index 5b058a99d2d..ab6dc846840 100644 --- a/src/native/mono/xamarin-app-stub/xamarin-app.hh +++ b/src/native/mono/xamarin-app-stub/xamarin-app.hh @@ -394,7 +394,6 @@ MONO_API MONO_API_EXPORT const MarshalMethodName mm_method_names[]; #endif // def RELEASE -using get_function_pointer_fn = void(*)(uint32_t mono_image_index, uint32_t class_index, uint32_t method_token, void*& target_ptr); -MONO_API MONO_API_EXPORT void xamarin_app_init (JNIEnv *env, get_function_pointer_fn fn) noexcept; - +MONO_API MONO_API_EXPORT size_t embedded_runtime_config_size; +MONO_API MONO_API_EXPORT uint8_t embedded_runtime_config[]; #endif // __XAMARIN_ANDROID_TYPEMAP_H From d01e4e1cffd8999a875866dbbf7eaba147d76d7b Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Tue, 8 Oct 2024 11:51:24 +0200 Subject: [PATCH 03/60] Runtime config binary blob is now fully embedded --- .../Utilities/ELFEmbeddingHelper.cs | 6 +++++- .../mono/monodroid/embedded-assemblies-zip.cc | 14 +++++++------- src/native/mono/monodroid/monodroid-glue.cc | 16 ++++++++++------ src/native/mono/runtime-base/android-system.cc | 2 ++ 4 files changed, 24 insertions(+), 14 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/ELFEmbeddingHelper.cs b/src/Xamarin.Android.Build.Tasks/Utilities/ELFEmbeddingHelper.cs index 5195c4b2d17..62da88708c7 100644 --- a/src/Xamarin.Android.Build.Tasks/Utilities/ELFEmbeddingHelper.cs +++ b/src/Xamarin.Android.Build.Tasks/Utilities/ELFEmbeddingHelper.cs @@ -144,9 +144,13 @@ static void DoEmbed ( throw new NotSupportedException ($"Internal error: unsupported target arch '{arch}'"); } + inputFile = Path.GetFullPath (inputFile); + outputFile = Path.GetFullPath (outputFile); + var fi = new FileInfo (inputFile); long inputFileSize = fi.Length; string asmInputFile = Path.ChangeExtension (outputFile, ".s"); + string sanitizedInputFilePath = inputFile.Replace ("\\", "\\\\"); using var fs = File.Open (asmInputFile, FileMode.Create, FileAccess.Write, FileShare.Read); using var sw = new StreamWriter (fs, asmFileEncoding); @@ -158,7 +162,7 @@ static void DoEmbed ( sw.WriteLine ($".global {symbolName}"); sw.WriteLine ($".type {symbolName},{cfg.AssemblerDirectivePrefix}object"); sw.WriteLine ($"{symbolName}:"); - sw.WriteLine ($"\t.incbin \"{inputFile}\""); + sw.WriteLine ($"\t.incbin \"{sanitizedInputFilePath}\""); sw.WriteLine ($"\t.size {symbolName}, {inputFileSize}"); sw.WriteLine (); diff --git a/src/native/mono/monodroid/embedded-assemblies-zip.cc b/src/native/mono/monodroid/embedded-assemblies-zip.cc index 95c36da3f3c..1894a0e83d1 100644 --- a/src/native/mono/monodroid/embedded-assemblies-zip.cc +++ b/src/native/mono/monodroid/embedded-assemblies-zip.cc @@ -62,13 +62,13 @@ EmbeddedAssemblies::zip_load_entry_common (size_t entry_index, std::vector 0) { + size_t blob_time_index; if (FastTiming::enabled ()) [[unlikely]] { internal_timing.start_event (TimingEventKind::RuntimeConfigBlob); } runtime_config_args.kind = 1; - EmbeddedAssemblies::get_runtime_config_blob (runtime_config_args.runtimeconfig.data.data, runtime_config_args.runtimeconfig.data.data_len); +// embeddedAssemblies.get_runtime_config_blob (runtime_config_args.runtimeconfig.data.data, runtime_config_args.runtimeconfig.data.data_len); + runtime_config_args.runtimeconfig.data.data = reinterpret_cast(embedded_runtime_config); + runtime_config_args.runtimeconfig.data.data_len = static_cast(embedded_runtime_config_size); monovm_runtimeconfig_initialize (&runtime_config_args, cleanup_runtime_config, nullptr); if (FastTiming::enabled ()) [[unlikely]] { @@ -1406,10 +1410,10 @@ MonodroidRuntime::Java_mono_android_Runtime_initInternal (JNIEnv *env, jclass kl Logger::init_logging_categories (mono_log_mask_raw, mono_log_level_raw); - log_warn (LOG_DEFAULT, "Embedded runtime config size: %zu", embedded_runtime_config_size); - if (embedded_runtime_config_size > 0) { - log_warn (LOG_DEFAULT, "First byte of embedded runtime config: 0x%x", embedded_runtime_config[0]); - } + // log_warn (LOG_DEFAULT, "Embedded runtime config size: %zu", embedded_runtime_config_size); + // if (embedded_runtime_config_size > 0) { + // log_warn (LOG_DEFAULT, "First byte of embedded runtime config: 0x%x", embedded_runtime_config[0]); + // } std::unique_ptr mono_log_mask (mono_log_mask_raw); std::unique_ptr mono_log_level (mono_log_level_raw); diff --git a/src/native/mono/runtime-base/android-system.cc b/src/native/mono/runtime-base/android-system.cc index 0fcd825bead..e4cbbcec6ce 100644 --- a/src/native/mono/runtime-base/android-system.cc +++ b/src/native/mono/runtime-base/android-system.cc @@ -741,10 +741,12 @@ AndroidSystem::setup_apk_directories (unsigned short running_on_cpu, jstring_arr if (have_split_apks) { if (Util::ends_with (apk, SharedConstants::split_config_abi_apk_name)) { + log_warn (LOG_ASSEMBLY, "Here #1"); add_apk_libdir (apk, number_of_added_directories, abi); break; } } else { + log_warn (LOG_ASSEMBLY, "Here #2"); add_apk_libdir (apk, number_of_added_directories, abi); } } From 514a28ab919aa3ecf15361d1ba69e247614c3a95 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Tue, 8 Oct 2024 17:53:04 +0200 Subject: [PATCH 04/60] Remove debug spam --- src/native/mono/runtime-base/android-system.cc | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/native/mono/runtime-base/android-system.cc b/src/native/mono/runtime-base/android-system.cc index e4cbbcec6ce..0fcd825bead 100644 --- a/src/native/mono/runtime-base/android-system.cc +++ b/src/native/mono/runtime-base/android-system.cc @@ -741,12 +741,10 @@ AndroidSystem::setup_apk_directories (unsigned short running_on_cpu, jstring_arr if (have_split_apks) { if (Util::ends_with (apk, SharedConstants::split_config_abi_apk_name)) { - log_warn (LOG_ASSEMBLY, "Here #1"); add_apk_libdir (apk, number_of_added_directories, abi); break; } } else { - log_warn (LOG_ASSEMBLY, "Here #2"); add_apk_libdir (apk, number_of_added_directories, abi); } } From 0081c367a360e9be6a79cbf57d7f1eeaa582226a Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Wed, 9 Oct 2024 17:23:08 +0200 Subject: [PATCH 05/60] New target to build embedded assembly store --- .../Microsoft.Android.Sdk.After.targets | 1 + ...crosoft.Android.Sdk.AssemblyStores.targets | 31 +++++++++++++++++++ .../Tasks/CreateEmbeddedAssemblyStore.cs | 14 +++++++++ 3 files changed, 46 insertions(+) create mode 100644 src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.AssemblyStores.targets create mode 100644 src/Xamarin.Android.Build.Tasks/Tasks/CreateEmbeddedAssemblyStore.cs diff --git a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.After.targets b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.After.targets index 8a64f834b80..c01bf0248cd 100644 --- a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.After.targets +++ b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.After.targets @@ -29,4 +29,5 @@ This file is imported *after* the Microsoft.NET.Sdk/Sdk.targets. + diff --git a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.AssemblyStores.targets b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.AssemblyStores.targets new file mode 100644 index 00000000000..afa905adcac --- /dev/null +++ b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.AssemblyStores.targets @@ -0,0 +1,31 @@ + + + + + + + + <_EmbeddedAssemblyStoreObjectFile Include="$(_NativeAssemblySourceDir)embed_assembly_store.%(_BuildTargetAbis.Identity).o" /> + + + + + + + + + + + + + + + diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/CreateEmbeddedAssemblyStore.cs b/src/Xamarin.Android.Build.Tasks/Tasks/CreateEmbeddedAssemblyStore.cs new file mode 100644 index 00000000000..d68e6d386f5 --- /dev/null +++ b/src/Xamarin.Android.Build.Tasks/Tasks/CreateEmbeddedAssemblyStore.cs @@ -0,0 +1,14 @@ +using Xamarin.Android.Tools; +using Microsoft.Android.Build.Tasks; + +namespace Xamarin.Android.Tasks; + +public class CreateEmbeddedAssemblyStore : AndroidTask +{ + public override string TaskPrefix => "CEAS"; + + public override bool RunTask () + { + return !Log.HasLoggedErrors; + } +} From 5d91471a42906afc51562b29d2e0122661e2df21 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Wed, 9 Oct 2024 17:24:11 +0200 Subject: [PATCH 06/60] New task to build embedded assembly store --- .../Tasks/CreateEmbeddedAssemblyStore.cs | 22 ++++++++++++++++++- .../Utilities/ELFEmbeddingHelper.cs | 1 + .../Xamarin.Android.Common.targets | 6 ++--- 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/CreateEmbeddedAssemblyStore.cs b/src/Xamarin.Android.Build.Tasks/Tasks/CreateEmbeddedAssemblyStore.cs index d68e6d386f5..357575e5fdd 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/CreateEmbeddedAssemblyStore.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/CreateEmbeddedAssemblyStore.cs @@ -1,5 +1,7 @@ -using Xamarin.Android.Tools; + using Microsoft.Android.Build.Tasks; +using Microsoft.Build.Framework; +using Xamarin.Android.Tools; namespace Xamarin.Android.Tasks; @@ -7,6 +9,24 @@ public class CreateEmbeddedAssemblyStore : AndroidTask { public override string TaskPrefix => "CEAS"; + [Required] + public string AndroidBinUtilsDirectory { get; set; } + + [Required] + public string AppSharedLibrariesDir { get; set; } + + [Required] + public ITaskItem[] ResolvedUserAssemblies { get; set; } + + [Required] + public ITaskItem[] ResolvedFrameworkAssemblies { get; set; } + + [Output] + public ITaskItem[] NativeAssemblySources { get; set; } + + [Output] + public ITaskItem[] EmbeddedObjectFiles { get; set; } + public override bool RunTask () { return !Log.HasLoggedErrors; diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/ELFEmbeddingHelper.cs b/src/Xamarin.Android.Build.Tasks/Utilities/ELFEmbeddingHelper.cs index 62da88708c7..56f399913f2 100644 --- a/src/Xamarin.Android.Build.Tasks/Utilities/ELFEmbeddingHelper.cs +++ b/src/Xamarin.Android.Build.Tasks/Utilities/ELFEmbeddingHelper.cs @@ -26,6 +26,7 @@ public EmbedItem (string symbolName, string baseFileName) public static class KnownEmbedItems { public static readonly EmbedItem RuntimeConfig = new ("embedded_runtime_config", "runtime_config"); + public static readonly EmbedItem AssemblyStore = new ("embedded_assembly_store", "assembly_store"); } sealed class LlvmMcTargetConfig diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets index bd4487759e1..6e7c3fd2cc1 100644 --- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets +++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets @@ -362,9 +362,7 @@ Copyright (C) 2011-2012 Xamarin. All rights reserved. <_AndroidUseMarshalMethods Condition=" '$(AndroidIncludeDebugSymbols)' == 'True' ">False <_AndroidUseMarshalMethods Condition=" '$(AndroidIncludeDebugSymbols)' != 'True' ">$(AndroidEnableMarshalMethods) - - <_AndroidUseManagedMarshalMethodsLookup Condition=" '$(_AndroidUseManagedMarshalMethodsLookup)' == '' and '$(_AndroidUseMarshalMethods)' == 'True' and '$(_AndroidRuntime)' != 'MonoVM' ">True - <_AndroidUseManagedMarshalMethodsLookup Condition=" '$(_AndroidUseManagedMarshalMethodsLookup)' == '' ">False + <_AndroidEmbedAssemblyStoreInRuntime Condition=" '$(AndroidUseAssemblyStore)' == 'True' And '$(_AndroidEmbedAssemblyStoreInRuntime)' == '' ">True @@ -2199,7 +2197,7 @@ because xbuild doesn't support framework reference assemblies. Date: Wed, 9 Oct 2024 18:03:38 +0200 Subject: [PATCH 07/60] Move some of assembly packaging code to a helper class --- .../Utilities/AssemblyPackagingHelper.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/AssemblyPackagingHelper.cs b/src/Xamarin.Android.Build.Tasks/Utilities/AssemblyPackagingHelper.cs index 1599a8e581e..ca9bd62ea33 100644 --- a/src/Xamarin.Android.Build.Tasks/Utilities/AssemblyPackagingHelper.cs +++ b/src/Xamarin.Android.Build.Tasks/Utilities/AssemblyPackagingHelper.cs @@ -10,7 +10,11 @@ namespace Xamarin.Android.Tasks; static class AssemblyPackagingHelper { +<<<<<<< HEAD public static void AddAssembliesFromCollection (TaskLoggingHelper Log, ICollection SupportedAbis, ICollection assemblies, Action doAddAssembly) +======= + public static void AddAssembliesFromCollection (TaskLoggingHelper Log, ICollection SupportedAbis, ICollection assemblies, Action> doAddAssemblies) +>>>>>>> c4d883405 (Move some of assembly packaging code to a helper class) { Dictionary> perArchAssemblies = MonoAndroidHelper.GetPerArchAssemblies ( assemblies, @@ -28,6 +32,7 @@ public static void AddAssembliesFromCollection (TaskLoggingHelper Log, ICollecti foreach (var kvp in perArchAssemblies) { Log.LogDebugMessage ($"Adding assemblies for architecture '{kvp.Key}'"); +<<<<<<< HEAD DoAddAssembliesFromArchCollection (Log, kvp.Key, kvp.Value, doAddAssembly); } } @@ -40,6 +45,9 @@ static void DoAddAssembliesFromArchCollection (TaskLoggingHelper Log, AndroidTar } doAddAssembly (Log, arch, assembly); +======= + doAddAssemblies (kvp.Key, kvp.Value); +>>>>>>> c4d883405 (Move some of assembly packaging code to a helper class) } } } From 297097be1d67a435d024554b6ac61728ac10d499 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Wed, 9 Oct 2024 18:25:26 +0200 Subject: [PATCH 08/60] Move more assembly packaging code to the helper class --- .../Utilities/AssemblyPackagingHelper.cs | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/AssemblyPackagingHelper.cs b/src/Xamarin.Android.Build.Tasks/Utilities/AssemblyPackagingHelper.cs index ca9bd62ea33..1599a8e581e 100644 --- a/src/Xamarin.Android.Build.Tasks/Utilities/AssemblyPackagingHelper.cs +++ b/src/Xamarin.Android.Build.Tasks/Utilities/AssemblyPackagingHelper.cs @@ -10,11 +10,7 @@ namespace Xamarin.Android.Tasks; static class AssemblyPackagingHelper { -<<<<<<< HEAD public static void AddAssembliesFromCollection (TaskLoggingHelper Log, ICollection SupportedAbis, ICollection assemblies, Action doAddAssembly) -======= - public static void AddAssembliesFromCollection (TaskLoggingHelper Log, ICollection SupportedAbis, ICollection assemblies, Action> doAddAssemblies) ->>>>>>> c4d883405 (Move some of assembly packaging code to a helper class) { Dictionary> perArchAssemblies = MonoAndroidHelper.GetPerArchAssemblies ( assemblies, @@ -32,7 +28,6 @@ public static void AddAssembliesFromCollection (TaskLoggingHelper Log, ICollecti foreach (var kvp in perArchAssemblies) { Log.LogDebugMessage ($"Adding assemblies for architecture '{kvp.Key}'"); -<<<<<<< HEAD DoAddAssembliesFromArchCollection (Log, kvp.Key, kvp.Value, doAddAssembly); } } @@ -45,9 +40,6 @@ static void DoAddAssembliesFromArchCollection (TaskLoggingHelper Log, AndroidTar } doAddAssembly (Log, arch, assembly); -======= - doAddAssemblies (kvp.Key, kvp.Value); ->>>>>>> c4d883405 (Move some of assembly packaging code to a helper class) } } } From 45ad89ac7f636c60ed19aac8eddf82a990c8bc92 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Wed, 9 Oct 2024 20:43:18 +0200 Subject: [PATCH 09/60] Almost there, TBC --- ...crosoft.Android.Sdk.AssemblyStores.targets | 7 +- .../Microsoft.Android.Sdk.BuildOrder.targets | 1 - .../Tasks/CreateEmbeddedAssemblyStore.cs | 54 ++++ .../Xamarin.Android.Common.targets | 249 ++++++++++-------- 4 files changed, 193 insertions(+), 118 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.AssemblyStores.targets b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.AssemblyStores.targets index afa905adcac..ba76fad8ce1 100644 --- a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.AssemblyStores.targets +++ b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.AssemblyStores.targets @@ -17,8 +17,13 @@ + ResolvedFrameworkAssemblies="@(_ShrunkFrameworkAssemblies)" + SupportedAbis="@(_BuildTargetAbis)"> diff --git a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.BuildOrder.targets b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.BuildOrder.targets index 17558b8efcd..b3285c44966 100644 --- a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.BuildOrder.targets +++ b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.BuildOrder.targets @@ -62,7 +62,6 @@ properties that determine build ordering. <_PrepareBuildApkDependsOnTargets> _SetLatestTargetFrameworkVersion; _GetLibraryImports; - _RemoveRegisterAttribute; _ResolveAssemblies; _ResolveSatellitePaths; _CreatePackageWorkspace; diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/CreateEmbeddedAssemblyStore.cs b/src/Xamarin.Android.Build.Tasks/Tasks/CreateEmbeddedAssemblyStore.cs index 357575e5fdd..3d272f3b933 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/CreateEmbeddedAssemblyStore.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/CreateEmbeddedAssemblyStore.cs @@ -1,6 +1,9 @@ +using System; +using System.Collections.Generic; using Microsoft.Android.Build.Tasks; using Microsoft.Build.Framework; +using Microsoft.Build.Utilities; using Xamarin.Android.Tools; namespace Xamarin.Android.Tasks; @@ -15,12 +18,27 @@ public class CreateEmbeddedAssemblyStore : AndroidTask [Required] public string AppSharedLibrariesDir { get; set; } + [Required] + public string CompressedAssembliesDir { get; set; } + + [Required] + public bool Debug { get; set; } + + [Required] + public bool EnableCompression { get; set; } + + [Required] + public string ProjectFullPath { get; set; } + [Required] public ITaskItem[] ResolvedUserAssemblies { get; set; } [Required] public ITaskItem[] ResolvedFrameworkAssemblies { get; set; } + [Required] + public string [] SupportedAbis { get; set; } + [Output] public ITaskItem[] NativeAssemblySources { get; set; } @@ -29,6 +47,42 @@ public class CreateEmbeddedAssemblyStore : AndroidTask public override bool RunTask () { + bool compress = !Debug && EnableCompression; + IDictionary>? compressedAssembliesInfo = null; + + if (compress) { + string key = CompressedAssemblyInfo.GetKey (ProjectFullPath); + Log.LogDebugMessage ($"[{TaskPrefix}] Retrieving assembly compression info with key '{key}'"); + compressedAssembliesInfo = BuildEngine4.GetRegisteredTaskObjectAssemblyLocal>> (key, RegisteredTaskObjectLifetime.Build); + if (compressedAssembliesInfo == null) { + throw new InvalidOperationException ($"Assembly compression info not found for key '{key}'. Compression will not be performed."); + } + } + + var storeBuilder = new AssemblyStoreBuilder (Log); + + // Add user assemblies + AssemblyPackagingHelper.AddAssembliesFromCollection (Log, SupportedAbis, ResolvedUserAssemblies, DoAddAssembliesFromArchCollection); + + // Add framework assemblies + AssemblyPackagingHelper.AddAssembliesFromCollection (Log, SupportedAbis, ResolvedFrameworkAssemblies, DoAddAssembliesFromArchCollection); + return !Log.HasLoggedErrors; + + void DoAddAssembliesFromArchCollection (TaskLoggingHelper log, AndroidTargetArch arch, ITaskItem assembly) + { + string sourcePath = CompressAssembly (assembly); + storeBuilder.AddAssembly (sourcePath, assembly, includeDebugSymbols: Debug); + return; + } + + string CompressAssembly (ITaskItem assembly) + { + if (!compress) { + return assembly.ItemSpec; + } + + return AssemblyCompression.Compress (Log, assembly, compressedAssembliesInfo, CompressedAssembliesDir); + } } } diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets index 6e7c3fd2cc1..9af4d2a1589 100644 --- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets +++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets @@ -311,9 +311,7 @@ Copyright (C) 2011-2012 Xamarin. All rights reserved. <_AndroidFastDeployEnvironmentFiles Condition=" '$(_AndroidFastDeployEnvironmentFiles)' == '' And '$(EmbedAssembliesIntoApk)' == 'False' ">True <_AndroidFastDeployEnvironmentFiles Condition=" '$(_AndroidFastDeployEnvironmentFiles)' == '' ">False - - <_AndroidUseCLR Condition=" '$(_AndroidRuntime)' == 'CoreCLR' ">True - <_AndroidUseCLR Condition=" '$(_AndroidRuntime)' != 'CoreCLR' ">False + <_AndroidCompressedAssembliesDir>$(IntermediateOutputPath)android\lz4 @@ -2067,6 +2065,7 @@ because xbuild doesn't support framework reference assemblies. <_CompileToDalvikDependsOnTargets> _CompileJava; + _RemoveRegisterAttribute; _CreateApplicationSharedLibraries; _GetMonoPlatformJarPath; _GetLibraryImports; @@ -2197,7 +2196,7 @@ because xbuild doesn't support framework reference assemblies. - + CompressedAssembliesDir="$(_AndroidCompressedAssembliesDir)"> + + + - - - - - - - - - - - + IntermediateOutputPath="$(IntermediateOutputPath)"> + CompressedAssembliesDir="$(_AndroidCompressedAssembliesDir)"> + + - - <_ApkOutputPath>$(ApkFileIntermediate) - - - - <_NativeLibraries Include="@(_AndroidNativeLibraryForFastDev)" /> - <_DalvikClasses Include="@(_DexFileForFastDev)" /> - - - - <_ApkOutputPath>$(_BaseZipIntermediate) - <_BundleNativeLibraries>$(_BundleResultNativeLibraries) - - - - <_NativeLibraries Include="@(AndroidNativeLibrary)" /> - <_DalvikClasses Include="@(_DexFile)" /> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + CompressedAssembliesDir="$(_AndroidCompressedAssembliesDir)"> + + + + CompressedAssembliesDir="$(_AndroidCompressedAssembliesDir)"> + + + Date: Thu, 10 Oct 2024 11:33:07 +0200 Subject: [PATCH 10/60] Assembly store embedding works --- ...crosoft.Android.Sdk.AssemblyStores.targets | 1 + .../Tasks/CreateEmbeddedAssemblyStore.cs | 37 +++++++++++++++++++ .../Utilities/AssemblyStoreGenerator.cs | 5 ++- 3 files changed, 41 insertions(+), 2 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.AssemblyStores.targets b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.AssemblyStores.targets index ba76fad8ce1..c7185129668 100644 --- a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.AssemblyStores.targets +++ b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.AssemblyStores.targets @@ -17,6 +17,7 @@ (); + var sourceFiles = new List (); + Dictionary assemblyStorePaths = storeBuilder.Generate (Path.Combine (AppSharedLibrariesDir, "embedded")); + foreach (var kvp in assemblyStorePaths) { + string abi = MonoAndroidHelper.ArchToAbi (kvp.Key); + string inputFile = kvp.Value; + + List items = ELFEmbeddingHelper.EmbedBinary ( + Log, + abi, + AndroidBinUtilsDirectory, + inputFile, + ELFEmbeddingHelper.KnownEmbedItems.AssemblyStore, + AssemblySourcesDir + ); + + if (items.Count == 0) { + continue; + } + + objectFiles.AddRange (items); + foreach (ITaskItem objectItem in items) { + var sourceItem = new TaskItem ( + Path.ChangeExtension (objectItem.ItemSpec, ".s"), + objectItem.CloneCustomMetadata () + ); + sourceFiles.Add (sourceItem); + } + } + + NativeAssemblySources = sourceFiles.ToArray (); + EmbeddedObjectFiles = objectFiles.ToArray (); + return !Log.HasLoggedErrors; void DoAddAssembliesFromArchCollection (TaskLoggingHelper log, AndroidTargetArch arch, ITaskItem assembly) diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/AssemblyStoreGenerator.cs b/src/Xamarin.Android.Build.Tasks/Utilities/AssemblyStoreGenerator.cs index 024f2cf0ac2..f061412a125 100644 --- a/src/Xamarin.Android.Build.Tasks/Utilities/AssemblyStoreGenerator.cs +++ b/src/Xamarin.Android.Build.Tasks/Utilities/AssemblyStoreGenerator.cs @@ -104,7 +104,8 @@ string Generate (string baseOutputDirectory, AndroidTargetArch arch, List (); var descriptors = new List (); ulong namesSize = 0; @@ -118,7 +119,7 @@ string Generate (string baseOutputDirectory, AndroidTargetArch arch, List Date: Thu, 10 Oct 2024 18:05:33 +0200 Subject: [PATCH 11/60] Actually use the embedded assembly store --- .../Xamarin.Android.Common.targets | 4 + .../mono/monodroid/embedded-assemblies-zip.cc | 89 +++++++++++-------- .../mono/monodroid/embedded-assemblies.hh | 14 +-- .../xamarin-app-stub/application_dso_stub.cc | 3 + .../mono/xamarin-app-stub/xamarin-app.hh | 3 + 5 files changed, 69 insertions(+), 44 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets index 9af4d2a1589..1706e4fb6b0 100644 --- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets +++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets @@ -2379,6 +2379,7 @@ because xbuild doesn't support framework reference assemblies. AndroidBinUtilsDirectory="$(AndroidBinUtilsDirectory)" IntermediateOutputPath="$(IntermediateOutputPath)"> CompressedAssembliesDir="$(_AndroidCompressedAssembliesDir)"> + AssemblyStoreEmbeddedInRuntime="$(_AndroidEmbedAssemblyStoreInRuntime)"> CompressedAssembliesDir="$(_AndroidCompressedAssembliesDir)"> + AssemblyStoreEmbeddedInRuntime="$(_AndroidEmbedAssemblyStoreInRuntime)"> CompressedAssembliesDir="$(_AndroidCompressedAssembliesDir)"> + AssemblyStoreEmbeddedInRuntime="$(_AndroidEmbedAssemblyStoreInRuntime)"> CompressedAssembliesDir="$(_AndroidCompressedAssembliesDir)"> + AssemblyStoreEmbeddedInRuntime="$(_AndroidEmbedAssemblyStoreInRuntime)"> c } } + +[[gnu::always_inline]] void +EmbeddedAssemblies::verify_assembly_store_and_set_info (void *data_start, const char *name) noexcept +{ + auto header = static_cast(data_start); + + if (header->magic != ASSEMBLY_STORE_MAGIC) { + Helpers::abort_application ( + LOG_ASSEMBLY, + Util::monodroid_strdup_printf ( + "Assembly store '%s' is not a valid .NET for Android assembly store file", + entry_name.get () + ) + ); + } + + if (header->version != ASSEMBLY_STORE_FORMAT_VERSION) { + Helpers::abort_application ( + LOG_ASSEMBLY, + Util::monodroid_strdup_printf ( + "Assembly store '%s' uses format version 0x%x, instead of the expected 0x%x", + entry_name.get (), + header->version, + ASSEMBLY_STORE_FORMAT_VERSION + ) + ); + } + + constexpr size_t header_size = sizeof(AssemblyStoreHeader); + + assembly_store.data_start = static_cast(data_start); + assembly_store.assembly_count = header->entry_count; + assembly_store.index_entry_count = header->index_entry_count; + assembly_store.assemblies = reinterpret_cast(assembly_store.data_start + header_size + header->index_size); + assembly_store_hashes = reinterpret_cast(assembly_store.data_start + header_size); + + number_of_found_assemblies += assembly_store.assembly_count; + number_of_mapped_assembly_stores++; + have_and_want_debug_symbols = register_debug_symbols; +} + inline void EmbeddedAssemblies::map_assembly_store (dynamic_local_string const& entry_name, ZipEntryLoadState &state) noexcept { @@ -219,42 +260,8 @@ EmbeddedAssemblies::map_assembly_store (dynamic_local_string } auto [payload_start, payload_size] = get_wrapper_dso_payload_pointer_and_size (assembly_store_map, entry_name.get ()); - log_debug (LOG_ASSEMBLY, "Adjusted assembly store pointer: {:p}; size: {}", payload_start, payload_size); - auto header = static_cast(payload_start); - - if (header->magic != ASSEMBLY_STORE_MAGIC) { - Helpers::abort_application ( - LOG_ASSEMBLY, - std::format ( - "Assembly store '{}' is not a valid .NET for Android assembly store file", - optional_string (entry_name.get ()) - ) - ); - } - - if (header->version != ASSEMBLY_STORE_FORMAT_VERSION) { - Helpers::abort_application ( - LOG_ASSEMBLY, - std::format ( - "Assembly store '{}' uses format version {:x}, instead of the expected {:x}", - optional_string (entry_name.get ()), - header->version, - ASSEMBLY_STORE_FORMAT_VERSION - ) - ); - } - - constexpr size_t header_size = sizeof(AssemblyStoreHeader); - - assembly_store.data_start = static_cast(payload_start); - assembly_store.assembly_count = header->entry_count; - assembly_store.index_entry_count = header->index_entry_count; - assembly_store.assemblies = reinterpret_cast(assembly_store.data_start + header_size + header->index_size); - assembly_store_hashes = reinterpret_cast(assembly_store.data_start + header_size); - - number_of_found_assemblies += assembly_store.assembly_count; - number_of_mapped_assembly_stores++; - have_and_want_debug_symbols = register_debug_symbols; + log_debug (LOG_ASSEMBLY, "Adjusted assembly store pointer: %p; size: %zu", payload_start, payload_size); + verify_assembly_store_and_set_info (payload_start, entry_name.get ()); } [[gnu::always_inline]] void @@ -265,9 +272,15 @@ EmbeddedAssemblies::zip_load_assembly_store_entries (std::vector const& } dynamic_local_string entry_name; - bool assembly_store_found = false; + bool assembly_store_found = embedded_assembly_store_size != 0; + if (assembly_store_found) { + log_debug (LOG_ASSEMBLY, "Got embedded assembly store, size %zu", embedded_assembly_store_size); + verify_assembly_store_and_set_info (embedded_assembly_store, "embedded"); + log_debug (LOG_ASSEMBLY, "Looking for DSOs in APK"); + } else { + log_debug (LOG_ASSEMBLY, "Looking for assembly store ('%s') and DSOs in APK", assembly_store_file_path.data ()); + } - log_debug (LOG_ASSEMBLY, "Looking for assembly stores in APK ('{}')", assembly_store_file_path.data ()); for (size_t i = 0uz; i < num_entries; i++) { if (all_required_zip_entries_found ()) { need_to_scan_more_apks = false; diff --git a/src/native/mono/monodroid/embedded-assemblies.hh b/src/native/mono/monodroid/embedded-assemblies.hh index f3447a69840..ed5608e9d2e 100644 --- a/src/native/mono/monodroid/embedded-assemblies.hh +++ b/src/native/mono/monodroid/embedded-assemblies.hh @@ -375,12 +375,14 @@ namespace xamarin::android::internal { static const TypeMapModuleEntry* binary_search (uint32_t key, const TypeMapModuleEntry *arr, uint32_t n) noexcept; #endif template - static void set_entry_data (XamarinAndroidBundledAssembly &entry, ZipEntryLoadState const& state, dynamic_local_string const& entry_name) noexcept; - static void set_assembly_entry_data (XamarinAndroidBundledAssembly &entry, ZipEntryLoadState const& state, dynamic_local_string const& entry_name) noexcept; - static void set_debug_entry_data (XamarinAndroidBundledAssembly &entry, ZipEntryLoadState const& state, dynamic_local_string const& entry_name) noexcept; - static void map_assembly_store (dynamic_local_string const& entry_name, ZipEntryLoadState &state) noexcept; - static const AssemblyStoreIndexEntry* find_assembly_store_entry (hash_t hash, const AssemblyStoreIndexEntry *entries, size_t entry_count) noexcept; - static void store_individual_assembly_data (dynamic_local_string const& entry_name, ZipEntryLoadState const& state, monodroid_should_register should_register) noexcept; + void set_entry_data (XamarinAndroidBundledAssembly &entry, ZipEntryLoadState const& state, dynamic_local_string const& entry_name) noexcept; + void set_assembly_entry_data (XamarinAndroidBundledAssembly &entry, ZipEntryLoadState const& state, dynamic_local_string const& entry_name) noexcept; + void set_debug_entry_data (XamarinAndroidBundledAssembly &entry, ZipEntryLoadState const& state, dynamic_local_string const& entry_name) noexcept; + + void verify_assembly_store_and_set_info (void *data_start, const char *name) noexcept; + void map_assembly_store (dynamic_local_string const& entry_name, ZipEntryLoadState &state) noexcept; + const AssemblyStoreIndexEntry* find_assembly_store_entry (hash_t hash, const AssemblyStoreIndexEntry *entries, size_t entry_count) noexcept; + void store_individual_assembly_data (dynamic_local_string const& entry_name, ZipEntryLoadState const& state, monodroid_should_register should_register) noexcept; constexpr static size_t get_mangled_name_max_size_overhead () { diff --git a/src/native/mono/xamarin-app-stub/application_dso_stub.cc b/src/native/mono/xamarin-app-stub/application_dso_stub.cc index 2e3253e7213..49588a88e38 100644 --- a/src/native/mono/xamarin-app-stub/application_dso_stub.cc +++ b/src/native/mono/xamarin-app-stub/application_dso_stub.cc @@ -308,3 +308,6 @@ const JniRemappingTypeReplacementEntry jni_remapping_type_replacements[] = { size_t embedded_runtime_config_size = 0; uint8_t embedded_runtime_config[0]; + +size_t embedded_assembly_store_size = 0; +uint8_t embedded_assembly_store[0]; diff --git a/src/native/mono/xamarin-app-stub/xamarin-app.hh b/src/native/mono/xamarin-app-stub/xamarin-app.hh index ab6dc846840..3e89c184057 100644 --- a/src/native/mono/xamarin-app-stub/xamarin-app.hh +++ b/src/native/mono/xamarin-app-stub/xamarin-app.hh @@ -396,4 +396,7 @@ MONO_API MONO_API_EXPORT const MarshalMethodName mm_method_names[]; MONO_API MONO_API_EXPORT size_t embedded_runtime_config_size; MONO_API MONO_API_EXPORT uint8_t embedded_runtime_config[]; + +MONO_API MONO_API_EXPORT size_t embedded_assembly_store_size; +MONO_API MONO_API_EXPORT uint8_t embedded_assembly_store[]; #endif // __XAMARIN_ANDROID_TYPEMAP_H From 12afaf79bb159cc834e9333debd261ba5cbb9328 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Thu, 10 Oct 2024 22:28:02 +0200 Subject: [PATCH 12/60] A handful of bugfixes and performance tweaks --- .../Tasks/GeneratePackageManagerJava.cs | 4 ++++ ...pplicationConfigNativeAssemblyGenerator.cs | 19 +++++++++++++++++++ .../Xamarin.Android.Common.targets | 2 ++ src/native/mono/monodroid/monodroid-glue.cc | 4 ++-- .../mono/runtime-base/android-system.cc | 18 +++--------------- src/native/mono/runtime-base/util.cc | 8 ++++---- src/native/mono/runtime-base/util.hh | 2 +- 7 files changed, 35 insertions(+), 22 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/GeneratePackageManagerJava.cs b/src/Xamarin.Android.Build.Tasks/Tasks/GeneratePackageManagerJava.cs index 53225aa1557..0596d932246 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/GeneratePackageManagerJava.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/GeneratePackageManagerJava.cs @@ -65,6 +65,9 @@ public override bool RunTask () [Required] public string AndroidBinUtilsDirectory { get; set; } + [Required] + public bool AssemblyStoreEmbeddedInRuntime { get; set; } + [Output] public ITaskItem[] EmbeddedObjectFiles { get; set; } @@ -331,6 +334,7 @@ void AddEnvironment () JniRemappingReplacementMethodIndexEntryCount = jniRemappingNativeCodeInfo == null ? 0 : jniRemappingNativeCodeInfo.ReplacementMethodIndexEntryCount, MarshalMethodsEnabled = EnableMarshalMethods, IgnoreSplitConfigs = ShouldIgnoreSplitConfigs (), + AssemblyStoreEmbeddedInRuntime = UseAssemblyStore && AssemblyStoreEmbeddedInRuntime, }; LLVMIR.LlvmIrModule appConfigModule = appConfigAsmGen.Construct (); diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/ApplicationConfigNativeAssemblyGenerator.cs b/src/Xamarin.Android.Build.Tasks/Utilities/ApplicationConfigNativeAssemblyGenerator.cs index 5844b9fb427..d4349ed1661 100644 --- a/src/Xamarin.Android.Build.Tasks/Utilities/ApplicationConfigNativeAssemblyGenerator.cs +++ b/src/Xamarin.Android.Build.Tasks/Utilities/ApplicationConfigNativeAssemblyGenerator.cs @@ -197,6 +197,7 @@ sealed class XamarinAndroidBundledAssembly public bool MarshalMethodsEnabled { get; set; } public bool ManagedMarshalMethodsLookupEnabled { get; set; } public bool IgnoreSplitConfigs { get; set; } + public bool AssemblyStoreEmbeddedInRuntime { get; set; } public ApplicationConfigNativeAssemblyGenerator (IDictionary environmentVariables, IDictionary systemProperties, TaskLoggingHelper log) : base (log) @@ -306,6 +307,24 @@ protected override void Construct (LlvmIrModule module) module.Add (bundled_assemblies); AddAssemblyStores (module); + + if (AssemblyStoreEmbeddedInRuntime) { + return; + } + + // Need these to keep ABI compatibility with `libxamarin-app.so` used at the runtime's build time + var embedded_assembly_store_size = new LlvmIrGlobalVariable ( + (ulong)0, + "embedded_assembly_store_size", + LlvmIrVariableOptions.GlobalConstant + ); + module.Add (embedded_assembly_store_size); + + var embedded_assembly_store = new LlvmIrGlobalVariable (typeof (byte[]), "embedded_assembly_store", LlvmIrVariableOptions.GlobalWritable) { + ZeroInitializeArray = true, + ArrayItemCount = 0, + }; + module.Add (embedded_assembly_store); } void AddAssemblyStores (LlvmIrModule module) diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets index 1706e4fb6b0..bd921b66859 100644 --- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets +++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets @@ -361,6 +361,7 @@ Copyright (C) 2011-2012 Xamarin. All rights reserved. <_AndroidUseMarshalMethods Condition=" '$(AndroidIncludeDebugSymbols)' == 'True' ">False <_AndroidUseMarshalMethods Condition=" '$(AndroidIncludeDebugSymbols)' != 'True' ">$(AndroidEnableMarshalMethods) <_AndroidEmbedAssemblyStoreInRuntime Condition=" '$(AndroidUseAssemblyStore)' == 'True' And '$(_AndroidEmbedAssemblyStoreInRuntime)' == '' ">True + <_AndroidEmbedAssemblyStoreInRuntime Condition="'$(_AndroidEmbedAssemblyStoreInRuntime)' == '' ">False @@ -1906,6 +1907,7 @@ because xbuild doesn't support framework reference assemblies. EnableMarshalMethods="$(_AndroidUseMarshalMethods)" CustomBundleConfigFile="$(AndroidBundleConfigurationFile)" AndroidBinUtilsDirectory="$(AndroidBinUtilsDirectory)" + AssemblyStoreEmbeddedInRuntime="$(_AndroidEmbedAssemblyStoreInRuntime)" > diff --git a/src/native/mono/monodroid/monodroid-glue.cc b/src/native/mono/monodroid/monodroid-glue.cc index 425edd15d56..727681bf268 100644 --- a/src/native/mono/monodroid/monodroid-glue.cc +++ b/src/native/mono/monodroid/monodroid-glue.cc @@ -1159,8 +1159,8 @@ MonodroidRuntime::set_profile_options () noexcept .append (OUTPUT_ARG) .append (output_path.get (), output_path.length ()); } - if (Util::create_directory (AndroidSystem::override_dirs[0], 0) < 0) { - log_warn (LOG_DEFAULT, "Failed to create directory '{}'. {}", optional_string (AndroidSystem::override_dirs[0]), std::strerror (errno)); + if (Util::create_directory (AndroidSystem::override_dirs[0], 0777, 000) < 0) { + log_warn (LOG_DEFAULT, "Failed to create directory '%s'. %s", AndroidSystem::override_dirs[0], std::strerror (errno)); } log_warn (LOG_DEFAULT, "Initializing profiler with options: {}", optional_string (value.get ())); diff --git a/src/native/mono/runtime-base/android-system.cc b/src/native/mono/runtime-base/android-system.cc index 0fcd825bead..62c358f3816 100644 --- a/src/native/mono/runtime-base/android-system.cc +++ b/src/native/mono/runtime-base/android-system.cc @@ -262,26 +262,14 @@ AndroidSystem::monodroid_get_system_property_from_overrides ([[maybe_unused]] co return 0; } -// TODO: review this. Do we really have to create the dir in release? void AndroidSystem::create_update_dir (char *override_dir) noexcept { -#if defined (RELEASE) - /* - * Don't create .__override__ on Release builds, because Google requires - * that pre-loaded apps not create world-writable directories. - * - * However, if any logging is enabled (which should _not_ happen with - * pre-loaded apps!), we need the .__override__ directory... - */ - if (log_categories == 0 && monodroid_get_system_property (SharedConstants::DEBUG_MONO_PROFILE_PROPERTY, nullptr) == 0) { - return; - } -#endif // def RELEASE - override_dirs [0] = override_dir; +#if defined(DEBUG) + log_debug (LOG_DEFAULT, "Creating public update directory: `%s`", override_dir); Util::create_public_directory (override_dir); - log_warn (LOG_DEFAULT, "Creating public update directory: `{}`", override_dir); +#endif } bool diff --git a/src/native/mono/runtime-base/util.cc b/src/native/mono/runtime-base/util.cc index fda41ecfd88..b017af23220 100644 --- a/src/native/mono/runtime-base/util.cc +++ b/src/native/mono/runtime-base/util.cc @@ -147,14 +147,14 @@ Util::path_combine (const char *path1, const char *path2) void Util::create_public_directory (const char *dir) { - int ret = create_directory (dir, 0777); + int ret = create_directory (dir, 0777, 0); if (ret < 0) { - log_warn (LOG_DEFAULT, "Failed to create directory '{}'. {}", dir, std::strerror (errno)); + log_warn (LOG_DEFAULT, "Failed to create public directory '%s'. %s", dir, std::strerror (errno)); } } int -Util::create_directory (const char *pathname, mode_t mode) +Util::create_directory (const char *pathname, mode_t mode, mode_t mask) { if (mode <= 0) mode = DEFAULT_DIRECTORY_MODE; @@ -163,7 +163,7 @@ Util::create_directory (const char *pathname, mode_t mode) errno = EINVAL; return -1; } - mode_t oldumask = umask (022); + mode_t oldumask = umask (mask); std::unique_ptr path {strdup_new (pathname)}; int rv, ret = 0; for (char *d = path.get (); d != nullptr && *d; ++d) { diff --git a/src/native/mono/runtime-base/util.hh b/src/native/mono/runtime-base/util.hh index a43009478ae..3bfd897658f 100644 --- a/src/native/mono/runtime-base/util.hh +++ b/src/native/mono/runtime-base/util.hh @@ -69,7 +69,7 @@ namespace xamarin::android static char *monodroid_strdup_vprintf (const char *format, va_list vargs); static char* path_combine (const char *path1, const char *path2); static void create_public_directory (const char *dir); - static int create_directory (const char *pathname, mode_t mode); + static int create_directory (const char *pathname, mode_t mode, mode_t mask = 022); static void set_world_accessable (const char *path); static auto set_world_accessible (int fd) noexcept -> bool; static void set_user_executable (const char *path); From 15a5bf444da285ffa26e778078740d6ee874cd78 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Fri, 11 Oct 2024 11:42:08 +0200 Subject: [PATCH 13/60] Fix DSO count when building Also, runtime config blob will no longer be packaged in the APK, stop checking whether it was found. --- .../Tasks/GeneratePackageManagerJava.cs | 31 +++++++++++++++++-- ...pplicationConfigNativeAssemblyGenerator.cs | 3 +- .../mono/monodroid/embedded-assemblies.hh | 17 +++++----- 3 files changed, 38 insertions(+), 13 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/GeneratePackageManagerJava.cs b/src/Xamarin.Android.Build.Tasks/Tasks/GeneratePackageManagerJava.cs index 0596d932246..20c501d58ac 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/GeneratePackageManagerJava.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/GeneratePackageManagerJava.cs @@ -285,10 +285,34 @@ void AddEnvironment () // pkgmgr.WriteLine ("\t\t\"" + Path.GetFileName (assembly) + "\","); //} - pkgmgr.WriteLine ("\t};"); + var uniqueNativeLibraries = new List (); + + // Number of DSOs that will be packaged, it may be different to the number of items in the above + // `uniqueNativeLibraries` list. + uint packagedNativeLibrariesCount = 0; + var seenNativeLibraryNames = new HashSet (StringComparer.OrdinalIgnoreCase); + if (NativeLibraries != null) { + foreach (ITaskItem item in NativeLibraries) { + // We don't care about different ABIs here, just the file name + string name = Path.GetFileName (item.ItemSpec); + if (seenNativeLibraryNames.Contains (name)) { + continue; + } - pkgmgr.WriteLine ("}"); - pkgmgr.Flush (); + if (!ELFHelper.IsEmptyAOTLibrary (Log, item.ItemSpec)) { + packagedNativeLibrariesCount++; + } + + seenNativeLibraryNames.Add (name); + uniqueNativeLibraries.Add (item); + } + + // libxamarin-app.so is not in NativeLibraries, but we must count it + if (!seenNativeLibraryNames.Contains ("libxamarin-app.so")) { + uniqueNativeLibraries.Add (new TaskItem ("libxamarin-app.so")); + packagedNativeLibrariesCount++; + } + } // Only copy to the real location if the contents actually changed var dest = Path.GetFullPath (Path.Combine (OutputDirectory, "MonoPackageManager_Resources.java")); @@ -326,6 +350,7 @@ void AddEnvironment () BundledAssemblyNameWidth = assemblyNameWidth, MonoComponents = (MonoComponent)monoComponents, NativeLibraries = uniqueNativeLibraries, + PackagedNativeLibrariesCount = packagedNativeLibrariesCount, HaveAssemblyStore = UseAssemblyStore, AndroidRuntimeJNIEnvToken = android_runtime_jnienv_class_token, JNIEnvInitializeToken = jnienv_initialize_method_token, diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/ApplicationConfigNativeAssemblyGenerator.cs b/src/Xamarin.Android.Build.Tasks/Utilities/ApplicationConfigNativeAssemblyGenerator.cs index d4349ed1661..097f84dea99 100644 --- a/src/Xamarin.Android.Build.Tasks/Utilities/ApplicationConfigNativeAssemblyGenerator.cs +++ b/src/Xamarin.Android.Build.Tasks/Utilities/ApplicationConfigNativeAssemblyGenerator.cs @@ -194,6 +194,7 @@ sealed class XamarinAndroidBundledAssembly public MonoComponent MonoComponents { get; set; } public PackageNamingPolicy PackageNamingPolicy { get; set; } public List NativeLibraries { get; set; } + public uint PackagedNativeLibrariesCount { get; set; } public bool MarshalMethodsEnabled { get; set; } public bool ManagedMarshalMethodsLookupEnabled { get; set; } public bool IgnoreSplitConfigs { get; set; } @@ -248,7 +249,7 @@ protected override void Construct (LlvmIrModule module) environment_variable_count = (uint)(environmentVariables == null ? 0 : environmentVariables.Count * 2), system_property_count = (uint)(systemProperties == null ? 0 : systemProperties.Count * 2), number_of_assemblies_in_apk = (uint)NumberOfAssembliesInApk, - number_of_shared_libraries = (uint)NativeLibraries.Count, + number_of_shared_libraries = PackagedNativeLibrariesCount, bundled_assembly_name_width = (uint)BundledAssemblyNameWidth, number_of_dso_cache_entries = (uint)dsoCache.Count, number_of_aot_cache_entries = (uint)aotDsoCache.Count, diff --git a/src/native/mono/monodroid/embedded-assemblies.hh b/src/native/mono/monodroid/embedded-assemblies.hh index ed5608e9d2e..a58835f6fb7 100644 --- a/src/native/mono/monodroid/embedded-assemblies.hh +++ b/src/native/mono/monodroid/embedded-assemblies.hh @@ -351,8 +351,7 @@ namespace xamarin::android::internal { static bool all_required_zip_entries_found () noexcept { return - number_of_mapped_assembly_stores == number_of_assembly_store_files && number_of_zip_dso_entries >= application_config.number_of_shared_libraries - && ((application_config.have_runtime_config_blob && runtime_config_blob_found) || !application_config.have_runtime_config_blob); + number_of_mapped_assembly_stores == number_of_assembly_store_files && number_of_zip_dso_entries >= application_config.number_of_shared_libraries; } [[gnu::always_inline]] static c_unique_ptr to_utf8 (const MonoString *s) noexcept @@ -461,13 +460,13 @@ namespace xamarin::android::internal { #endif // DEBUG static inline const char *assemblies_prefix_override = nullptr; - static inline md_mmap_info runtime_config_blob_mmap{}; - static inline void *runtime_config_data = nullptr; - static inline size_t runtime_config_data_size = 0uz; - static inline bool runtime_config_blob_found = false; - static inline uint32_t number_of_mapped_assembly_stores = 0u; - static inline uint32_t number_of_zip_dso_entries = 0u; - static inline bool need_to_scan_more_apks = true; + md_mmap_info runtime_config_blob_mmap{}; + void *runtime_config_data = nullptr; + size_t runtime_config_data_size = 0uz; + bool runtime_config_blob_found = embedded_runtime_config_size > 0u; + uint32_t number_of_mapped_assembly_stores = 0u; + uint32_t number_of_zip_dso_entries = 0u; + bool need_to_scan_more_apks = true; static inline AssemblyStoreIndexEntry *assembly_store_hashes = nullptr; static inline xamarin::android::mutex assembly_decompress_mutex {}; From 9391224699f7085312efd3b2c70a82d4665f2e65 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Fri, 11 Oct 2024 12:14:24 +0200 Subject: [PATCH 14/60] Don't allocate memory for ZIP Central Directory data Instead use `mmap` --- .../mono/monodroid/embedded-assemblies-zip.cc | 56 ++++++++++--------- .../mono/monodroid/embedded-assemblies.hh | 15 ++--- 2 files changed, 38 insertions(+), 33 deletions(-) diff --git a/src/native/mono/monodroid/embedded-assemblies-zip.cc b/src/native/mono/monodroid/embedded-assemblies-zip.cc index c7236d4edbb..ac69313bf23 100644 --- a/src/native/mono/monodroid/embedded-assemblies-zip.cc +++ b/src/native/mono/monodroid/embedded-assemblies-zip.cc @@ -15,8 +15,8 @@ using namespace xamarin::android::internal; -[[gnu::always_inline]] bool -EmbeddedAssemblies::zip_load_entry_common (size_t entry_index, std::vector const& buf, dynamic_local_string &entry_name, ZipEntryLoadState &state) noexcept +force_inline bool +EmbeddedAssemblies::zip_load_entry_common (size_t entry_index, std::span const& buf, dynamic_local_string &entry_name, ZipEntryLoadState &state) noexcept { entry_name.clear (); @@ -150,8 +150,8 @@ EmbeddedAssemblies::store_individual_assembly_data (dynamic_local_string const& buf, uint32_t num_entries, [[maybe_unused]] monodroid_should_register should_register, ZipEntryLoadState &state) noexcept +force_inline void +EmbeddedAssemblies::zip_load_individual_assembly_entries (std::span const& buf, uint32_t num_entries, [[maybe_unused]] monodroid_should_register should_register, ZipEntryLoadState &state) noexcept { // TODO: do away with all the string manipulation here. Replace it with generating xxhash for the entry name dynamic_local_string entry_name; @@ -264,8 +264,8 @@ EmbeddedAssemblies::map_assembly_store (dynamic_local_string verify_assembly_store_and_set_info (payload_start, entry_name.get ()); } -[[gnu::always_inline]] void -EmbeddedAssemblies::zip_load_assembly_store_entries (std::vector const& buf, uint32_t num_entries, ZipEntryLoadState &state) noexcept +force_inline void +EmbeddedAssemblies::zip_load_assembly_store_entries (std::span const& buf, uint32_t num_entries, ZipEntryLoadState &state) noexcept { if (all_required_zip_entries_found ()) { return; @@ -344,26 +344,28 @@ EmbeddedAssemblies::zip_load_entries (int fd, const char *apk_name, [[maybe_unus ) ); } -#ifdef DEBUG - log_info (LOG_ASSEMBLY, "Central directory offset: {}", cd_offset); - log_info (LOG_ASSEMBLY, "Central directory size: {}", cd_size); - log_info (LOG_ASSEMBLY, "Central directory entries: {}", cd_entries); -#endif - off_t retval = ::lseek (fd, static_cast(cd_offset), SEEK_SET); - if (retval < 0) { - Helpers::abort_application ( - LOG_ASSEMBLY, - std::format ( - "Failed to seek to central directory position in APK: {}. retval={} errno={}, File={}", - std::strerror (errno), - retval, - errno, - optional_string (apk_name) - ) - ); - } - std::vector buf (cd_size); + md_mmap_info apk_map = md_mmap_apk_file (fd, cd_offset, cd_size, apk_name); + + log_debug (LOG_ASSEMBLY, "Central directory offset: %u", cd_offset); + log_debug (LOG_ASSEMBLY, "Central directory size: %u", cd_size); + log_debug (LOG_ASSEMBLY, "Central directory entries: %u", cd_entries); + + // off_t retval = ::lseek (fd, static_cast(cd_offset), SEEK_SET); + // if (retval < 0) { + // Helpers::abort_application ( + // LOG_ASSEMBLY, + // Util::monodroid_strdup_printf ( + // "Failed to seek to central directory position in APK: %s. retval=%d errno=%d, File=%s", + // std::strerror (errno), + // retval, + // errno, + // apk_name + // ) + // ); + // } + + std::span buf (reinterpret_cast(apk_map.area), apk_map.size); const auto [prefix, prefix_len] = get_assemblies_prefix_and_length (); ZipEntryLoadState state { .file_fd = fd, @@ -399,6 +401,8 @@ EmbeddedAssemblies::zip_load_entries (int fd, const char *apk_name, [[maybe_unus } else { zip_load_individual_assembly_entries (buf, cd_entries, should_register, state); } + + // TODO: unmap here } template @@ -660,7 +664,7 @@ EmbeddedAssemblies::zip_read_field (T const& buf, size_t index, size_t count, dy } bool -EmbeddedAssemblies::zip_read_entry_info (std::vector const& buf, dynamic_local_string& file_name, ZipEntryLoadState &state) noexcept +EmbeddedAssemblies::zip_read_entry_info (std::span const& buf, dynamic_local_string& file_name, ZipEntryLoadState &state) { constexpr size_t CD_COMPRESSION_METHOD_OFFSET = 10uz; constexpr size_t CD_UNCOMPRESSED_SIZE_OFFSET = 24uz; diff --git a/src/native/mono/monodroid/embedded-assemblies.hh b/src/native/mono/monodroid/embedded-assemblies.hh index a58835f6fb7..635f7b973ef 100644 --- a/src/native/mono/monodroid/embedded-assemblies.hh +++ b/src/native/mono/monodroid/embedded-assemblies.hh @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -267,12 +268,12 @@ namespace xamarin::android::internal { static void get_assembly_data (XamarinAndroidBundledAssembly const& e, uint8_t*& assembly_data, uint32_t& assembly_data_size) noexcept; static void get_assembly_data (AssemblyStoreSingleAssemblyRuntimeData const& e, uint8_t*& assembly_data, uint32_t& assembly_data_size) noexcept; - static void zip_load_entries (int fd, const char *apk_name, monodroid_should_register should_register) noexcept; - static void zip_load_individual_assembly_entries (std::vector const& buf, uint32_t num_entries, monodroid_should_register should_register, ZipEntryLoadState &state) noexcept; - static void zip_load_assembly_store_entries (std::vector const& buf, uint32_t num_entries, ZipEntryLoadState &state) noexcept; - static bool zip_load_entry_common (size_t entry_index, std::vector const& buf, dynamic_local_string &entry_name, ZipEntryLoadState &state) noexcept; - static bool zip_read_cd_info (int fd, uint32_t& cd_offset, uint32_t& cd_size, uint16_t& cd_entries) noexcept; - static bool zip_adjust_data_offset (int fd, ZipEntryLoadState &state) noexcept; + void zip_load_entries (int fd, const char *apk_name, monodroid_should_register should_register); + void zip_load_individual_assembly_entries (std::span const& buf, uint32_t num_entries, monodroid_should_register should_register, ZipEntryLoadState &state) noexcept; + void zip_load_assembly_store_entries (std::span const& buf, uint32_t num_entries, ZipEntryLoadState &state) noexcept; + bool zip_load_entry_common (size_t entry_index, std::span const& buf, dynamic_local_string &entry_name, ZipEntryLoadState &state) noexcept; + bool zip_read_cd_info (int fd, uint32_t& cd_offset, uint32_t& cd_size, uint16_t& cd_entries); + bool zip_adjust_data_offset (int fd, ZipEntryLoadState &state); template static bool zip_extract_cd_info (std::array const& buf, uint32_t& cd_offset, uint32_t& cd_size, uint16_t& cd_entries) noexcept; @@ -292,7 +293,7 @@ namespace xamarin::android::internal { template static bool zip_read_field (T const& buf, size_t index, size_t count, dynamic_local_string& characters) noexcept; - static bool zip_read_entry_info (std::vector const& buf, dynamic_local_string& file_name, ZipEntryLoadState &state) noexcept; + bool zip_read_entry_info (std::span const& buf, dynamic_local_string& file_name, ZipEntryLoadState &state); [[gnu::always_inline]] static std::tuple get_wrapper_dso_payload_pointer_and_size (md_mmap_info const& map_info, const char *file_name) noexcept From 955da119afab124db6889a1cf223c563a60b1848 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Fri, 11 Oct 2024 19:43:06 +0200 Subject: [PATCH 15/60] Experimenting with zip scanning performance --- .../mono/monodroid/embedded-assemblies-zip.cc | 10 ++--- .../mono/monodroid/embedded-assemblies.cc | 45 ------------------- .../mono/monodroid/embedded-assemblies.hh | 38 +++++++++++++++- 3 files changed, 40 insertions(+), 53 deletions(-) diff --git a/src/native/mono/monodroid/embedded-assemblies-zip.cc b/src/native/mono/monodroid/embedded-assemblies-zip.cc index ac69313bf23..df93b483a01 100644 --- a/src/native/mono/monodroid/embedded-assemblies-zip.cc +++ b/src/native/mono/monodroid/embedded-assemblies-zip.cc @@ -328,6 +328,7 @@ EmbeddedAssemblies::zip_load_assembly_store_entries (std::span const& b } } +[[gnu::flatten]] void EmbeddedAssemblies::zip_load_entries (int fd, const char *apk_name, [[maybe_unused]] monodroid_should_register should_register) noexcept { @@ -335,7 +336,7 @@ EmbeddedAssemblies::zip_load_entries (int fd, const char *apk_name, [[maybe_unus uint32_t cd_size; uint16_t cd_entries; - if (!zip_read_cd_info (fd, cd_offset, cd_size, cd_entries)) { + if (!zip_read_cd_info (fd, cd_offset, cd_size, cd_entries)) [[unlikely]] { Helpers::abort_application ( LOG_ASSEMBLY, std::format ( @@ -345,14 +346,12 @@ EmbeddedAssemblies::zip_load_entries (int fd, const char *apk_name, [[maybe_unus ); } - md_mmap_info apk_map = md_mmap_apk_file (fd, cd_offset, cd_size, apk_name); - log_debug (LOG_ASSEMBLY, "Central directory offset: %u", cd_offset); log_debug (LOG_ASSEMBLY, "Central directory size: %u", cd_size); log_debug (LOG_ASSEMBLY, "Central directory entries: %u", cd_entries); // off_t retval = ::lseek (fd, static_cast(cd_offset), SEEK_SET); - // if (retval < 0) { + // if (retval < 0) [[unlikely]] { // Helpers::abort_application ( // LOG_ASSEMBLY, // Util::monodroid_strdup_printf ( @@ -365,7 +364,6 @@ EmbeddedAssemblies::zip_load_entries (int fd, const char *apk_name, [[maybe_unus // ); // } - std::span buf (reinterpret_cast(apk_map.area), apk_map.size); const auto [prefix, prefix_len] = get_assemblies_prefix_and_length (); ZipEntryLoadState state { .file_fd = fd, @@ -402,7 +400,7 @@ EmbeddedAssemblies::zip_load_entries (int fd, const char *apk_name, [[maybe_unus zip_load_individual_assembly_entries (buf, cd_entries, should_register, state); } - // TODO: unmap here + //delete[] raw_data; } template diff --git a/src/native/mono/monodroid/embedded-assemblies.cc b/src/native/mono/monodroid/embedded-assemblies.cc index c35324f408b..98e80d8a289 100644 --- a/src/native/mono/monodroid/embedded-assemblies.cc +++ b/src/native/mono/monodroid/embedded-assemblies.cc @@ -910,51 +910,6 @@ EmbeddedAssemblies::typemap_managed_to_java (MonoReflectionType *reflection_type return ret; } -EmbeddedAssemblies::md_mmap_info -EmbeddedAssemblies::md_mmap_apk_file (int fd, uint32_t offset, size_t size, const char* filename) -{ - md_mmap_info file_info; - md_mmap_info mmap_info; - - size_t pageSize = static_cast(Util::monodroid_getpagesize ()); - size_t offsetFromPage = offset % pageSize; - size_t offsetPage = offset - offsetFromPage; - size_t offsetSize = size + offsetFromPage; - - mmap_info.area = mmap (nullptr, offsetSize, PROT_READ, MAP_PRIVATE, fd, static_cast(offsetPage)); - - if (mmap_info.area == MAP_FAILED) { - Helpers::abort_application ( - LOG_ASSEMBLY, - std::format ( - "Could not mmap APK fd {}: {}; File={}", - fd, - strerror (errno), - optional_string (filename) - ) - ); - } - - mmap_info.size = offsetSize; - file_info.area = pointer_add (mmap_info.area, offsetFromPage); - file_info.size = size; - - log_info ( - LOG_ASSEMBLY, - " mmap_start: {:<8p}; mmap_end: {:<8p} mmap_len: {:<12} file_start: {:<8p} file_end: {:<8p} file_len: {:<12} apk descriptor: {} file: {}", - mmap_info.area, - pointer_add (mmap_info.area, mmap_info.size), - mmap_info.size, - file_info.area, - pointer_add (file_info.area, file_info.size), - file_info.size, - fd, - optional_string (filename) - ); - - return file_info; -} - void EmbeddedAssemblies::gather_bundled_assemblies_from_apk (const char* apk, monodroid_should_register should_register) noexcept { diff --git a/src/native/mono/monodroid/embedded-assemblies.hh b/src/native/mono/monodroid/embedded-assemblies.hh index 635f7b973ef..63ac8bd655a 100644 --- a/src/native/mono/monodroid/embedded-assemblies.hh +++ b/src/native/mono/monodroid/embedded-assemblies.hh @@ -27,7 +27,7 @@ #include #include "cppcompat.hh" #include "shared-constants.hh" -#include +#include "xxhash.hh" #include "util.hh" #include @@ -259,7 +259,41 @@ namespace xamarin::android::internal { static const TypeMapEntry *typemap_managed_to_java (const char *managed_type_name) noexcept; #endif // DEBUG - static md_mmap_info md_mmap_apk_file (int fd, uint32_t offset, size_t size, const char* filename); + [[gnu::always_inline]] + static md_mmap_info md_mmap_apk_file (int fd, uint32_t offset, size_t size, const char* filename, md_mmap_info &original_info, md_mmap_info &adjusted_info) noexcept + { + size_t pageSize = static_cast(Util::monodroid_getpagesize ()); + size_t offsetFromPage = offset % pageSize; + size_t offsetPage = offset - offsetFromPage; + size_t offsetSize = size + offsetFromPage; + + original_info.area = mmap (nullptr, offsetSize, PROT_READ, MAP_PRIVATE, fd, static_cast(offsetPage)); + + if (original_info.area == MAP_FAILED) { + log_fatal (LOG_DEFAULT, "Could not `mmap` apk fd %d entry `%s`: %s", fd, filename, strerror (errno)); + Helpers::abort_application (); + } + + original_info.size = offsetSize; + adjusted_info.area = (void*)((const char*)original_info.area + offsetFromPage); + adjusted_info.size = size; + + log_info (LOG_ASSEMBLY, " mmap_start: %08p mmap_end: %08p mmap_len: % 12u file_start: %08p file_end: %08p file_len: % 12u apk descriptor: %d file: %s", + original_info.area, reinterpret_cast (original_info.area) + original_info.size, original_info.size, + adjusted_info.area, reinterpret_cast (adjusted_info.area) + adjusted_info.size, adjusted_info.size, fd, filename); + + return adjusted_info; + } + + [[gnu::flatten, gnu::always_inline]] + static md_mmap_info md_mmap_apk_file (int fd, uint32_t offset, size_t size, const char* filename) noexcept + { + md_mmap_info file_info; + md_mmap_info mmap_info; + + return md_mmap_apk_file (fd, offset, size, filename, mmap_info, file_info); + } + static MonoAssembly* open_from_bundles_full (MonoAssemblyName *aname, char **assemblies_path, void *user_data); static MonoAssembly* open_from_bundles (MonoAssemblyLoadContextGCHandle alc_gchandle, MonoAssemblyName *aname, char **assemblies_path, void *user_data, MonoError *error); From dee133a2fa956967e4aae3b3bb3bde5839573af6 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Tue, 15 Oct 2024 12:16:50 +0200 Subject: [PATCH 16/60] Post rebase fixups --- src/native/mono/monodroid/embedded-assemblies.hh | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/native/mono/monodroid/embedded-assemblies.hh b/src/native/mono/monodroid/embedded-assemblies.hh index 63ac8bd655a..f040c3be509 100644 --- a/src/native/mono/monodroid/embedded-assemblies.hh +++ b/src/native/mono/monodroid/embedded-assemblies.hh @@ -270,17 +270,25 @@ namespace xamarin::android::internal { original_info.area = mmap (nullptr, offsetSize, PROT_READ, MAP_PRIVATE, fd, static_cast(offsetPage)); if (original_info.area == MAP_FAILED) { - log_fatal (LOG_DEFAULT, "Could not `mmap` apk fd %d entry `%s`: %s", fd, filename, strerror (errno)); - Helpers::abort_application (); + Helpers::abort_application ( + LOG_ASSEMBLY, + Util::monodroid_strdup_printf ( + "Could not mmap APK fd %d: %s; File=%s", + fd, + strerror (errno), + filename + ) + ); } original_info.size = offsetSize; adjusted_info.area = (void*)((const char*)original_info.area + offsetFromPage); adjusted_info.size = size; - log_info (LOG_ASSEMBLY, " mmap_start: %08p mmap_end: %08p mmap_len: % 12u file_start: %08p file_end: %08p file_len: % 12u apk descriptor: %d file: %s", + log_info (LOG_ASSEMBLY, "mmap_start: %08p mmap_end: %08p mmap_len: % 12u file_start: %08p file_end: %08p file_len: % 12u; apk descriptor: %d; file: %s", original_info.area, reinterpret_cast (original_info.area) + original_info.size, original_info.size, - adjusted_info.area, reinterpret_cast (adjusted_info.area) + adjusted_info.size, adjusted_info.size, fd, filename); + adjusted_info.area, reinterpret_cast (adjusted_info.area) + adjusted_info.size, adjusted_info.size, fd, filename + ); return adjusted_info; } From a27f435fc08d8801232d77699d047922fb511612 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Tue, 15 Oct 2024 12:31:45 +0200 Subject: [PATCH 17/60] More post rebase fixups --- src/native/mono/monodroid/embedded-assemblies-zip.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/native/mono/monodroid/embedded-assemblies-zip.cc b/src/native/mono/monodroid/embedded-assemblies-zip.cc index df93b483a01..cedf27e29d0 100644 --- a/src/native/mono/monodroid/embedded-assemblies-zip.cc +++ b/src/native/mono/monodroid/embedded-assemblies-zip.cc @@ -194,7 +194,7 @@ EmbeddedAssemblies::verify_assembly_store_and_set_info (void *data_start, const LOG_ASSEMBLY, Util::monodroid_strdup_printf ( "Assembly store '%s' is not a valid .NET for Android assembly store file", - entry_name.get () + name ) ); } @@ -204,7 +204,7 @@ EmbeddedAssemblies::verify_assembly_store_and_set_info (void *data_start, const LOG_ASSEMBLY, Util::monodroid_strdup_printf ( "Assembly store '%s' uses format version 0x%x, instead of the expected 0x%x", - entry_name.get (), + name, header->version, ASSEMBLY_STORE_FORMAT_VERSION ) From 963d76077346b51d9fbccafe0a95949cdc1874b9 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Tue, 15 Oct 2024 16:29:28 +0200 Subject: [PATCH 18/60] seek and ye shall read --- .../mono/monodroid/embedded-assemblies-zip.cc | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/native/mono/monodroid/embedded-assemblies-zip.cc b/src/native/mono/monodroid/embedded-assemblies-zip.cc index cedf27e29d0..3171778d719 100644 --- a/src/native/mono/monodroid/embedded-assemblies-zip.cc +++ b/src/native/mono/monodroid/embedded-assemblies-zip.cc @@ -350,19 +350,19 @@ EmbeddedAssemblies::zip_load_entries (int fd, const char *apk_name, [[maybe_unus log_debug (LOG_ASSEMBLY, "Central directory size: %u", cd_size); log_debug (LOG_ASSEMBLY, "Central directory entries: %u", cd_entries); - // off_t retval = ::lseek (fd, static_cast(cd_offset), SEEK_SET); - // if (retval < 0) [[unlikely]] { - // Helpers::abort_application ( - // LOG_ASSEMBLY, - // Util::monodroid_strdup_printf ( - // "Failed to seek to central directory position in APK: %s. retval=%d errno=%d, File=%s", - // std::strerror (errno), - // retval, - // errno, - // apk_name - // ) - // ); - // } + off_t retval = ::lseek (fd, static_cast(cd_offset), SEEK_SET); + if (retval < 0) [[unlikely]] { + Helpers::abort_application ( + LOG_ASSEMBLY, + Util::monodroid_strdup_printf ( + "Failed to seek to central directory position in APK: %s. retval=%d errno=%d, File=%s", + std::strerror (errno), + retval, + errno, + apk_name + ) + ); + } const auto [prefix, prefix_len] = get_assemblies_prefix_and_length (); ZipEntryLoadState state { From 460dc65947817a88b901a455885cb83e490bc596 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Wed, 16 Oct 2024 14:05:16 +0200 Subject: [PATCH 19/60] Details, details... --- .../Xamarin.Android.Common.targets | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets index bd921b66859..5c685584b63 100644 --- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets +++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets @@ -2379,8 +2379,8 @@ because xbuild doesn't support framework reference assemblies. ZipAlignmentPages="$(AndroidZipAlignment)" UseAssemblyStore="$(AndroidUseAssemblyStore)" AndroidBinUtilsDirectory="$(AndroidBinUtilsDirectory)" - IntermediateOutputPath="$(IntermediateOutputPath)"> - CompressedAssembliesDir="$(_AndroidCompressedAssembliesDir)"> + IntermediateOutputPath="$(IntermediateOutputPath)" + CompressedAssembliesDir="$(_AndroidCompressedAssembliesDir)" AssemblyStoreEmbeddedInRuntime="$(_AndroidEmbedAssemblyStoreInRuntime)"> @@ -2450,8 +2450,8 @@ because xbuild doesn't support framework reference assemblies. CheckedBuild="$(_AndroidCheckedBuild)" ZipAlignmentPages="$(AndroidZipAlignment)" AndroidBinUtilsDirectory="$(AndroidBinUtilsDirectory)" - IntermediateOutputPath="$(IntermediateOutputPath)"> - CompressedAssembliesDir="$(_AndroidCompressedAssembliesDir)"> + IntermediateOutputPath="$(IntermediateOutputPath)" + CompressedAssembliesDir="$(_AndroidCompressedAssembliesDir)" AssemblyStoreEmbeddedInRuntime="$(_AndroidEmbedAssemblyStoreInRuntime)"> @@ -2525,8 +2525,8 @@ because xbuild doesn't support framework reference assemblies. ZipFlushSizeLimit="$(_ZipFlushSizeLimit)" ExcludeFiles="@(AndroidPackagingOptionsExclude)" AndroidBinUtilsDirectory="$(AndroidBinUtilsDirectory)" - IntermediateOutputPath="$(IntermediateOutputPath)"> - CompressedAssembliesDir="$(_AndroidCompressedAssembliesDir)"> + IntermediateOutputPath="$(IntermediateOutputPath)" + CompressedAssembliesDir="$(_AndroidCompressedAssembliesDir)" AssemblyStoreEmbeddedInRuntime="$(_AndroidEmbedAssemblyStoreInRuntime)"> @@ -2566,8 +2566,8 @@ because xbuild doesn't support framework reference assemblies. ZipFlushSizeLimit="$(_ZipFlushSizeLimit)" ExcludeFiles="@(AndroidPackagingOptionsExclude)" AndroidBinUtilsDirectory="$(AndroidBinUtilsDirectory)" - IntermediateOutputPath="$(IntermediateOutputPath)"> - CompressedAssembliesDir="$(_AndroidCompressedAssembliesDir)"> + IntermediateOutputPath="$(IntermediateOutputPath)" + CompressedAssembliesDir="$(_AndroidCompressedAssembliesDir)" AssemblyStoreEmbeddedInRuntime="$(_AndroidEmbedAssemblyStoreInRuntime)"> From 001cfd8eb7c4592f48323bbd6f0a6cee2d465e53 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Wed, 16 Oct 2024 17:38:54 +0200 Subject: [PATCH 20/60] Cleanup --- .../Xamarin.Android.Common.targets | 10 ++++++---- src/native/mono/monodroid/embedded-assemblies-zip.cc | 11 ----------- src/native/mono/monodroid/embedded-assemblies.hh | 7 +------ src/native/mono/monodroid/monodroid-glue.cc | 7 ------- 4 files changed, 7 insertions(+), 28 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets index 5c685584b63..038628923a1 100644 --- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets +++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets @@ -311,6 +311,7 @@ Copyright (C) 2011-2012 Xamarin. All rights reserved. <_AndroidFastDeployEnvironmentFiles Condition=" '$(_AndroidFastDeployEnvironmentFiles)' == '' And '$(EmbedAssembliesIntoApk)' == 'False' ">True <_AndroidFastDeployEnvironmentFiles Condition=" '$(_AndroidFastDeployEnvironmentFiles)' == '' ">False + <_AndroidCompressedAssembliesDir>$(IntermediateOutputPath)android\lz4 @@ -2067,7 +2068,7 @@ because xbuild doesn't support framework reference assemblies. <_CompileToDalvikDependsOnTargets> _CompileJava; - _RemoveRegisterAttribute; + _RemoveRegisterAttribute; _CreateApplicationSharedLibraries; _GetMonoPlatformJarPath; _GetLibraryImports; @@ -2371,7 +2372,6 @@ because xbuild doesn't support framework reference assemblies. ProjectFullPath="$(MSBuildProjectFullPath)" IncludeWrapSh="$(AndroidIncludeWrapSh)" CheckedBuild="$(_AndroidCheckedBuild)" - RuntimeConfigBinFilePath="$(_BinaryRuntimeConfigPath)" ExcludeFiles="@(AndroidPackagingOptionsExclude)" IncludeFiles="@(AndroidPackagingOptionsInclude)" ZipFlushFilesLimit="$(_ZipFlushFilesLimit)" @@ -2448,6 +2448,10 @@ because xbuild doesn't support framework reference assemblies. SupportedAbis="@(_BuildTargetAbis)" IncludeWrapSh="$(AndroidIncludeWrapSh)" CheckedBuild="$(_AndroidCheckedBuild)" + ExcludeFiles="@(AndroidPackagingOptionsExclude)" + IncludeFiles="@(AndroidPackagingOptionsInclude)" + ZipFlushFilesLimit="$(_ZipFlushFilesLimit)" + ZipFlushSizeLimit="$(_ZipFlushSizeLimit)" ZipAlignmentPages="$(AndroidZipAlignment)" AndroidBinUtilsDirectory="$(AndroidBinUtilsDirectory)" IntermediateOutputPath="$(IntermediateOutputPath)" @@ -2520,7 +2524,6 @@ because xbuild doesn't support framework reference assemblies. ProjectFullPath="$(MSBuildProjectFullPath)" IncludeWrapSh="$(AndroidIncludeWrapSh)" CheckedBuild="$(_AndroidCheckedBuild)" - RuntimeConfigBinFilePath="$(_BinaryRuntimeConfigPath)" ZipFlushFilesLimit="$(_ZipFlushFilesLimit)" ZipFlushSizeLimit="$(_ZipFlushSizeLimit)" ExcludeFiles="@(AndroidPackagingOptionsExclude)" @@ -2561,7 +2564,6 @@ because xbuild doesn't support framework reference assemblies. ProjectFullPath="$(MSBuildProjectFullPath)" IncludeWrapSh="$(AndroidIncludeWrapSh)" CheckedBuild="$(_AndroidCheckedBuild)" - RuntimeConfigBinFilePath="$(_BinaryRuntimeConfigPath)" ZipFlushFilesLimit="$(_ZipFlushFilesLimit)" ZipFlushSizeLimit="$(_ZipFlushSizeLimit)" ExcludeFiles="@(AndroidPackagingOptionsExclude)" diff --git a/src/native/mono/monodroid/embedded-assemblies-zip.cc b/src/native/mono/monodroid/embedded-assemblies-zip.cc index 3171778d719..a554f3ef9bf 100644 --- a/src/native/mono/monodroid/embedded-assemblies-zip.cc +++ b/src/native/mono/monodroid/embedded-assemblies-zip.cc @@ -62,14 +62,6 @@ EmbeddedAssemblies::zip_load_entry_common (size_t entry_index, std::span const& b dynamic_local_string entry_name; bool assembly_store_found = embedded_assembly_store_size != 0; if (assembly_store_found) { - log_debug (LOG_ASSEMBLY, "Got embedded assembly store, size %zu", embedded_assembly_store_size); verify_assembly_store_and_set_info (embedded_assembly_store, "embedded"); log_debug (LOG_ASSEMBLY, "Looking for DSOs in APK"); } else { @@ -399,8 +390,6 @@ EmbeddedAssemblies::zip_load_entries (int fd, const char *apk_name, [[maybe_unus } else { zip_load_individual_assembly_entries (buf, cd_entries, should_register, state); } - - //delete[] raw_data; } template diff --git a/src/native/mono/monodroid/embedded-assemblies.hh b/src/native/mono/monodroid/embedded-assemblies.hh index f040c3be509..db110d7f426 100644 --- a/src/native/mono/monodroid/embedded-assemblies.hh +++ b/src/native/mono/monodroid/embedded-assemblies.hh @@ -194,12 +194,7 @@ namespace xamarin::android::internal { runtime_config_data_size = 0uz; } - static bool have_runtime_config_blob () noexcept - { - return application_config.have_runtime_config_blob && runtime_config_blob_mmap.area != nullptr; - } - - static bool keep_scanning () noexcept + bool keep_scanning () const noexcept { return need_to_scan_more_apks; } diff --git a/src/native/mono/monodroid/monodroid-glue.cc b/src/native/mono/monodroid/monodroid-glue.cc index 727681bf268..df82db42457 100644 --- a/src/native/mono/monodroid/monodroid-glue.cc +++ b/src/native/mono/monodroid/monodroid-glue.cc @@ -728,7 +728,6 @@ MonodroidRuntime::create_domain (JNIEnv *env, jstring_array_wrapper &runtimeApks gather_bundled_assemblies (runtimeApks, &user_assemblies_count, have_split_apks); - // if (embeddedAssemblies.have_runtime_config_blob ()) { if (embedded_runtime_config_size > 0) { size_t blob_time_index; if (FastTiming::enabled ()) [[unlikely]] { @@ -736,7 +735,6 @@ MonodroidRuntime::create_domain (JNIEnv *env, jstring_array_wrapper &runtimeApks } runtime_config_args.kind = 1; -// embeddedAssemblies.get_runtime_config_blob (runtime_config_args.runtimeconfig.data.data, runtime_config_args.runtimeconfig.data.data_len); runtime_config_args.runtimeconfig.data.data = reinterpret_cast(embedded_runtime_config); runtime_config_args.runtimeconfig.data.data_len = static_cast(embedded_runtime_config_size); monovm_runtimeconfig_initialize (&runtime_config_args, cleanup_runtime_config, nullptr); @@ -1410,11 +1408,6 @@ MonodroidRuntime::Java_mono_android_Runtime_initInternal (JNIEnv *env, jclass kl Logger::init_logging_categories (mono_log_mask_raw, mono_log_level_raw); - // log_warn (LOG_DEFAULT, "Embedded runtime config size: %zu", embedded_runtime_config_size); - // if (embedded_runtime_config_size > 0) { - // log_warn (LOG_DEFAULT, "First byte of embedded runtime config: 0x%x", embedded_runtime_config[0]); - // } - std::unique_ptr mono_log_mask (mono_log_mask_raw); std::unique_ptr mono_log_level (mono_log_level_raw); From 0907f4d76cb5b6c4e9c44804bc5dc202a67bb767 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Wed, 16 Oct 2024 17:39:06 +0200 Subject: [PATCH 21/60] Teach assembly store explorer about embedded stores --- .../Utilities/ELFHelper.Basic.cs | 61 ++++++++++++++++ .../Utilities/ELFHelper.cs | 26 +------ .../AssemblyStore/ELFPayloadError.cs | 1 + .../AssemblyStore/StoreReader_V2.cs | 47 ++++++++---- .../AssemblyStore/Utils.cs | 73 +++++++++++++++---- .../assembly-store-reader.csproj | 1 + 6 files changed, 155 insertions(+), 54 deletions(-) create mode 100644 src/Xamarin.Android.Build.Tasks/Utilities/ELFHelper.Basic.cs diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/ELFHelper.Basic.cs b/src/Xamarin.Android.Build.Tasks/Utilities/ELFHelper.Basic.cs new file mode 100644 index 00000000000..df401b2f462 --- /dev/null +++ b/src/Xamarin.Android.Build.Tasks/Utilities/ELFHelper.Basic.cs @@ -0,0 +1,61 @@ +using System; + +using ELFSharp.ELF; +using ELFSharp.ELF.Sections; + +namespace Xamarin.Android.Tasks; + +static partial class ELFHelper +{ + public static ISymbolTable? GetSymbolTable (IELF elf, string sectionName) + { + ISection? section = GetSection (elf, sectionName); + if (section == null) { + return null; + } + + var symtab = section as ISymbolTable; + if (symtab == null) { + return null; + } + + return symtab; + } + + public static ISection? GetSection (IELF elf, string sectionName) + { + if (!elf.TryGetSection (sectionName, out ISection section)) { + return null; + } + + return section; + } + + public static SymbolEntry? FindSymbol (ISymbolTable? symbolTable, string symbolName) where T: struct + { + if (symbolTable == null) { + return null; + } + + ISymbolEntry? symbol = null; + foreach (ISymbolEntry entry in symbolTable.Entries) { + if (String.Compare (entry.Name, symbolName, StringComparison.Ordinal) != 0) { + continue; + } + + symbol = entry; + break; + } + + if (symbol == null) { + return null; + } + + Type t = typeof(T); + if (t == typeof(ulong) || t == typeof(uint)) { + return (SymbolEntry)symbol; + } + + throw new InvalidOperationException ($"Only `ulong` and `uint` types are accepted"); + } +} diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/ELFHelper.cs b/src/Xamarin.Android.Build.Tasks/Utilities/ELFHelper.cs index 5c4879dc323..f51b9fb30b9 100644 --- a/src/Xamarin.Android.Build.Tasks/Utilities/ELFHelper.cs +++ b/src/Xamarin.Android.Build.Tasks/Utilities/ELFHelper.cs @@ -16,7 +16,7 @@ namespace Xamarin.Android.Tasks { - static class ELFHelper + static partial class ELFHelper { public static void AssertValidLibraryAlignment (TaskLoggingHelper log, int alignmentInPages, string path, ITaskItem? item) { @@ -226,29 +226,5 @@ bool IsNonEmptyCodeSymbol (SymbolEntry? symbolEntry) where T : struct return size != 0 && symbolEntry.PointedSection.Type == ELFSectionType.ProgBits; } } - - static ISymbolTable? GetSymbolTable (IELF elf, string sectionName) - { - ISection? section = GetSection (elf, sectionName); - if (section == null) { - return null; - } - - var symtab = section as ISymbolTable; - if (symtab == null) { - return null; - } - - return symtab; - } - - static ISection? GetSection (IELF elf, string sectionName) - { - if (!elf.TryGetSection (sectionName, out ISection section)) { - return null; - } - - return section; - } } } diff --git a/tools/assembly-store-reader-mk2/AssemblyStore/ELFPayloadError.cs b/tools/assembly-store-reader-mk2/AssemblyStore/ELFPayloadError.cs index 932f151c80f..78372c26853 100644 --- a/tools/assembly-store-reader-mk2/AssemblyStore/ELFPayloadError.cs +++ b/tools/assembly-store-reader-mk2/AssemblyStore/ELFPayloadError.cs @@ -8,4 +8,5 @@ enum ELFPayloadError NotSharedLibrary, NotLittleEndian, NoPayloadSection, + NoEmbeddedStore, } diff --git a/tools/assembly-store-reader-mk2/AssemblyStore/StoreReader_V2.cs b/tools/assembly-store-reader-mk2/AssemblyStore/StoreReader_V2.cs index a43960102e2..1fc93530a66 100644 --- a/tools/assembly-store-reader-mk2/AssemblyStore/StoreReader_V2.cs +++ b/tools/assembly-store-reader-mk2/AssemblyStore/StoreReader_V2.cs @@ -86,6 +86,19 @@ public StoreReader_V2 (Stream store, string path) protected override ulong GetStoreStartDataOffset () => elfOffset; + string PayloadErrorToString (ELFPayloadError error) + { + return error switch { + ELFPayloadError.NotELF => $"Store '{StorePath}' is not a valid ELF binary", + ELFPayloadError.LoadFailed => $"Store '{StorePath}' could not be loaded", + ELFPayloadError.NotSharedLibrary => $"Store '{StorePath}' is not a shared ELF library", + ELFPayloadError.NotLittleEndian => $"Store '{StorePath}' is not a little-endian ELF image", + ELFPayloadError.NoPayloadSection => $"Store '{StorePath}' does not contain the 'payload' section", + ELFPayloadError.NoEmbeddedStore => $"Store '{StorePath}' does not contain embedded data blob", + _ => $"Unknown ELF payload section error for store '{StorePath}': {error}" + }; + } + protected override bool IsSupported () { StoreStream.Seek (0, SeekOrigin.Begin); @@ -94,22 +107,19 @@ protected override bool IsSupported () uint magic = reader.ReadUInt32 (); if (magic == Utils.ELF_MAGIC) { ELFPayloadError error; - (elfOffset, _, error) = Utils.FindELFPayloadSectionOffsetAndSize (StoreStream); - + (elfOffset, _, error) = Utils.FindEmbeddedStoreOffsetAndSize (StoreStream); if (error != ELFPayloadError.None) { - string message = error switch { - ELFPayloadError.NotELF => $"Store '{StorePath}' is not a valid ELF binary", - ELFPayloadError.LoadFailed => $"Store '{StorePath}' could not be loaded", - ELFPayloadError.NotSharedLibrary => $"Store '{StorePath}' is not a shared ELF library", - ELFPayloadError.NotLittleEndian => $"Store '{StorePath}' is not a little-endian ELF image", - ELFPayloadError.NoPayloadSection => $"Store '{StorePath}' does not contain the 'payload' section", - _ => $"Unknown ELF payload section error for store '{StorePath}': {error}" - }; - Log.Debug (message); - } else if (elfOffset >= 0) { - StoreStream.Seek ((long)elfOffset, SeekOrigin.Begin); - magic = reader.ReadUInt32 (); + MaybeLogError (error); + + (elfOffset, _, error) = Utils.FindELFPayloadSectionOffsetAndSize (StoreStream); + if (error != ELFPayloadError.None) { + MaybeLogError (error); + return false; + } } + + StoreStream.Seek ((long)elfOffset, SeekOrigin.Begin); + magic = reader.ReadUInt32 (); } if (magic != Utils.ASSEMBLY_STORE_MAGIC) { @@ -129,6 +139,15 @@ protected override bool IsSupported () header = new Header (magic, version, entry_count, index_entry_count, index_size); return true; + + void MaybeLogError (ELFPayloadError error) + { + if (error == ELFPayloadError.None) { + return; + } + + Log.Debug (PayloadErrorToString (error)); + } } protected override void Prepare () diff --git a/tools/assembly-store-reader-mk2/AssemblyStore/Utils.cs b/tools/assembly-store-reader-mk2/AssemblyStore/Utils.cs index 284f501c9ac..2e2f03e5e52 100644 --- a/tools/assembly-store-reader-mk2/AssemblyStore/Utils.cs +++ b/tools/assembly-store-reader-mk2/AssemblyStore/Utils.cs @@ -4,6 +4,7 @@ using ELFSharp.ELF; using ELFSharp.ELF.Sections; +using Xamarin.Android.Tasks; using Xamarin.Tools.Zip; namespace Xamarin.Android.AssemblyStore; @@ -29,31 +30,28 @@ static class Utils public static readonly ArrayPool BytePool = ArrayPool.Shared; - public static (ulong offset, ulong size, ELFPayloadError error) FindELFPayloadSectionOffsetAndSize (Stream stream) + static (bool is64, IELF? elf, ELFPayloadError error) TryOpenELF (Stream stream) { + bool is64 = false; stream.Seek (0, SeekOrigin.Begin); Class elfClass = ELFReader.CheckELFType (stream); if (elfClass == Class.NotELF) { - return ReturnError (null, ELFPayloadError.NotELF); + return ReturnError (is64, null, ELFPayloadError.NotELF); } if (!ELFReader.TryLoad (stream, shouldOwnStream: false, out IELF? elf)) { - return ReturnError (elf, ELFPayloadError.LoadFailed); + return ReturnError (is64, elf, ELFPayloadError.LoadFailed); } if (elf.Type != FileType.SharedObject) { - return ReturnError (elf, ELFPayloadError.NotSharedLibrary); + return ReturnError (is64, elf, ELFPayloadError.NotSharedLibrary); } if (elf.Endianess != ELFSharp.Endianess.LittleEndian) { - return ReturnError (elf, ELFPayloadError.NotLittleEndian); - } - - if (!elf.TryGetSection ("payload", out ISection? payloadSection)) { - return ReturnError (elf, ELFPayloadError.NoPayloadSection); + return ReturnError (is64, elf, ELFPayloadError.NotLittleEndian); } - bool is64 = elf.Machine switch { + is64 = elf.Machine switch { Machine.ARM => false, Machine.Intel386 => false, @@ -63,6 +61,51 @@ public static (ulong offset, ulong size, ELFPayloadError error) FindELFPayloadSe _ => throw new NotSupportedException ($"Unsupported ELF architecture '{elf.Machine}'") }; + return (is64, elf, ELFPayloadError.None); + + (bool is64, IELF? elf, ELFPayloadError error) ReturnError (bool is64, IELF? elf, ELFPayloadError error) + { + elf?.Dispose (); + + return (is64, null, error); + } + } + + public static (ulong offset, ulong size, ELFPayloadError error) FindEmbeddedStoreOffsetAndSize (Stream stream) + { + (bool is64, IELF? elf, ELFPayloadError error) = TryOpenELF (stream); + if (elf == null || error != ELFPayloadError.None) { + return ReturnError (elf, error); + } + + const string SymbolName = "embedded_assembly_store"; + ISymbolTable? dynsym = ELFHelper.GetSymbolTable (elf, ".dynsym"); + if (is64) { + SymbolEntry? symbol = ELFHelper.FindSymbol (dynsym, SymbolName); + if (symbol != null) { + return (symbol.Value, symbol.Size, ELFPayloadError.None); + } + } else { + SymbolEntry? symbol = ELFHelper.FindSymbol (dynsym, SymbolName); + if (symbol != null) { + return ((ulong)symbol.Value, (ulong)symbol.Size, ELFPayloadError.None); + } + } + + return (0, 0, ELFPayloadError.NoEmbeddedStore); + } + + public static (ulong offset, ulong size, ELFPayloadError error) FindELFPayloadSectionOffsetAndSize (Stream stream) + { + (bool is64, IELF? elf, ELFPayloadError error) = TryOpenELF (stream); + if (elf == null || error != ELFPayloadError.None) { + return ReturnError (elf, error); + } + + if (!elf.TryGetSection ("payload", out ISection? payloadSection)) { + return ReturnError (elf, ELFPayloadError.NoPayloadSection); + } + ulong offset; ulong size; @@ -84,13 +127,13 @@ public static (ulong offset, ulong size, ELFPayloadError error) FindELFPayloadSe { return ((ulong)payload.Offset, (ulong)payload.Size); } + } - (ulong offset, ulong size, ELFPayloadError error) ReturnError (IELF? elf, ELFPayloadError error) - { - elf?.Dispose (); + static (ulong offset, ulong size, ELFPayloadError error) ReturnError (IELF? elf, ELFPayloadError error) + { + elf?.Dispose (); - return (0, 0, error); - } + return (0, 0, error); } public static (FileFormat format, FileInfo? info) DetectFileFormat (string path) diff --git a/tools/assembly-store-reader-mk2/assembly-store-reader.csproj b/tools/assembly-store-reader-mk2/assembly-store-reader.csproj index ec4c90fecb1..3bd2852d04e 100644 --- a/tools/assembly-store-reader-mk2/assembly-store-reader.csproj +++ b/tools/assembly-store-reader-mk2/assembly-store-reader.csproj @@ -24,6 +24,7 @@ + From 94d1a6a3cada80f7b4f00b4bb1cbfb4bc96412f4 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Wed, 16 Oct 2024 17:47:22 +0200 Subject: [PATCH 22/60] Teach store v2 reader to look in `libxamarin-app.so`, too --- .../AssemblyStore/StoreReader_V2.cs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/tools/assembly-store-reader-mk2/AssemblyStore/StoreReader_V2.cs b/tools/assembly-store-reader-mk2/AssemblyStore/StoreReader_V2.cs index 1fc93530a66..1ba0cb8b488 100644 --- a/tools/assembly-store-reader-mk2/AssemblyStore/StoreReader_V2.cs +++ b/tools/assembly-store-reader-mk2/AssemblyStore/StoreReader_V2.cs @@ -40,6 +40,11 @@ static StoreReader_V2 () GetArchPath (AndroidTargetArch.Arm), GetArchPath (AndroidTargetArch.X86_64), GetArchPath (AndroidTargetArch.X86), + + GetArchPath (AndroidTargetArch.Arm64, embeddedBlob: true), + GetArchPath (AndroidTargetArch.Arm, embeddedBlob: true), + GetArchPath (AndroidTargetArch.X86_64, embeddedBlob: true), + GetArchPath (AndroidTargetArch.X86, embeddedBlob: true), }; ApkPaths = paths.AsReadOnly (); AabBasePaths = ApkPaths; @@ -50,10 +55,15 @@ static StoreReader_V2 () GetArchPath (AndroidTargetArch.Arm, AabBaseDir), GetArchPath (AndroidTargetArch.X86_64, AabBaseDir), GetArchPath (AndroidTargetArch.X86, AabBaseDir), + + GetArchPath (AndroidTargetArch.Arm64, AabBaseDir, embeddedBlob: true), + GetArchPath (AndroidTargetArch.Arm, AabBaseDir, embeddedBlob: true), + GetArchPath (AndroidTargetArch.X86_64, AabBaseDir, embeddedBlob: true), + GetArchPath (AndroidTargetArch.X86, AabBaseDir, embeddedBlob: true), }; AabPaths = paths.AsReadOnly (); - string GetArchPath (AndroidTargetArch arch, string? root = null) + string GetArchPath (AndroidTargetArch arch, string? root = null, bool embeddedBlob = false) { const string LibDirName = "lib"; @@ -65,7 +75,9 @@ string GetArchPath (AndroidTargetArch arch, string? root = null) root = LibDirName; } parts.Add (abi); - parts.Add (GetBlobName (abi)); + parts.Add ( + embeddedBlob ? "libxamarin-app.so" : GetBlobName (abi) + ); return MonoAndroidHelper.MakeZipArchivePath (root, parts); } From fd91482020fdf1b3ca782d6ce307b40b77fb468b Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Wed, 16 Oct 2024 17:48:55 +0200 Subject: [PATCH 23/60] Nicer --- .../AssemblyStore/StoreReader_V2.cs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/tools/assembly-store-reader-mk2/AssemblyStore/StoreReader_V2.cs b/tools/assembly-store-reader-mk2/AssemblyStore/StoreReader_V2.cs index 1ba0cb8b488..fbccf1bdb94 100644 --- a/tools/assembly-store-reader-mk2/AssemblyStore/StoreReader_V2.cs +++ b/tools/assembly-store-reader-mk2/AssemblyStore/StoreReader_V2.cs @@ -75,9 +75,7 @@ string GetArchPath (AndroidTargetArch arch, string? root = null, bool embeddedBl root = LibDirName; } parts.Add (abi); - parts.Add ( - embeddedBlob ? "libxamarin-app.so" : GetBlobName (abi) - ); + parts.Add (GetBlobName (abi, embeddedBlob)); return MonoAndroidHelper.MakeZipArchivePath (root, parts); } @@ -94,7 +92,7 @@ public StoreReader_V2 (Stream store, string path) }; } - static string GetBlobName (string abi) => $"libassemblies.{abi}.blob.so"; + static string GetBlobName (string abi, bool embeddedBlob) => embeddedBlob ? "libxamarin-app.so" : $"libassemblies.{abi}.blob.so"; protected override ulong GetStoreStartDataOffset () => elfOffset; From 7a063b31e89efe523f193f6bdcdd5ec7a8de9622 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Thu, 17 Oct 2024 10:02:47 +0200 Subject: [PATCH 24/60] The runtime configuration blob is now part of `libxamarin-app.so` --- .../Tests/Xamarin.Android.Build.Tests/PackagingTest.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/PackagingTest.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/PackagingTest.cs index 21f48d77025..23cca31ecbe 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/PackagingTest.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/PackagingTest.cs @@ -129,7 +129,6 @@ public void CheckIncludedAssemblies ([Values (false, true)] bool usesAssemblySto "System.Collections.dll", "System.Collections.Concurrent.dll", "System.Text.RegularExpressions.dll", - "libarc.bin.so", }; using (var b = CreateApkBuilder ()) { From f9f555636323408b1c1da0a09f266c66e704ec8a Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Thu, 17 Oct 2024 11:14:14 +0200 Subject: [PATCH 25/60] Optionally produce "empty" embed.*.s files Even though we might not have any content to embed, we need the symbols to be present, because they're part of the `libxamarin-app.so` ABI expected by `libmonodroid.so` --- .../Tasks/CreateEmbeddedAssemblyStore.cs | 3 +- .../Tasks/GeneratePackageManagerJava.cs | 29 +++++----- .../Utilities/ELFEmbeddingHelper.cs | 58 ++++++++++++++----- 3 files changed, 58 insertions(+), 32 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/CreateEmbeddedAssemblyStore.cs b/src/Xamarin.Android.Build.Tasks/Tasks/CreateEmbeddedAssemblyStore.cs index 26c5394ff9e..288f52be3db 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/CreateEmbeddedAssemblyStore.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/CreateEmbeddedAssemblyStore.cs @@ -84,7 +84,8 @@ public override bool RunTask () AndroidBinUtilsDirectory, inputFile, ELFEmbeddingHelper.KnownEmbedItems.AssemblyStore, - AssemblySourcesDir + AssemblySourcesDir, + missingContentOK: false ); if (items.Count == 0) { diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/GeneratePackageManagerJava.cs b/src/Xamarin.Android.Build.Tasks/Tasks/GeneratePackageManagerJava.cs index 20c501d58ac..72ed235721a 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/GeneratePackageManagerJava.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/GeneratePackageManagerJava.cs @@ -62,7 +62,9 @@ public override bool RunTask () [Required] public bool EnablePreloadAssembliesDefault { get; set; } - [Required] + // This property should be required but it can't, because during design time builds there's no + // value to pass and MSBuild signals an error that a required property wasn't given a value. + //[Required] public string AndroidBinUtilsDirectory { get; set; } [Required] @@ -318,20 +320,17 @@ void AddEnvironment () var dest = Path.GetFullPath (Path.Combine (OutputDirectory, "MonoPackageManager_Resources.java")); bool haveRuntimeConfigBlob = !String.IsNullOrEmpty (RuntimeConfigBinFilePath) && File.Exists (RuntimeConfigBinFilePath); - if (haveRuntimeConfigBlob) { - List objectFilePaths = ELFEmbeddingHelper.EmbedBinary ( - Log, - SupportedAbis, - AndroidBinUtilsDirectory, - RuntimeConfigBinFilePath, - ELFEmbeddingHelper.KnownEmbedItems.RuntimeConfig, - EnvironmentOutputDirectory - ); - - EmbeddedObjectFiles = objectFilePaths.ToArray (); - } else { - EmbeddedObjectFiles = Array.Empty (); - } + List objectFilePaths = ELFEmbeddingHelper.EmbedBinary ( + Log, + SupportedAbis, + AndroidBinUtilsDirectory, + RuntimeConfigBinFilePath, + ELFEmbeddingHelper.KnownEmbedItems.RuntimeConfig, + EnvironmentOutputDirectory, + missingContentOK: !haveRuntimeConfigBlob + ); + + EmbeddedObjectFiles = objectFilePaths.ToArray (); var jniRemappingNativeCodeInfo = BuildEngine4.GetRegisteredTaskObjectAssemblyLocal (ProjectSpecificTaskObjectKey (GenerateJniRemappingNativeCode.JniRemappingNativeCodeInfoKey), RegisteredTaskObjectLifetime.Build); var appConfigAsmGen = new ApplicationConfigNativeAssemblyGenerator (environmentVariables, systemProperties, Log) { diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/ELFEmbeddingHelper.cs b/src/Xamarin.Android.Build.Tasks/Utilities/ELFEmbeddingHelper.cs index 56f399913f2..9116cabcd58 100644 --- a/src/Xamarin.Android.Build.Tasks/Utilities/ELFEmbeddingHelper.cs +++ b/src/Xamarin.Android.Build.Tasks/Utilities/ELFEmbeddingHelper.cs @@ -62,9 +62,10 @@ public static List EmbedBinary ( TaskLoggingHelper log, ICollection supportedAbis, string androidBinUtilsDirectory, - string inputFile, + string? inputFile, EmbedItem embedItem, - string outputDirectory) + string outputDirectory, + bool missingContentOK) { if (supportedAbis.Count < 1) { throw new ArgumentException ("At least one target ABI must be present", nameof (supportedAbis)); @@ -80,7 +81,8 @@ public static List EmbedBinary ( abi, inputFile, outputDirectory, - embedItem + embedItem, + missingContentOK ); } @@ -91,9 +93,10 @@ public static List EmbedBinary ( TaskLoggingHelper log, string abi, string androidBinUtilsDirectory, - string inputFile, + string? inputFile, EmbedItem embedItem, - string outputDirectory) + string outputDirectory, + bool missingContentOK) { if (String.IsNullOrEmpty (abi)) { throw new ArgumentException ("Must be a supported ABI name", nameof (abi)); @@ -107,7 +110,8 @@ public static List EmbedBinary ( abi, inputFile, outputDirectory, - embedItem + embedItem, + missingContentOK ); return ret; } @@ -119,10 +123,11 @@ static void EmbedBinary ( string abi, string inputFile, string outputDirectory, - EmbedItem embedItem) + EmbedItem embedItem, + bool missingContentOK) { string outputFile = Path.Combine (outputDirectory, $"embed_{embedItem.BaseFileName}.{abi.ToLowerInvariant ()}.o"); - DoEmbed (log, MonoAndroidHelper.AbiToTargetArch (abi), llvmMcPath, inputFile, outputFile, embedItem); + DoEmbed (log, MonoAndroidHelper.AbiToTargetArch (abi), llvmMcPath, inputFile, outputFile, embedItem, missingContentOK); if (!File.Exists (outputFile)) { return; } @@ -137,33 +142,54 @@ static void DoEmbed ( TaskLoggingHelper log, AndroidTargetArch arch, string llvmMcPath, - string inputFile, + string? inputFile, string outputFile, - EmbedItem item) + EmbedItem item, + bool missingContentOK) { if (!llvmMcConfigs.TryGetValue (arch, out LlvmMcTargetConfig cfg)) { throw new NotSupportedException ($"Internal error: unsupported target arch '{arch}'"); } - inputFile = Path.GetFullPath (inputFile); + bool haveInputFile = !String.IsNullOrEmpty (inputFile); + if (!haveInputFile) { + if (!missingContentOK) { + throw new InvalidOperationException ("Internal error: input file must be specified"); + } + } else { + inputFile = Path.GetFullPath (inputFile); + } outputFile = Path.GetFullPath (outputFile); - var fi = new FileInfo (inputFile); - long inputFileSize = fi.Length; + long inputFileSize = 0; + string? sanitizedInputFilePath = null; + + if (haveInputFile) { + var fi = new FileInfo (inputFile); + if (fi.Exists) { + inputFileSize = fi.Length; + sanitizedInputFilePath = inputFile.Replace ("\\", "\\\\"); + } else if (!missingContentOK) { + throw new InvalidOperationException ($"Internal error: input file '{inputFile}' does not exist"); + } + } + string asmInputFile = Path.ChangeExtension (outputFile, ".s"); - string sanitizedInputFilePath = inputFile.Replace ("\\", "\\\\"); using var fs = File.Open (asmInputFile, FileMode.Create, FileAccess.Write, FileShare.Read); using var sw = new StreamWriter (fs, asmFileEncoding); string symbolName = item.SymbolName; sw.WriteLine ($".section .rodata,\"a\",{cfg.AssemblerDirectivePrefix}progbits"); - sw.WriteLine (".p2align 3, 0x00"); // Put the data at 4k boundary + sw.WriteLine (".p2align 3, 0x00"); // Put the data at the 4k boundary sw.WriteLine (); sw.WriteLine ($".global {symbolName}"); sw.WriteLine ($".type {symbolName},{cfg.AssemblerDirectivePrefix}object"); sw.WriteLine ($"{symbolName}:"); - sw.WriteLine ($"\t.incbin \"{sanitizedInputFilePath}\""); + + if (!String.IsNullOrEmpty (sanitizedInputFilePath)) { + sw.WriteLine ($"\t.incbin \"{sanitizedInputFilePath}\""); + } sw.WriteLine ($"\t.size {symbolName}, {inputFileSize}"); sw.WriteLine (); From b04f22eff91c96186990fc413fcbd9962232be08 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Thu, 17 Oct 2024 11:31:59 +0200 Subject: [PATCH 26/60] Don't embed assembly store when fastdev is used --- src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets index 038628923a1..62a3adba302 100644 --- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets +++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets @@ -361,7 +361,7 @@ Copyright (C) 2011-2012 Xamarin. All rights reserved. <_AndroidUseMarshalMethods Condition=" '$(AndroidIncludeDebugSymbols)' == 'True' ">False <_AndroidUseMarshalMethods Condition=" '$(AndroidIncludeDebugSymbols)' != 'True' ">$(AndroidEnableMarshalMethods) - <_AndroidEmbedAssemblyStoreInRuntime Condition=" '$(AndroidUseAssemblyStore)' == 'True' And '$(_AndroidEmbedAssemblyStoreInRuntime)' == '' ">True + <_AndroidEmbedAssemblyStoreInRuntime Condition=" '$(AndroidUseAssemblyStore)' == 'True' And '$(EmbedAssembliesIntoApk)' == 'true' And '$(_AndroidEmbedAssemblyStoreInRuntime)' == '' ">True <_AndroidEmbedAssemblyStoreInRuntime Condition="'$(_AndroidEmbedAssemblyStoreInRuntime)' == '' ">False From d53f711a93ca30312070570c68f0203ac2a105fe Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Thu, 17 Oct 2024 13:24:11 +0200 Subject: [PATCH 27/60] Let's see if designer tests pass now --- .../Tasks/GeneratePackageManagerJava.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/GeneratePackageManagerJava.cs b/src/Xamarin.Android.Build.Tasks/Tasks/GeneratePackageManagerJava.cs index 72ed235721a..7c651a4155b 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/GeneratePackageManagerJava.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/GeneratePackageManagerJava.cs @@ -62,12 +62,11 @@ public override bool RunTask () [Required] public bool EnablePreloadAssembliesDefault { get; set; } - // This property should be required but it can't, because during design time builds there's no - // value to pass and MSBuild signals an error that a required property wasn't given a value. + // These two properties should be required but they will require modifying `monodroid` first //[Required] public string AndroidBinUtilsDirectory { get; set; } - [Required] + //[Required] public bool AssemblyStoreEmbeddedInRuntime { get; set; } [Output] From 1070f1cdde0a1d81b02373cf56791f560622b92d Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Fri, 18 Oct 2024 12:40:36 +0200 Subject: [PATCH 28/60] Expect the unexpected, DTB doesn't specify any ABIs --- .../Utilities/ELFEmbeddingHelper.cs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/ELFEmbeddingHelper.cs b/src/Xamarin.Android.Build.Tasks/Utilities/ELFEmbeddingHelper.cs index 9116cabcd58..e58f2b94d5e 100644 --- a/src/Xamarin.Android.Build.Tasks/Utilities/ELFEmbeddingHelper.cs +++ b/src/Xamarin.Android.Build.Tasks/Utilities/ELFEmbeddingHelper.cs @@ -3,6 +3,7 @@ using System.IO; using System.Text; +using Microsoft.Android.Build.Tasks; using Microsoft.Build.Framework; using Microsoft.Build.Utilities; using Xamarin.Android.Tools; @@ -67,12 +68,13 @@ public static List EmbedBinary ( string outputDirectory, bool missingContentOK) { + var ret = new List (); if (supportedAbis.Count < 1) { - throw new ArgumentException ("At least one target ABI must be present", nameof (supportedAbis)); + log.LogDebugMessage ("ELFEmbeddingHelper: at least one target ABI must be specified. Probably a DTB build, skipping generation."); + return ret; } string llvmMcPath = GetLlvmMcPath (androidBinUtilsDirectory); - var ret = new List (); foreach (string abi in supportedAbis) { EmbedBinary ( log, @@ -98,11 +100,12 @@ public static List EmbedBinary ( string outputDirectory, bool missingContentOK) { + var ret = new List (); if (String.IsNullOrEmpty (abi)) { - throw new ArgumentException ("Must be a supported ABI name", nameof (abi)); + log.LogDebugMessage ("ELFEmbeddingHelper: ABI must be specified. Probably a DTB build, skipping generation."); + return ret; } - var ret = new List (); EmbedBinary ( log, ret, From 91f740f2251868dc464ea85eec0b7cea3a30d829 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Fri, 18 Oct 2024 19:31:34 +0200 Subject: [PATCH 29/60] [WIP] Builds but doesn't work --- ...crosoft.Android.Sdk.AssemblyStores.targets | 7 +- .../Tasks/CompileNativeAssembly.cs | 21 +- ...teCompressedAssembliesNativeSourceFiles.cs | 2 +- .../Tasks/GeneratePackageManagerJava.cs | 2 +- .../Tasks/PrepareAbiItems.cs | 37 +--- .../Utilities/AssemblyCompression.cs | 5 +- .../Utilities/ELFEmbeddingHelper.cs | 10 +- .../Utilities/MonoAndroidHelper.cs | 19 +- .../Utilities/NativeAssemblerCompilation.cs | 199 ++++++++++++++++++ .../Utilities/NativeAssemblerItemsHelper.cs | 65 ++++++ .../Xamarin.Android.Common.targets | 86 +++----- .../AssemblyStore/StoreReader_V2.cs | 10 +- 12 files changed, 339 insertions(+), 124 deletions(-) create mode 100644 src/Xamarin.Android.Build.Tasks/Utilities/NativeAssemblerCompilation.cs create mode 100644 src/Xamarin.Android.Build.Tasks/Utilities/NativeAssemblerItemsHelper.cs diff --git a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.AssemblyStores.targets b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.AssemblyStores.targets index c7185129668..dee4e5d46be 100644 --- a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.AssemblyStores.targets +++ b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.AssemblyStores.targets @@ -7,13 +7,17 @@ <_EmbeddedAssemblyStoreObjectFile Include="$(_NativeAssemblySourceDir)embed_assembly_store.%(_BuildTargetAbis.Identity).o" /> + + + <_EmbeddedAssemblyStoreSourceFiles Include="@(_EmbeddedAssemblyStoreObjectFile->'$([System.IO.Path]::ChangeExtension('%(Identity)', '.s'))')" /> + + Outputs="@(_EmbeddedAssemblyStoreObjectFile);@(_EmbeddedAssemblyStoreSourceFiles)"> - diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/CompileNativeAssembly.cs b/src/Xamarin.Android.Build.Tasks/Tasks/CompileNativeAssembly.cs index 9d6d324f678..1504b5b6562 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/CompileNativeAssembly.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/CompileNativeAssembly.cs @@ -99,9 +99,24 @@ void RunAssembler (Config config) } } + static readonly List llcArguments = new () { + "-O2", + "--debugger-tune=lldb", // NDK uses lldb now + "--debugify-level=location+variables", + "--fatal-warnings", + "--filetype=obj", + "--relocation-model=pic", + }; + + static readonly List llvmMcArguments = new () { + "--assemble", + "--filetype=obj", + "-g", + }; + IEnumerable GetAssemblerConfigs () { - const string assemblerOptions = + const string llcOptions = "-O2 " + "--debugger-tune=lldb " + // NDK uses lldb now "--debugify-level=location+variables " + @@ -113,14 +128,14 @@ IEnumerable GetAssemblerConfigs () foreach (ITaskItem item in Sources) { // We don't need the directory since our WorkingDirectory is where all the sources are string sourceFile = Path.GetFileName (item.ItemSpec); - string outputFile = QuoteFileName (sourceFile.Replace (".ll", ".o")); + string outputFile = QuoteFileName (Path.ChangeExtension (sourceFile, ".o")); string executableDir = Path.GetDirectoryName (llcPath); string executableName = MonoAndroidHelper.GetExecutablePath (executableDir, Path.GetFileName (llcPath)); yield return new Config { InputSource = item.ItemSpec, AssemblerPath = Path.Combine (executableDir, executableName), - AssemblerOptions = $"{assemblerOptions} -o={outputFile} {QuoteFileName (sourceFile)}", + AssemblerOptions = $"{llcOptions} -o={outputFile} {QuoteFileName (sourceFile)}", }; } } diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/GenerateCompressedAssembliesNativeSourceFiles.cs b/src/Xamarin.Android.Build.Tasks/Tasks/GenerateCompressedAssembliesNativeSourceFiles.cs index fd6b78fcebd..be5346385bf 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/GenerateCompressedAssembliesNativeSourceFiles.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/GenerateCompressedAssembliesNativeSourceFiles.cs @@ -66,7 +66,7 @@ void GenerateCompressedAssemblySources () var assemblyKey = CompressedAssemblyInfo.GetDictionaryKey (assembly); if (assemblies.ContainsKey (assemblyKey)) { - Log.LogDebugMessage ($"Skipping duplicate assembly: {assembly.ItemSpec} (arch {MonoAndroidHelper.GetAssemblyAbi(assembly)})"); + Log.LogDebugMessage ($"Skipping duplicate assembly: {assembly.ItemSpec} (arch {MonoAndroidHelper.GetItemAbi(assembly)})"); continue; } diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/GeneratePackageManagerJava.cs b/src/Xamarin.Android.Build.Tasks/Tasks/GeneratePackageManagerJava.cs index 7c651a4155b..d3f79f66af1 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/GeneratePackageManagerJava.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/GeneratePackageManagerJava.cs @@ -249,7 +249,7 @@ void AddEnvironment () uniqueAssemblyNames.Add (assemblyName); } - string abi = MonoAndroidHelper.GetAssemblyAbi (assembly); + string abi = MonoAndroidHelper.GetItemAbi (assembly); archAssemblyNames ??= new HashSet (StringComparer.OrdinalIgnoreCase); if (!archAssemblyNames.Contains (assemblyName)) { diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/PrepareAbiItems.cs b/src/Xamarin.Android.Build.Tasks/Tasks/PrepareAbiItems.cs index cad5439df21..41328dbf299 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/PrepareAbiItems.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/PrepareAbiItems.cs @@ -1,5 +1,3 @@ -using System; -using System.IO; using System.Collections.Generic; using Microsoft.Build.Framework; @@ -10,13 +8,6 @@ namespace Xamarin.Android.Tasks { public class PrepareAbiItems : AndroidTask { - const string ArmV7a = "armeabi-v7a"; - const string TypeMapBase = "typemaps"; - const string EnvBase = "environment"; - const string CompressedAssembliesBase = "compressed_assemblies"; - const string JniRemappingBase = "jni_remap"; - const string MarshalMethodsBase = "marshal_methods"; - public override string TaskPrefix => "PAI"; [Required] @@ -28,45 +19,23 @@ public class PrepareAbiItems : AndroidTask [Required] public string Mode { get; set; } = ""; - [Required] - public bool Debug { get; set; } - [Output] public ITaskItem[]? AssemblySources { get; set; } - [Output] - public ITaskItem[]? AssemblyIncludes { get; set; } - public override bool RunTask () { var sources = new List (); - var includes = new List (); - string baseName; - - if (String.Compare ("typemap", Mode, StringComparison.OrdinalIgnoreCase) == 0) { - baseName = TypeMapBase; - } else if (String.Compare ("environment", Mode, StringComparison.OrdinalIgnoreCase) == 0) { - baseName = EnvBase; - } else if (String.Compare ("compressed", Mode, StringComparison.OrdinalIgnoreCase) == 0) { - baseName = CompressedAssembliesBase; - } else if (String.Compare ("jniremap", Mode, StringComparison.OrdinalIgnoreCase) == 0) { - baseName = JniRemappingBase; - } else if (String.Compare ("marshal_methods", Mode, StringComparison.OrdinalIgnoreCase) == 0) { - baseName = MarshalMethodsBase; - } else { - Log.LogError ($"Unknown mode: {Mode}"); - return false; - } TaskItem item; + NativeAssemblerItemsHelper.KnownMode mode = NativeAssemblerItemsHelper.ToKnownMode (Mode); foreach (string abi in BuildTargetAbis) { - item = new TaskItem (Path.Combine (NativeSourcesDir, $"{baseName}.{abi}.ll")); + item = new TaskItem (NativeAssemblerItemsHelper.GetSourcePath (Log, mode, NativeSourcesDir, abi)); item.SetMetadata ("abi", abi); + item.SetMetadata ("RuntimeIdentifier", MonoAndroidHelper.AbiToRid (abi)); sources.Add (item); } AssemblySources = sources.ToArray (); - AssemblyIncludes = includes.ToArray (); return !Log.HasLoggedErrors; } } diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/AssemblyCompression.cs b/src/Xamarin.Android.Build.Tasks/Utilities/AssemblyCompression.cs index 9ef32a4dcb8..af7f97cdcd5 100644 --- a/src/Xamarin.Android.Build.Tasks/Utilities/AssemblyCompression.cs +++ b/src/Xamarin.Android.Build.Tasks/Utilities/AssemblyCompression.cs @@ -170,9 +170,8 @@ static string GetCompressedAssemblyOutputDirectory (ITaskItem assembly, string c { string assemblyOutputDir; string subDirectory = assembly.GetMetadata ("DestinationSubDirectory"); - string abi = MonoAndroidHelper.GetAssemblyAbi (assembly); - - if (!string.IsNullOrEmpty (subDirectory) && !(subDirectory.EndsWith ($"{abi}/", StringComparison.Ordinal) || subDirectory.EndsWith ($"{abi}\\", StringComparison.Ordinal))) { + string abi = MonoAndroidHelper.GetItemAbi (assembly); + if (!String.IsNullOrEmpty (subDirectory) && !(subDirectory.EndsWith ($"{abi}/", StringComparison.Ordinal) || subDirectory.EndsWith ($"{abi}\\", StringComparison.Ordinal))) { assemblyOutputDir = Path.Combine (compressedOutputDir, abi, subDirectory); } else { assemblyOutputDir = Path.Combine (compressedOutputDir, abi); diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/ELFEmbeddingHelper.cs b/src/Xamarin.Android.Build.Tasks/Utilities/ELFEmbeddingHelper.cs index e58f2b94d5e..714269b37b7 100644 --- a/src/Xamarin.Android.Build.Tasks/Utilities/ELFEmbeddingHelper.cs +++ b/src/Xamarin.Android.Build.Tasks/Utilities/ELFEmbeddingHelper.cs @@ -215,10 +215,12 @@ static void DoEmbed ( MonoAndroidHelper.QuoteFileNameArgument (asmInputFile), }; - int ret = MonoAndroidHelper.RunProcess (llvmMcPath, String.Join (" ", args), log); - if (ret != 0) { - return; - } + // int ret = MonoAndroidHelper.RunProcess (llvmMcPath, String.Join (" ", args), log); + // File.Copy (asmInputFile, $"/tmp/{Path.GetFileName (asmInputFile)}", true); + // File.Copy (outputFile, $"/tmp/{Path.GetFileName (outputFile)}", true); + // if (ret != 0) { + // return; + // } } static string GetLlvmMcPath (string androidBinUtilsDirectory) => MonoAndroidHelper.GetLlvmMcPath (androidBinUtilsDirectory); diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/MonoAndroidHelper.cs b/src/Xamarin.Android.Build.Tasks/Utilities/MonoAndroidHelper.cs index 9276ba600ca..7724a979335 100644 --- a/src/Xamarin.Android.Build.Tasks/Utilities/MonoAndroidHelper.cs +++ b/src/Xamarin.Android.Build.Tasks/Utilities/MonoAndroidHelper.cs @@ -568,29 +568,17 @@ public static int ConvertSupportedOSPlatformVersionToApiLevel (string version) } #if MSBUILD - public static string GetAssemblyAbi (ITaskItem asmItem) + public static string GetItemAbi (ITaskItem asmItem) { string? abi = asmItem.GetMetadata ("Abi"); if (String.IsNullOrEmpty (abi)) { - throw new InvalidOperationException ($"Internal error: assembly '{asmItem}' lacks ABI metadata"); + throw new InvalidOperationException ($"Internal error: item '{asmItem}' lacks ABI metadata"); } return abi; } - public static AndroidTargetArch GetTargetArch (ITaskItem asmItem) => AbiToTargetArch (GetAssemblyAbi (asmItem)); - - - public static AndroidTargetArch GetRequiredValidArchitecture (ITaskItem item) - { - AndroidTargetArch ret = GetTargetArch (item); - - if (ret == AndroidTargetArch.None) { - throw new InvalidOperationException ($"Internal error: assembly '{item}' doesn't target any architecture."); - } - - return ret; - } + public static AndroidTargetArch GetTargetArch (ITaskItem asmItem) => AbiToTargetArch (GetItemAbi (asmItem)); #endif // MSBUILD static string GetToolsRootDirectoryRelativePath (string androidBinUtilsDirectory) @@ -785,6 +773,7 @@ public static string QuoteFileNameArgument (string? fileName) public static string GetLlvmObjcopyPath (string androidBinUtilsDirectory) => GetBinUtilsToolPath (androidBinUtilsDirectory, "llvm-objcopy"); public static string GetLlvmMcPath (string androidBinUtilsDirectory) => GetBinUtilsToolPath (androidBinUtilsDirectory, "llvm-mc"); + public static string GetLlvmLlcPath (string androidBinUtilsDirectory) => GetBinUtilsToolPath (androidBinUtilsDirectory, "llc"); static string GetBinUtilsToolPath (string androidBinUtilsDirectory, string toolName) { diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/NativeAssemblerCompilation.cs b/src/Xamarin.Android.Build.Tasks/Utilities/NativeAssemblerCompilation.cs new file mode 100644 index 00000000000..78a3b33d90e --- /dev/null +++ b/src/Xamarin.Android.Build.Tasks/Utilities/NativeAssemblerCompilation.cs @@ -0,0 +1,199 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Threading; + +using Microsoft.Android.Build.Tasks; +using Microsoft.Build.Framework; +using Microsoft.Build.Utilities; +using Xamarin.Android.Tools; + +namespace Xamarin.Android.Tasks; + +class NativeAssemblerCompilation +{ + public sealed class AssemblerConfig + { + public readonly string ExecutablePath; + public readonly string Options; + public readonly string InputSource; + + public AssemblerConfig (string executablePath, string options, string inputSource) + { + ExecutablePath = executablePath; + Options = options; + InputSource = inputSource; + } + } + + public sealed class AssemblerRunContext + { + public readonly TaskLoggingHelper Log; + public readonly Action? RegisterForCancellation; + public readonly Action? Cancel; + public readonly string? WorkingDirectory; + + public AssemblerRunContext (TaskLoggingHelper log, string? workingDirectory = null, Action? registerForCancellation = null, Action? cancel = null) + { + Log = log; + RegisterForCancellation = registerForCancellation; + Cancel = cancel; + WorkingDirectory = workingDirectory; + } + } + + public sealed class LlvmMcTargetConfig + { + public readonly string TargetArch; + public readonly string TripleArch; + public readonly string TripleApiPrefix; + public readonly string AssemblerDirectivePrefix; + public readonly string SizeType; + public readonly uint WordSize; + + public LlvmMcTargetConfig (string targetArch, string tripleArch, string tripleApiPrefix, string assemblerDirectivePrefix, string sizeType, uint wordSize) + { + TargetArch = targetArch; + TripleArch = tripleArch; + TripleApiPrefix = tripleApiPrefix; + AssemblerDirectivePrefix = assemblerDirectivePrefix; + SizeType = sizeType; + WordSize = wordSize; + } + } + + static readonly Dictionary llvmMcConfigs = new () { + { AndroidTargetArch.Arm64, new ("aarch64", "aarch64", "android", "@", ".xword", 8) }, + { AndroidTargetArch.Arm, new ("arm", "armv7a", "androideabi", "%", ".long", 4) }, + { AndroidTargetArch.X86_64, new ("x86-64", "x86_64", "android", "@", ".quad", 8) }, + { AndroidTargetArch.X86, new ("x86", "i686", "android", "@", ".long", 4) }, + }; + + static readonly List llcArguments = new () { + "-O2", + "--debugger-tune=lldb", // NDK uses lldb now + "--debugify-level=location+variables", + "--fatal-warnings", + "--filetype=obj", + "--relocation-model=pic", + }; + + static readonly List llvmMcArguments = new () { + "--assemble", + "--filetype=obj", + "-g", + }; + + public static AssemblerConfig GetAssemblerConfig (string androidBinUtilsDir, ITaskItem source, bool stripFilePaths) + { + string sourceFile = stripFilePaths ? Path.GetFileName (source.ItemSpec) : source.ItemSpec; + string sourceExtension = Path.GetExtension (sourceFile); + string executable; + var arguments = new List (); + + if (String.Compare (".ll", sourceExtension, StringComparison.OrdinalIgnoreCase) == 0) { + executable = MonoAndroidHelper.GetLlvmLlcPath (androidBinUtilsDir); + arguments.AddRange (llcArguments); + } else if (String.Compare (".s", sourceExtension, StringComparison.OrdinalIgnoreCase) == 0) { + executable = MonoAndroidHelper.GetLlvmMcPath (androidBinUtilsDir); + arguments.AddRange (llvmMcArguments); + + LlvmMcTargetConfig cfg = GetLlvmMcConfig (MonoAndroidHelper.GetTargetArch (source)); + arguments.Add ($"--arch={cfg.TargetArch}"); + arguments.Add ($"--triple={cfg.TripleArch}-linux-{cfg.TripleApiPrefix}{XABuildConfig.AndroidMinimumDotNetApiLevel}"); + } else { + throw new InvalidOperationException ($"Internal exception: unknown native assembler source {source.ItemSpec}"); + } + + string outputFile = Path.ChangeExtension (sourceFile, ".o"); + arguments.Add ("-o"); + arguments.Add (MonoAndroidHelper.QuoteFileNameArgument (outputFile)); + arguments.Add (MonoAndroidHelper.QuoteFileNameArgument (sourceFile)); + + return new AssemblerConfig (executable, String.Join (" ", arguments), source.ItemSpec); + } + + public static LlvmMcTargetConfig GetLlvmMcConfig (AndroidTargetArch arch) + { + if (!llvmMcConfigs.TryGetValue (arch, out LlvmMcTargetConfig cfg)) { + throw new NotSupportedException ($"Internal error: unsupported target arch '{arch}'"); + } + + return cfg; + } + + public static void RunAssembler (AssemblerRunContext context, AssemblerConfig config) + { + var stdout_completed = new ManualResetEvent (false); + var stderr_completed = new ManualResetEvent (false); + var psi = new ProcessStartInfo () { + FileName = config.ExecutablePath, + Arguments = config.Options, + UseShellExecute = false, + RedirectStandardOutput = true, + RedirectStandardError = true, + CreateNoWindow = true, + WindowStyle = ProcessWindowStyle.Hidden, + WorkingDirectory = context.WorkingDirectory, + }; + + string assemblerName = Path.GetFileName (config.ExecutablePath); + context.Log.LogDebugMessage ($"[{assemblerName}] {psi.FileName} {psi.Arguments}"); + + var stdoutLines = new List (); + var stderrLines = new List (); + + using var proc = new Process (); + proc.OutputDataReceived += (s, e) => { + if (e.Data != null) { + OnOutputData (context, assemblerName, s, e); + stdoutLines.Add (e.Data); + } else + stdout_completed.Set (); + }; + + proc.ErrorDataReceived += (s, e) => { + if (e.Data != null) { + OnErrorData (context, assemblerName, s, e); + stderrLines.Add (e.Data); + } else + stderr_completed.Set (); + }; + + proc.StartInfo = psi; + proc.Start (); + proc.BeginOutputReadLine (); + proc.BeginErrorReadLine (); + + if (context.RegisterForCancellation != null) { + context.RegisterForCancellation (proc); + } + + proc.WaitForExit (); + + if (psi.RedirectStandardError) { + stderr_completed.WaitOne (TimeSpan.FromSeconds (30)); + } + + if (psi.RedirectStandardOutput) { + stdout_completed.WaitOne (TimeSpan.FromSeconds (30)); + } + + if (proc.ExitCode != 0) { + var sb = MonoAndroidHelper.MergeStdoutAndStderrMessages (stdoutLines, stderrLines); + context.Log.LogCodedError ("XA3006", Properties.Resources.XA3006, Path.GetFileName (config.InputSource), sb.ToString ()); + context.Cancel?.Invoke (); + } + } + + static void OnOutputData (AssemblerRunContext context, string assemblerName, object sender, DataReceivedEventArgs e) + { + context.Log.LogDebugMessage ($"[{assemblerName} stdout] {e.Data}"); + } + + static void OnErrorData (AssemblerRunContext context, string assemblerName, object sender, DataReceivedEventArgs e) + { + context.Log.LogMessage ($"[{assemblerName} stderr] {e.Data}", MessageImportance.High); + } +} diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/NativeAssemblerItemsHelper.cs b/src/Xamarin.Android.Build.Tasks/Utilities/NativeAssemblerItemsHelper.cs new file mode 100644 index 00000000000..6f2df37c30a --- /dev/null +++ b/src/Xamarin.Android.Build.Tasks/Utilities/NativeAssemblerItemsHelper.cs @@ -0,0 +1,65 @@ +using System; +using System.Collections.Generic; +using System.IO; + +using Microsoft.Build.Utilities; + +namespace Xamarin.Android.Tasks; + +static class NativeAssemblerItemsHelper +{ + public enum KnownMode + { + CompressedAssemblies, + EmbeddedAssemblyStore, + EmbeddedRuntimeConfig, + Environment, + JNIRemap, + MarshalMethods, + TypeMap, + } + + sealed class ModeConfig + { + public readonly string FileNameBase; + public readonly string Extension; + + public ModeConfig (string fileNameBase, string extension) + { + FileNameBase = fileNameBase; + Extension = extension; + } + } + + const string LlvmIrExtension = "ll"; + const string NativeAssemblerExtension = "s"; + + static readonly Dictionary ModeConfigs = new () { + { KnownMode.CompressedAssemblies, new ("compressed_assemblies", LlvmIrExtension) }, + { KnownMode.EmbeddedAssemblyStore, new ("embed_assembly_store", NativeAssemblerExtension) }, + { KnownMode.EmbeddedRuntimeConfig, new ("embed_runtime_config", NativeAssemblerExtension) }, + { KnownMode.Environment, new ("environment", LlvmIrExtension) }, + { KnownMode.JNIRemap, new ("jni_remap", LlvmIrExtension) }, + { KnownMode.MarshalMethods, new ("marshal_methods", LlvmIrExtension) }, + { KnownMode.TypeMap, new ("typemaps", LlvmIrExtension) }, + }; + + public static string? GetSourcePath (TaskLoggingHelper log, KnownMode mode, string nativeSourcesDir, string abi) + { + if (!ModeConfigs.TryGetValue (mode, out ModeConfig config)) { + log.LogError ($"Unknown mode: {mode}"); + return null; + } + + return Path.Combine (nativeSourcesDir, $"{config.FileNameBase}.{abi.ToLowerInvariant ()}.{config.Extension}"); + } + + public static KnownMode ToKnownMode (string mode) + { + if (!Enum.TryParse (mode, ignoreCase: true, out KnownMode result)) { + throw new InvalidOperationException ($"Internal exception: uknown native assembler generator mode '{mode}'"); + } + + return result; + } +} diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets index 62a3adba302..15c55742b7b 100644 --- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets +++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets @@ -1534,10 +1534,8 @@ because xbuild doesn't support framework reference assemblies. + Mode="TypeMap"> - @@ -1680,7 +1678,6 @@ because xbuild doesn't support framework reference assemblies. - @@ -1752,24 +1749,27 @@ because xbuild doesn't support framework reference assemblies. + Mode="Environment"> + Mode="CompressedAssemblies"> + Mode="MarshalMethods"> + + + @@ -1794,8 +1794,7 @@ because xbuild doesn't support framework reference assemblies. + Mode="JNIRemap"> @@ -1908,54 +1907,11 @@ because xbuild doesn't support framework reference assemblies. EnableMarshalMethods="$(_AndroidUseMarshalMethods)" CustomBundleConfigFile="$(AndroidBundleConfigurationFile)" AndroidBinUtilsDirectory="$(AndroidBinUtilsDirectory)" - AssemblyStoreEmbeddedInRuntime="$(_AndroidEmbedAssemblyStoreInRuntime)" - > - - - - - - - - - + AssemblyStoreEmbeddedInRuntime="$(_AndroidEmbedAssemblyStoreInRuntime)" /> - + @@ -2181,6 +2137,18 @@ because xbuild doesn't support framework reference assemblies. <_NativeAssemblyTarget Include="@(_AndroidRemapAssemblySource->'$([System.IO.Path]::ChangeExtension('%(Identity)', '.o'))')"> %(_AndroidRemapAssemblySource.abi) + <_NativeAssemblyTarget Include="@(_EmbeddedRuntimeConfigAssemblySource->'$([System.IO.Path]::ChangeExtension('%(Identity)', '.o'))')"> + %(_EmbeddedRuntimeConfigAssemblySource.abi) + + + + + <_NativeAssemblySource Include="@(_AndroidRemapAssemblySource)" /> + <_NativeAssemblySource Include="@(_CompressedAssembliesAssemblySource)" /> + <_NativeAssemblySource Include="@(_EmbeddedRuntimeConfigAssemblySource)" /> + <_NativeAssemblySource Include="@(_EnvironmentAssemblySource)" /> + <_NativeAssemblySource Include="@(_MarshalMethodsAssemblySource)" /> + <_NativeAssemblySource Include="@(_TypeMapAssemblySource)" /> @@ -2200,10 +2168,10 @@ because xbuild doesn't support framework reference assemblies. 0) { + StoreStream.Seek ((long)elfOffset, SeekOrigin.Begin); + magic = reader.ReadUInt32 (); + } else { + return false; + } } if (magic != Utils.ASSEMBLY_STORE_MAGIC) { From 525dd96957fa167e0771e03aa29a4c7cbb61460c Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Mon, 21 Oct 2024 21:14:13 +0200 Subject: [PATCH 30/60] Let's see how it works now --- ...crosoft.Android.Sdk.AssemblyStores.targets | 22 ++- .../Tasks/CompileNativeAssembly.cs | 139 +++--------------- .../Tasks/CreateEmbeddedAssemblyStore.cs | 26 +--- .../Tasks/GeneratePackageManagerJava.cs | 7 +- .../Utilities/ELFEmbeddingHelper.cs | 118 +++------------ .../Utilities/NativeAssemblerCompilation.cs | 11 +- .../Utilities/NativeAssemblerItemsHelper.cs | 6 + .../Xamarin.Android.Common.targets | 8 +- 8 files changed, 65 insertions(+), 272 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.AssemblyStores.targets b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.AssemblyStores.targets index dee4e5d46be..c47516065c0 100644 --- a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.AssemblyStores.targets +++ b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.AssemblyStores.targets @@ -1,23 +1,22 @@ + - - - <_EmbeddedAssemblyStoreObjectFile Include="$(_NativeAssemblySourceDir)embed_assembly_store.%(_BuildTargetAbis.Identity).o" /> - - - - <_EmbeddedAssemblyStoreSourceFiles Include="@(_EmbeddedAssemblyStoreObjectFile->'$([System.IO.Path]::ChangeExtension('%(Identity)', '.s'))')" /> - + + + + Outputs="@(_EmbeddedAssemblyStoreSourceFiles)"> - - - + SupportedAbis="@(_BuildTargetAbis)" /> diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/CompileNativeAssembly.cs b/src/Xamarin.Android.Build.Tasks/Tasks/CompileNativeAssembly.cs index 1504b5b6562..4bfc03d9d26 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/CompileNativeAssembly.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/CompileNativeAssembly.cs @@ -2,12 +2,8 @@ using System.Collections.Generic; using System.Diagnostics; using System.IO; -using System.Threading; using Microsoft.Build.Framework; -using Microsoft.Build.Utilities; - -using Xamarin.Android.Tools; using Microsoft.Android.Build.Tasks; namespace Xamarin.Android.Tasks @@ -16,13 +12,6 @@ public class CompileNativeAssembly : AsyncTask { public override string TaskPrefix => "CNA"; - sealed class Config - { - public string? AssemblerPath; - public string? AssemblerOptions; - public string? InputSource; - } - [Required] public ITaskItem[] Sources { get; set; } = []; @@ -37,124 +26,34 @@ sealed class Config public override System.Threading.Tasks.Task RunTaskAsync () { - return this.WhenAll (GetAssemblerConfigs (), RunAssembler); + var context = new NativeAssemblerCompilation.AssemblerRunContext ( + Log, + Path.GetFullPath (WorkingDirectory), + registerForCancellation: RegisterForCancellation, + cancel: Cancel + ); + + return this.WhenAll ( + GetAssemblerConfigs (), + (NativeAssemblerCompilation.AssemblerConfig config) => NativeAssemblerCompilation.RunAssembler (context, config) + ); } - void RunAssembler (Config config) + void RegisterForCancellation (Process proc) { - var stdout_completed = new ManualResetEvent (false); - var stderr_completed = new ManualResetEvent (false); - var psi = new ProcessStartInfo () { - FileName = config.AssemblerPath, - Arguments = config.AssemblerOptions, - UseShellExecute = false, - RedirectStandardOutput = true, - RedirectStandardError = true, - CreateNoWindow = true, - WindowStyle = ProcessWindowStyle.Hidden, - WorkingDirectory = WorkingDirectory, - }; - - string assemblerName = Path.GetFileName (config.AssemblerPath); - LogDebugMessage ($"[LLVM llc] {psi.FileName} {psi.Arguments}"); - - var stdoutLines = new List (); - var stderrLines = new List (); - - using (var proc = new Process ()) { - proc.OutputDataReceived += (s, e) => { - if (e.Data != null) { - OnOutputData (assemblerName, s, e); - stdoutLines.Add (e.Data); - } else - stdout_completed.Set (); - }; - - proc.ErrorDataReceived += (s, e) => { - if (e.Data != null) { - OnErrorData (assemblerName, s, e); - stderrLines.Add (e.Data); - } else - stderr_completed.Set (); - }; - - proc.StartInfo = psi; - proc.Start (); - proc.BeginOutputReadLine (); - proc.BeginErrorReadLine (); - CancellationToken.Register (() => { try { proc.Kill (); } catch (Exception) { } }); - proc.WaitForExit (); - - if (psi.RedirectStandardError) - stderr_completed.WaitOne (TimeSpan.FromSeconds (30)); - - if (psi.RedirectStandardOutput) - stdout_completed.WaitOne (TimeSpan.FromSeconds (30)); - - if (proc.ExitCode != 0) { - var sb = MonoAndroidHelper.MergeStdoutAndStderrMessages (stdoutLines, stderrLines); - LogCodedError ("XA3006", Properties.Resources.XA3006, Path.GetFileName (config.InputSource), sb.ToString ()); - Cancel (); + CancellationToken.Register (() => { + try { + proc.Kill (); + } catch (Exception) { } - } + }); } - static readonly List llcArguments = new () { - "-O2", - "--debugger-tune=lldb", // NDK uses lldb now - "--debugify-level=location+variables", - "--fatal-warnings", - "--filetype=obj", - "--relocation-model=pic", - }; - - static readonly List llvmMcArguments = new () { - "--assemble", - "--filetype=obj", - "-g", - }; - - IEnumerable GetAssemblerConfigs () + IEnumerable GetAssemblerConfigs () { - const string llcOptions = - "-O2 " + - "--debugger-tune=lldb " + // NDK uses lldb now - "--debugify-level=location+variables " + - "--fatal-warnings " + - "--filetype=obj " + - "--relocation-model=pic"; - string llcPath = Path.Combine (AndroidBinUtilsDirectory, "llc"); - foreach (ITaskItem item in Sources) { - // We don't need the directory since our WorkingDirectory is where all the sources are - string sourceFile = Path.GetFileName (item.ItemSpec); - string outputFile = QuoteFileName (Path.ChangeExtension (sourceFile, ".o")); - string executableDir = Path.GetDirectoryName (llcPath); - string executableName = MonoAndroidHelper.GetExecutablePath (executableDir, Path.GetFileName (llcPath)); - - yield return new Config { - InputSource = item.ItemSpec, - AssemblerPath = Path.Combine (executableDir, executableName), - AssemblerOptions = $"{llcOptions} -o={outputFile} {QuoteFileName (sourceFile)}", - }; + yield return NativeAssemblerCompilation.GetAssemblerConfig (AndroidBinUtilsDirectory, item, stripFilePaths: true); } } - - void OnOutputData (string assemblerName, object sender, DataReceivedEventArgs e) - { - LogDebugMessage ($"[{assemblerName} stdout] {e.Data}"); - } - - void OnErrorData (string assemblerName, object sender, DataReceivedEventArgs e) - { - LogMessage ($"[{assemblerName} stderr] {e.Data}", MessageImportance.High); - } - - static string QuoteFileName (string fileName) - { - var builder = new CommandLineBuilder (); - builder.AppendFileNameIfNotNull (fileName); - return builder.ToString (); - } } } diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/CreateEmbeddedAssemblyStore.cs b/src/Xamarin.Android.Build.Tasks/Tasks/CreateEmbeddedAssemblyStore.cs index 288f52be3db..2823af2c3e8 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/CreateEmbeddedAssemblyStore.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/CreateEmbeddedAssemblyStore.cs @@ -43,12 +43,6 @@ public class CreateEmbeddedAssemblyStore : AndroidTask [Required] public string [] SupportedAbis { get; set; } - [Output] - public ITaskItem[] NativeAssemblySources { get; set; } - - [Output] - public ITaskItem[] EmbeddedObjectFiles { get; set; } - public override bool RunTask () { bool compress = !Debug && EnableCompression; @@ -71,14 +65,12 @@ public override bool RunTask () // Add framework assemblies AssemblyPackagingHelper.AddAssembliesFromCollection (Log, SupportedAbis, ResolvedFrameworkAssemblies, DoAddAssembliesFromArchCollection); - var objectFiles = new List (); - var sourceFiles = new List (); Dictionary assemblyStorePaths = storeBuilder.Generate (Path.Combine (AppSharedLibrariesDir, "embedded")); foreach (var kvp in assemblyStorePaths) { string abi = MonoAndroidHelper.ArchToAbi (kvp.Key); string inputFile = kvp.Value; - List items = ELFEmbeddingHelper.EmbedBinary ( + ELFEmbeddingHelper.EmbedBinary ( Log, abi, AndroidBinUtilsDirectory, @@ -87,24 +79,8 @@ public override bool RunTask () AssemblySourcesDir, missingContentOK: false ); - - if (items.Count == 0) { - continue; - } - - objectFiles.AddRange (items); - foreach (ITaskItem objectItem in items) { - var sourceItem = new TaskItem ( - Path.ChangeExtension (objectItem.ItemSpec, ".s"), - objectItem.CloneCustomMetadata () - ); - sourceFiles.Add (sourceItem); - } } - NativeAssemblySources = sourceFiles.ToArray (); - EmbeddedObjectFiles = objectFiles.ToArray (); - return !Log.HasLoggedErrors; void DoAddAssembliesFromArchCollection (TaskLoggingHelper log, AndroidTargetArch arch, ITaskItem assembly) diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/GeneratePackageManagerJava.cs b/src/Xamarin.Android.Build.Tasks/Tasks/GeneratePackageManagerJava.cs index d3f79f66af1..1ad4ee1fb58 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/GeneratePackageManagerJava.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/GeneratePackageManagerJava.cs @@ -69,9 +69,6 @@ public override bool RunTask () //[Required] public bool AssemblyStoreEmbeddedInRuntime { get; set; } - [Output] - public ITaskItem[] EmbeddedObjectFiles { get; set; } - public bool EnableMarshalMethods { get; set; } public string RuntimeConfigBinFilePath { get; set; } public string BoundExceptionType { get; set; } @@ -319,7 +316,7 @@ void AddEnvironment () var dest = Path.GetFullPath (Path.Combine (OutputDirectory, "MonoPackageManager_Resources.java")); bool haveRuntimeConfigBlob = !String.IsNullOrEmpty (RuntimeConfigBinFilePath) && File.Exists (RuntimeConfigBinFilePath); - List objectFilePaths = ELFEmbeddingHelper.EmbedBinary ( + ELFEmbeddingHelper.EmbedBinary ( Log, SupportedAbis, AndroidBinUtilsDirectory, @@ -329,8 +326,6 @@ void AddEnvironment () missingContentOK: !haveRuntimeConfigBlob ); - EmbeddedObjectFiles = objectFilePaths.ToArray (); - var jniRemappingNativeCodeInfo = BuildEngine4.GetRegisteredTaskObjectAssemblyLocal (ProjectSpecificTaskObjectKey (GenerateJniRemappingNativeCode.JniRemappingNativeCodeInfoKey), RegisteredTaskObjectLifetime.Build); var appConfigAsmGen = new ApplicationConfigNativeAssemblyGenerator (environmentVariables, systemProperties, Log) { UsesMonoAOT = usesMonoAOT, diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/ELFEmbeddingHelper.cs b/src/Xamarin.Android.Build.Tasks/Utilities/ELFEmbeddingHelper.cs index 714269b37b7..2d6a2551765 100644 --- a/src/Xamarin.Android.Build.Tasks/Utilities/ELFEmbeddingHelper.cs +++ b/src/Xamarin.Android.Build.Tasks/Utilities/ELFEmbeddingHelper.cs @@ -4,7 +4,6 @@ using System.Text; using Microsoft.Android.Build.Tasks; -using Microsoft.Build.Framework; using Microsoft.Build.Utilities; using Xamarin.Android.Tools; @@ -16,50 +15,25 @@ public sealed class EmbedItem { public readonly string SymbolName; public readonly string BaseFileName; + public readonly NativeAssemblerItemsHelper.KnownMode NativeAssemblerMode; - public EmbedItem (string symbolName, string baseFileName) + public EmbedItem (string symbolName, string baseFileName, NativeAssemblerItemsHelper.KnownMode nativeAssemblerMode) { SymbolName = symbolName; BaseFileName = baseFileName; + NativeAssemblerMode = nativeAssemblerMode; } } public static class KnownEmbedItems { - public static readonly EmbedItem RuntimeConfig = new ("embedded_runtime_config", "runtime_config"); - public static readonly EmbedItem AssemblyStore = new ("embedded_assembly_store", "assembly_store"); + public static readonly EmbedItem RuntimeConfig = new ("embedded_runtime_config", "runtime_config", NativeAssemblerItemsHelper.KnownMode.EmbeddedRuntimeConfig); + public static readonly EmbedItem AssemblyStore = new ("embedded_assembly_store", "assembly_store", NativeAssemblerItemsHelper.KnownMode.EmbeddedAssemblyStore); } - sealed class LlvmMcTargetConfig - { - public readonly string TargetArch; - public readonly string TripleArch; - public readonly string TripleApiPrefix; - public readonly string AssemblerDirectivePrefix; - public readonly string SizeType; - public readonly uint WordSize; - - public LlvmMcTargetConfig (string targetArch, string tripleArch, string tripleApiPrefix, string assemblerDirectivePrefix, string sizeType, uint wordSize) - { - TargetArch = targetArch; - TripleArch = tripleArch; - TripleApiPrefix = tripleApiPrefix; - AssemblerDirectivePrefix = assemblerDirectivePrefix; - SizeType = sizeType; - WordSize = wordSize; - } - } - - static readonly Dictionary llvmMcConfigs = new () { - { AndroidTargetArch.Arm64, new ("aarch64", "aarch64", "android", "@", ".xword", 8) }, - { AndroidTargetArch.Arm, new ("arm", "armv7a", "androideabi", "%", ".long", 4) }, - { AndroidTargetArch.X86_64, new ("x86-64", "x86_64", "android", "@", ".quad", 8) }, - { AndroidTargetArch.X86, new ("x86", "i686", "android", "@", ".long", 4) }, - }; - static readonly Encoding asmFileEncoding = new UTF8Encoding (false); - public static List EmbedBinary ( + public static void EmbedBinary ( TaskLoggingHelper log, ICollection supportedAbis, string androidBinUtilsDirectory, @@ -68,30 +42,23 @@ public static List EmbedBinary ( string outputDirectory, bool missingContentOK) { - var ret = new List (); if (supportedAbis.Count < 1) { log.LogDebugMessage ("ELFEmbeddingHelper: at least one target ABI must be specified. Probably a DTB build, skipping generation."); - return ret; + return; } - string llvmMcPath = GetLlvmMcPath (androidBinUtilsDirectory); foreach (string abi in supportedAbis) { - EmbedBinary ( + DoEmbed ( log, - ret, - llvmMcPath, - abi, - inputFile, - outputDirectory, + MonoAndroidHelper.AbiToTargetArch (abi), + inputFile, outputDirectory, embedItem, missingContentOK ); } - - return ret; } - public static List EmbedBinary ( + public static void EmbedBinary ( TaskLoggingHelper log, string abi, string androidBinUtilsDirectory, @@ -100,59 +67,30 @@ public static List EmbedBinary ( string outputDirectory, bool missingContentOK) { - var ret = new List (); if (String.IsNullOrEmpty (abi)) { log.LogDebugMessage ("ELFEmbeddingHelper: ABI must be specified. Probably a DTB build, skipping generation."); - return ret; + return; } - EmbedBinary ( + DoEmbed ( log, - ret, - GetLlvmMcPath (androidBinUtilsDirectory), - abi, + MonoAndroidHelper.AbiToTargetArch (abi), inputFile, outputDirectory, embedItem, missingContentOK ); - return ret; - } - - static void EmbedBinary ( - TaskLoggingHelper log, - List resultItems, - string llvmMcPath, - string abi, - string inputFile, - string outputDirectory, - EmbedItem embedItem, - bool missingContentOK) - { - string outputFile = Path.Combine (outputDirectory, $"embed_{embedItem.BaseFileName}.{abi.ToLowerInvariant ()}.o"); - DoEmbed (log, MonoAndroidHelper.AbiToTargetArch (abi), llvmMcPath, inputFile, outputFile, embedItem, missingContentOK); - if (!File.Exists (outputFile)) { - return; - } - - var taskItem = new TaskItem (outputFile); - taskItem.SetMetadata ("Abi", abi); - taskItem.SetMetadata ("RuntimeIdentifier", MonoAndroidHelper.AbiToRid (abi)); - resultItems.Add (taskItem); } static void DoEmbed ( TaskLoggingHelper log, AndroidTargetArch arch, - string llvmMcPath, string? inputFile, - string outputFile, + string outputDirectory, EmbedItem item, bool missingContentOK) { - if (!llvmMcConfigs.TryGetValue (arch, out LlvmMcTargetConfig cfg)) { - throw new NotSupportedException ($"Internal error: unsupported target arch '{arch}'"); - } + NativeAssemblerCompilation.LlvmMcTargetConfig cfg = NativeAssemblerCompilation.GetLlvmMcConfig (arch); bool haveInputFile = !String.IsNullOrEmpty (inputFile); if (!haveInputFile) { @@ -162,7 +100,6 @@ static void DoEmbed ( } else { inputFile = Path.GetFullPath (inputFile); } - outputFile = Path.GetFullPath (outputFile); long inputFileSize = 0; string? sanitizedInputFilePath = null; @@ -177,9 +114,9 @@ static void DoEmbed ( } } - string asmInputFile = Path.ChangeExtension (outputFile, ".s"); + string asmSourceFile = NativeAssemblerItemsHelper.GetSourcePath (log, item.NativeAssemblerMode, outputDirectory, arch); - using var fs = File.Open (asmInputFile, FileMode.Create, FileAccess.Write, FileShare.Read); + using var fs = File.Open (asmSourceFile, FileMode.Create, FileAccess.Write, FileShare.Read); using var sw = new StreamWriter (fs, asmFileEncoding); string symbolName = item.SymbolName; @@ -204,24 +141,5 @@ static void DoEmbed ( sw.Flush (); sw.Close (); - - var args = new List { - $"--arch={cfg.TargetArch}", - "--assemble", - "--filetype=obj", - "-g", - $"--triple={cfg.TripleArch}-linux-{cfg.TripleApiPrefix}{XABuildConfig.AndroidMinimumDotNetApiLevel}", - "-o", MonoAndroidHelper.QuoteFileNameArgument (outputFile), - MonoAndroidHelper.QuoteFileNameArgument (asmInputFile), - }; - - // int ret = MonoAndroidHelper.RunProcess (llvmMcPath, String.Join (" ", args), log); - // File.Copy (asmInputFile, $"/tmp/{Path.GetFileName (asmInputFile)}", true); - // File.Copy (outputFile, $"/tmp/{Path.GetFileName (outputFile)}", true); - // if (ret != 0) { - // return; - // } } - - static string GetLlvmMcPath (string androidBinUtilsDirectory) => MonoAndroidHelper.GetLlvmMcPath (androidBinUtilsDirectory); } diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/NativeAssemblerCompilation.cs b/src/Xamarin.Android.Build.Tasks/Utilities/NativeAssemblerCompilation.cs index 78a3b33d90e..6e4c08478ce 100644 --- a/src/Xamarin.Android.Build.Tasks/Utilities/NativeAssemblerCompilation.cs +++ b/src/Xamarin.Android.Build.Tasks/Utilities/NativeAssemblerCompilation.cs @@ -149,26 +149,25 @@ public static void RunAssembler (AssemblerRunContext context, AssemblerConfig co if (e.Data != null) { OnOutputData (context, assemblerName, s, e); stdoutLines.Add (e.Data); - } else + } else { stdout_completed.Set (); + } }; proc.ErrorDataReceived += (s, e) => { if (e.Data != null) { OnErrorData (context, assemblerName, s, e); stderrLines.Add (e.Data); - } else + } else { stderr_completed.Set (); + } }; proc.StartInfo = psi; proc.Start (); proc.BeginOutputReadLine (); proc.BeginErrorReadLine (); - - if (context.RegisterForCancellation != null) { - context.RegisterForCancellation (proc); - } + context.RegisterForCancellation?.Invoke (proc); proc.WaitForExit (); diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/NativeAssemblerItemsHelper.cs b/src/Xamarin.Android.Build.Tasks/Utilities/NativeAssemblerItemsHelper.cs index 6f2df37c30a..6781f2461eb 100644 --- a/src/Xamarin.Android.Build.Tasks/Utilities/NativeAssemblerItemsHelper.cs +++ b/src/Xamarin.Android.Build.Tasks/Utilities/NativeAssemblerItemsHelper.cs @@ -3,6 +3,7 @@ using System.IO; using Microsoft.Build.Utilities; +using Xamarin.Android.Tools; namespace Xamarin.Android.Tasks; @@ -44,6 +45,11 @@ public ModeConfig (string fileNameBase, string extension) { KnownMode.TypeMap, new ("typemaps", LlvmIrExtension) }, }; + public static string? GetSourcePath (TaskLoggingHelper log, KnownMode mode, string nativeSourcesDir, AndroidTargetArch arch) + { + return GetSourcePath (log, mode, nativeSourcesDir, MonoAndroidHelper.ArchToAbi (arch)); + } + public static string? GetSourcePath (TaskLoggingHelper log, KnownMode mode, string nativeSourcesDir, string abi) { if (!ModeConfigs.TryGetValue (mode, out ModeConfig config)) { diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets index 15c55742b7b..c3c3700ac47 100644 --- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets +++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets @@ -2117,7 +2117,7 @@ because xbuild doesn't support framework reference assemblies. - + <_NativeAssemblyTarget Include="@(_TypeMapAssemblySource->'$([System.IO.Path]::ChangeExtension('%(Identity)', '.o'))')"> %(_TypeMapAssemblySource.abi) @@ -2137,6 +2137,9 @@ because xbuild doesn't support framework reference assemblies. <_NativeAssemblyTarget Include="@(_AndroidRemapAssemblySource->'$([System.IO.Path]::ChangeExtension('%(Identity)', '.o'))')"> %(_AndroidRemapAssemblySource.abi) + <_NativeAssemblyTarget Include="@(_EmbeddedAssemblyStoreSourceFiles->'$([System.IO.Path]::ChangeExtension('%(Identity)', '.o'))')"> + %(_EmbeddedAssemblyStoreSourceFiles.abi) + <_NativeAssemblyTarget Include="@(_EmbeddedRuntimeConfigAssemblySource->'$([System.IO.Path]::ChangeExtension('%(Identity)', '.o'))')"> %(_EmbeddedRuntimeConfigAssemblySource.abi) @@ -2145,6 +2148,7 @@ because xbuild doesn't support framework reference assemblies. <_NativeAssemblySource Include="@(_AndroidRemapAssemblySource)" /> <_NativeAssemblySource Include="@(_CompressedAssembliesAssemblySource)" /> + <_NativeAssemblySource Include="@(_EmbeddedAssemblyStoreSourceFiles)" /> <_NativeAssemblySource Include="@(_EmbeddedRuntimeConfigAssemblySource)" /> <_NativeAssemblySource Include="@(_EnvironmentAssemblySource)" /> <_NativeAssemblySource Include="@(_MarshalMethodsAssemblySource)" /> @@ -2167,7 +2171,7 @@ because xbuild doesn't support framework reference assemblies. Date: Tue, 22 Oct 2024 11:46:32 +0200 Subject: [PATCH 31/60] Always generate embedded store sources in CreateEmbeddedAssemblyStore --- ...crosoft.Android.Sdk.AssemblyStores.targets | 2 +- .../Tasks/CreateEmbeddedAssemblyStore.cs | 25 +++++++++++++++++++ .../Tasks/GeneratePackageManagerJava.cs | 6 +---- ...pplicationConfigNativeAssemblyGenerator.cs | 19 -------------- .../Xamarin.Android.Common.targets | 3 +-- 5 files changed, 28 insertions(+), 27 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.AssemblyStores.targets b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.AssemblyStores.targets index c47516065c0..89da58cc4f1 100644 --- a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.AssemblyStores.targets +++ b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.AssemblyStores.targets @@ -13,7 +13,6 @@ @@ -21,6 +20,7 @@ AndroidBinUtilsDirectory="$(AndroidBinUtilsDirectory)" AppSharedLibrariesDir="$(_AndroidApplicationSharedLibraryPath)" AssemblySourcesDir="$(IntermediateOutputPath)android" + AssemblyStoreEmbeddedInRuntime="$(_AndroidEmbedAssemblyStoreInRuntime)" CompressedAssembliesDir="$(_AndroidCompressedAssembliesDir)\test\" Debug="$(AndroidIncludeDebugSymbols)" EnableCompression="$(AndroidEnableAssemblyCompression)" diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/CreateEmbeddedAssemblyStore.cs b/src/Xamarin.Android.Build.Tasks/Tasks/CreateEmbeddedAssemblyStore.cs index 2823af2c3e8..d6eda689509 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/CreateEmbeddedAssemblyStore.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/CreateEmbeddedAssemblyStore.cs @@ -25,6 +25,9 @@ public class CreateEmbeddedAssemblyStore : AndroidTask [Required] public string CompressedAssembliesDir { get; set; } + [Required] + public bool AssemblyStoreEmbeddedInRuntime { get; set; } + [Required] public bool Debug { get; set; } @@ -44,6 +47,28 @@ public class CreateEmbeddedAssemblyStore : AndroidTask public string [] SupportedAbis { get; set; } public override bool RunTask () + { + if (AssemblyStoreEmbeddedInRuntime) { + return EmbedAssemblyStore (); + } + + // Generate sources to satisfy libmonodroid's ABI requirements + foreach (string abi in SupportedAbis) { + ELFEmbeddingHelper.EmbedBinary ( + Log, + abi, + AndroidBinUtilsDirectory, + inputFile: null, + ELFEmbeddingHelper.KnownEmbedItems.AssemblyStore, + AssemblySourcesDir, + missingContentOK: true + ); + } + + return !Log.HasLoggedErrors; + } + + bool EmbedAssemblyStore () { bool compress = !Debug && EnableCompression; IDictionary>? compressedAssembliesInfo = null; diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/GeneratePackageManagerJava.cs b/src/Xamarin.Android.Build.Tasks/Tasks/GeneratePackageManagerJava.cs index 1ad4ee1fb58..0e102d6f90d 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/GeneratePackageManagerJava.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/GeneratePackageManagerJava.cs @@ -62,13 +62,10 @@ public override bool RunTask () [Required] public bool EnablePreloadAssembliesDefault { get; set; } - // These two properties should be required but they will require modifying `monodroid` first + // This property should be required but it will require modifying `monodroid` first //[Required] public string AndroidBinUtilsDirectory { get; set; } - //[Required] - public bool AssemblyStoreEmbeddedInRuntime { get; set; } - public bool EnableMarshalMethods { get; set; } public string RuntimeConfigBinFilePath { get; set; } public string BoundExceptionType { get; set; } @@ -352,7 +349,6 @@ void AddEnvironment () JniRemappingReplacementMethodIndexEntryCount = jniRemappingNativeCodeInfo == null ? 0 : jniRemappingNativeCodeInfo.ReplacementMethodIndexEntryCount, MarshalMethodsEnabled = EnableMarshalMethods, IgnoreSplitConfigs = ShouldIgnoreSplitConfigs (), - AssemblyStoreEmbeddedInRuntime = UseAssemblyStore && AssemblyStoreEmbeddedInRuntime, }; LLVMIR.LlvmIrModule appConfigModule = appConfigAsmGen.Construct (); diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/ApplicationConfigNativeAssemblyGenerator.cs b/src/Xamarin.Android.Build.Tasks/Utilities/ApplicationConfigNativeAssemblyGenerator.cs index 097f84dea99..d374df67dbb 100644 --- a/src/Xamarin.Android.Build.Tasks/Utilities/ApplicationConfigNativeAssemblyGenerator.cs +++ b/src/Xamarin.Android.Build.Tasks/Utilities/ApplicationConfigNativeAssemblyGenerator.cs @@ -198,7 +198,6 @@ sealed class XamarinAndroidBundledAssembly public bool MarshalMethodsEnabled { get; set; } public bool ManagedMarshalMethodsLookupEnabled { get; set; } public bool IgnoreSplitConfigs { get; set; } - public bool AssemblyStoreEmbeddedInRuntime { get; set; } public ApplicationConfigNativeAssemblyGenerator (IDictionary environmentVariables, IDictionary systemProperties, TaskLoggingHelper log) : base (log) @@ -308,24 +307,6 @@ protected override void Construct (LlvmIrModule module) module.Add (bundled_assemblies); AddAssemblyStores (module); - - if (AssemblyStoreEmbeddedInRuntime) { - return; - } - - // Need these to keep ABI compatibility with `libxamarin-app.so` used at the runtime's build time - var embedded_assembly_store_size = new LlvmIrGlobalVariable ( - (ulong)0, - "embedded_assembly_store_size", - LlvmIrVariableOptions.GlobalConstant - ); - module.Add (embedded_assembly_store_size); - - var embedded_assembly_store = new LlvmIrGlobalVariable (typeof (byte[]), "embedded_assembly_store", LlvmIrVariableOptions.GlobalWritable) { - ZeroInitializeArray = true, - ArrayItemCount = 0, - }; - module.Add (embedded_assembly_store); } void AddAssemblyStores (LlvmIrModule module) diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets index c3c3700ac47..f88a86453b5 100644 --- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets +++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets @@ -1906,8 +1906,7 @@ because xbuild doesn't support framework reference assemblies. UseAssemblyStore="$(AndroidUseAssemblyStore)" EnableMarshalMethods="$(_AndroidUseMarshalMethods)" CustomBundleConfigFile="$(AndroidBundleConfigurationFile)" - AndroidBinUtilsDirectory="$(AndroidBinUtilsDirectory)" - AssemblyStoreEmbeddedInRuntime="$(_AndroidEmbedAssemblyStoreInRuntime)" /> + AndroidBinUtilsDirectory="$(AndroidBinUtilsDirectory)" /> From b3b644d857672c656c86250a6eb84cad4048af39 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Tue, 22 Oct 2024 16:46:39 +0200 Subject: [PATCH 32/60] Let's see... --- .../Microsoft.Android.Sdk.AssemblyResolution.targets | 4 ++-- .../Microsoft.Android.Sdk.AssemblyStores.targets | 11 ++++++++--- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.AssemblyResolution.targets b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.AssemblyResolution.targets index 6c3a48b3131..cc91d4a18d7 100644 --- a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.AssemblyResolution.targets +++ b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.AssemblyResolution.targets @@ -204,7 +204,7 @@ _ResolveAssemblies MSBuild target. - + <_ResolvedAssemblies Include="@(ResolvedAssemblies->'$(MonoAndroidIntermediateAssemblyDir)%(DestinationSubPath)')" Condition=" '%(DestinationSubPath)' != '' " /> <_ResolvedUserAssemblies Include="@(ResolvedUserAssemblies->'$(MonoAndroidIntermediateAssemblyDir)%(DestinationSubPath)')" Condition=" '%(DestinationSubPath)' != '' " /> <_ResolvedFrameworkAssemblies Include="@(ResolvedFrameworkAssemblies->'$(MonoAndroidIntermediateAssemblyDir)%(DestinationSubPath)')" Condition=" '%(DestinationSubPath)' != '' " /> @@ -213,7 +213,7 @@ _ResolveAssemblies MSBuild target. <_ShrunkUserAssemblies Include="@(_ResolvedUserAssemblies)" /> <_ShrunkFrameworkAssemblies Include="@(_ResolvedFrameworkAssemblies)" /> - + <_ResolvedAssemblies Include="@(ResolvedAssemblies)" /> <_ResolvedUserAssemblies Include="@(ResolvedUserAssemblies)" /> <_ResolvedFrameworkAssemblies Include="@(ResolvedFrameworkAssemblies)" /> diff --git a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.AssemblyStores.targets b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.AssemblyStores.targets index 89da58cc4f1..22fa9dca278 100644 --- a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.AssemblyStores.targets +++ b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.AssemblyStores.targets @@ -8,13 +8,18 @@ BuildTargetAbis="@(_BuildTargetAbis)" NativeSourcesDir="$(_NativeAssemblySourceDir)" Mode="EmbeddedAssemblyStore"> - - + + + + + <_CreateEmbeddedAssemblyStoreAssembly Include="@(_ShrunkUserAssemblies);@(_AndroidResolvedSatellitePaths);@(_ShrunkFrameworkAssemblies)"/> + <_CreateEmbeddedAssemblyStoreAssembly Condition=" '@(_CreateEmbeddedAssemblyStoreAssembly->Count())' == '0' " Include="@(_ResolvedUserAssemblies);@(_ResolvedFrameworkAssemblies);@(_AndroidResolvedSatellitePaths)" /> + Date: Wed, 23 Oct 2024 13:09:41 +0200 Subject: [PATCH 33/60] Don't assume assemblies exist --- .../ApplicationAttribute.Partial.cs | 6 ++ .../InstrumentationAttribute.Partial.cs | 10 ++- .../PermissionAttribute.Partial.cs | 10 ++- .../PermissionGroupAttribute.Partial.cs | 10 ++- .../PermissionTreeAttribute.Partial.cs | 10 ++- .../SupportsGLTextureAttribute.Partial.cs | 9 +- .../UsesFeatureAttribute.Partial.cs | 9 +- .../UsesPermissionAttribute.Partial.cs | 6 ++ .../Tasks/GeneratePackageManagerJava.cs | 82 ++++++++++++++++++- .../Utilities/ManifestDocument.cs | 4 + 10 files changed, 143 insertions(+), 13 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Mono.Android/ApplicationAttribute.Partial.cs b/src/Xamarin.Android.Build.Tasks/Mono.Android/ApplicationAttribute.Partial.cs index 2997d50006e..1c8f86c9ac9 100644 --- a/src/Xamarin.Android.Build.Tasks/Mono.Android/ApplicationAttribute.Partial.cs +++ b/src/Xamarin.Android.Build.Tasks/Mono.Android/ApplicationAttribute.Partial.cs @@ -60,6 +60,12 @@ static partial void AddManualMapping () public static ApplicationAttribute FromCustomAttributeProvider (ICustomAttributeProvider provider, TypeDefinitionCache cache) { + // `provider` might be null in situations when application configuration is broken, and it surfaces in a number of + // tests which check these situations. + if (provider == null) { + return null; + } + CustomAttribute attr = provider.GetCustomAttributes ("Android.App.ApplicationAttribute") .SingleOrDefault (); if (attr == null) diff --git a/src/Xamarin.Android.Build.Tasks/Mono.Android/InstrumentationAttribute.Partial.cs b/src/Xamarin.Android.Build.Tasks/Mono.Android/InstrumentationAttribute.Partial.cs index 98b5a0611fc..8aff5daaa87 100644 --- a/src/Xamarin.Android.Build.Tasks/Mono.Android/InstrumentationAttribute.Partial.cs +++ b/src/Xamarin.Android.Build.Tasks/Mono.Android/InstrumentationAttribute.Partial.cs @@ -13,11 +13,17 @@ namespace Android.App { partial class InstrumentationAttribute { - - ICollection? specified; + + ICollection specified; public static IEnumerable FromCustomAttributeProvider (ICustomAttributeProvider provider, TypeDefinitionCache cache) { + // `provider` might be null in situations when application configuration is broken, and it surfaces in a number of + // tests which check these situations. + if (provider == null) { + yield break; + } + foreach (CustomAttribute attr in provider.GetCustomAttributes ("Android.App.InstrumentationAttribute")) { InstrumentationAttribute self = new InstrumentationAttribute (); self.specified = mapping.Load (self, attr, cache); diff --git a/src/Xamarin.Android.Build.Tasks/Mono.Android/PermissionAttribute.Partial.cs b/src/Xamarin.Android.Build.Tasks/Mono.Android/PermissionAttribute.Partial.cs index 2f85d446562..16d32e0bf5b 100644 --- a/src/Xamarin.Android.Build.Tasks/Mono.Android/PermissionAttribute.Partial.cs +++ b/src/Xamarin.Android.Build.Tasks/Mono.Android/PermissionAttribute.Partial.cs @@ -16,11 +16,17 @@ namespace Android.App { partial class PermissionAttribute { - - ICollection? specified; + + ICollection specified; public static IEnumerable FromCustomAttributeProvider (ICustomAttributeProvider provider, TypeDefinitionCache cache) { + // `provider` might be null in situations when application configuration is broken, and it surfaces in a number of + // tests which check these situations. + if (provider == null) { + yield break; + } + var attrs = provider.GetCustomAttributes ("Android.App.PermissionAttribute"); foreach (var attr in attrs) { PermissionAttribute self = new PermissionAttribute (); diff --git a/src/Xamarin.Android.Build.Tasks/Mono.Android/PermissionGroupAttribute.Partial.cs b/src/Xamarin.Android.Build.Tasks/Mono.Android/PermissionGroupAttribute.Partial.cs index 51d1a9f0d95..1cda1eefe1b 100644 --- a/src/Xamarin.Android.Build.Tasks/Mono.Android/PermissionGroupAttribute.Partial.cs +++ b/src/Xamarin.Android.Build.Tasks/Mono.Android/PermissionGroupAttribute.Partial.cs @@ -16,11 +16,17 @@ namespace Android.App { partial class PermissionGroupAttribute { - - ICollection? specified; + + ICollection specified; public static IEnumerable FromCustomAttributeProvider (ICustomAttributeProvider provider, TypeDefinitionCache cache) { + // `provider` might be null in situations when application configuration is broken, and it surfaces in a number of + // tests which check these situations. + if (provider == null) { + yield break; + } + var attrs = provider.GetCustomAttributes ("Android.App.PermissionGroupAttribute"); foreach (var attr in attrs) { PermissionGroupAttribute self = new PermissionGroupAttribute (); diff --git a/src/Xamarin.Android.Build.Tasks/Mono.Android/PermissionTreeAttribute.Partial.cs b/src/Xamarin.Android.Build.Tasks/Mono.Android/PermissionTreeAttribute.Partial.cs index 2c88bfdaaa7..5447164294c 100644 --- a/src/Xamarin.Android.Build.Tasks/Mono.Android/PermissionTreeAttribute.Partial.cs +++ b/src/Xamarin.Android.Build.Tasks/Mono.Android/PermissionTreeAttribute.Partial.cs @@ -16,11 +16,17 @@ namespace Android.App { partial class PermissionTreeAttribute { - - ICollection? specified; + + ICollection specified; public static IEnumerable FromCustomAttributeProvider (ICustomAttributeProvider provider, TypeDefinitionCache cache) { + // `provider` might be null in situations when application configuration is broken, and it surfaces in a number of + // tests which check these situations. + if (provider == null) { + yield break; + } + var attrs = provider.GetCustomAttributes ("Android.App.PermissionTreeAttribute"); foreach (var attr in attrs) { PermissionTreeAttribute self = new PermissionTreeAttribute (); diff --git a/src/Xamarin.Android.Build.Tasks/Mono.Android/SupportsGLTextureAttribute.Partial.cs b/src/Xamarin.Android.Build.Tasks/Mono.Android/SupportsGLTextureAttribute.Partial.cs index b632f1e4717..15bd12f175c 100644 --- a/src/Xamarin.Android.Build.Tasks/Mono.Android/SupportsGLTextureAttribute.Partial.cs +++ b/src/Xamarin.Android.Build.Tasks/Mono.Android/SupportsGLTextureAttribute.Partial.cs @@ -31,16 +31,21 @@ internal XElement ToElement (string packageName, TypeDefinitionCache cache) public static IEnumerable FromCustomAttributeProvider (ICustomAttributeProvider provider, TypeDefinitionCache cache) { + // `provider` might be null in situations when application configuration is broken, and it surfaces in a number of + // tests which check these situations. + if (provider == null) { + yield break; + } + var attrs = provider.GetCustomAttributes ("Android.App.SupportsGLTextureAttribute"); foreach (var attr in attrs) { if (attr.HasConstructorArguments && attr.ConstructorArguments.Count == 1) { SupportsGLTextureAttribute self = new SupportsGLTextureAttribute((string)attr.ConstructorArguments[0].Value); self.specified = mapping.Load (self, attr, cache); self.specified.Add("Name"); - yield return self; + yield return self; } } } } } - diff --git a/src/Xamarin.Android.Build.Tasks/Mono.Android/UsesFeatureAttribute.Partial.cs b/src/Xamarin.Android.Build.Tasks/Mono.Android/UsesFeatureAttribute.Partial.cs index 86ecc5f825c..90d4d29b7be 100644 --- a/src/Xamarin.Android.Build.Tasks/Mono.Android/UsesFeatureAttribute.Partial.cs +++ b/src/Xamarin.Android.Build.Tasks/Mono.Android/UsesFeatureAttribute.Partial.cs @@ -37,12 +37,18 @@ internal XElement ToElement (string packageName, TypeDefinitionCache cache) public static IEnumerable FromCustomAttributeProvider (ICustomAttributeProvider provider, TypeDefinitionCache cache) { + // `provider` might be null in situations when application configuration is broken, and it surfaces in a number of + // tests which check these situations. + if (provider == null) { + yield break; + } + var attrs = provider.GetCustomAttributes ("Android.App.UsesFeatureAttribute"); foreach (var attr in attrs) { UsesFeatureAttribute self = new UsesFeatureAttribute (); - if (attr.HasProperties) { + if (attr.HasProperties) { // handle the case where the user sets additional properties self.specified = mapping.Load (self, attr, cache); if (self.specified.Contains("GLESVersion") && self.GLESVersion==0) { @@ -66,4 +72,3 @@ public static IEnumerable FromCustomAttributeProvider (ICu } } } - diff --git a/src/Xamarin.Android.Build.Tasks/Mono.Android/UsesPermissionAttribute.Partial.cs b/src/Xamarin.Android.Build.Tasks/Mono.Android/UsesPermissionAttribute.Partial.cs index 7b957979b72..48648aceefc 100644 --- a/src/Xamarin.Android.Build.Tasks/Mono.Android/UsesPermissionAttribute.Partial.cs +++ b/src/Xamarin.Android.Build.Tasks/Mono.Android/UsesPermissionAttribute.Partial.cs @@ -16,6 +16,12 @@ partial class UsesPermissionAttribute { public static IEnumerable FromCustomAttributeProvider (ICustomAttributeProvider provider, TypeDefinitionCache cache) { + // `provider` might be null in situations when application configuration is broken, and it surfaces in a number of + // tests which check these situations. + if (provider == null) { + yield break; + } + var attrs = provider.GetCustomAttributes ("Android.App.UsesPermissionAttribute"); foreach (var attr in attrs) { UsesPermissionAttribute self; diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/GeneratePackageManagerJava.cs b/src/Xamarin.Android.Build.Tasks/Tasks/GeneratePackageManagerJava.cs index 0e102d6f90d..053a07a5eca 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/GeneratePackageManagerJava.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/GeneratePackageManagerJava.cs @@ -432,6 +432,86 @@ string ValidAssemblerString (string s) } } - return !Log.HasLoggedErrors; + bool ShouldIgnoreSplitConfigs () + { + if (String.IsNullOrEmpty (CustomBundleConfigFile)) { + return false; + } + + return BundleConfigSplitConfigsChecker.ShouldIgnoreSplitConfigs (Log, CustomBundleConfigFile); + } + + void GetRequiredTokens (string assemblyFilePath, out int android_runtime_jnienv_class_token, out int jnienv_initialize_method_token, out int jnienv_registerjninatives_method_token) + { + if (File.Exists (assemblyFilePath)) { + using var pe = new PEReader (File.OpenRead (assemblyFilePath)); + GetRequiredTokens (pe.GetMetadataReader (), out android_runtime_jnienv_class_token, out jnienv_initialize_method_token, out jnienv_registerjninatives_method_token); + } else { + android_runtime_jnienv_class_token = -1; + jnienv_initialize_method_token = -1; + jnienv_registerjninatives_method_token = -1; + Log.LogDebugMessage ($"Assembly '{assemblyFilePath}' does not exist, unable to read required tokens from it"); + return; + } + + if (android_runtime_jnienv_class_token == -1 || jnienv_initialize_method_token == -1 || jnienv_registerjninatives_method_token == -1) { + throw new InvalidOperationException ($"Unable to find the required Android.Runtime.JNIEnvInit method tokens for {assemblyFilePath}"); + } + } + + void GetRequiredTokens (MetadataReader reader, out int android_runtime_jnienv_class_token, out int jnienv_initialize_method_token, out int jnienv_registerjninatives_method_token) + { + android_runtime_jnienv_class_token = -1; + jnienv_initialize_method_token = -1; + jnienv_registerjninatives_method_token = -1; + + TypeDefinition? typeDefinition = null; + + foreach (TypeDefinitionHandle typeHandle in reader.TypeDefinitions) { + TypeDefinition td = reader.GetTypeDefinition (typeHandle); + if (!TypeMatches (td)) { + continue; + } + + typeDefinition = td; + android_runtime_jnienv_class_token = MetadataTokens.GetToken (reader, typeHandle); + break; + } + + if (typeDefinition == null) { + return; + } + + foreach (MethodDefinitionHandle methodHandle in typeDefinition.Value.GetMethods ()) { + MethodDefinition md = reader.GetMethodDefinition (methodHandle); + string name = reader.GetString (md.Name); + + if (jnienv_initialize_method_token == -1 && String.Compare (name, "Initialize", StringComparison.Ordinal) == 0) { + jnienv_initialize_method_token = MetadataTokens.GetToken (reader, methodHandle); + } else if (jnienv_registerjninatives_method_token == -1 && String.Compare (name, "RegisterJniNatives", StringComparison.Ordinal) == 0) { + jnienv_registerjninatives_method_token = MetadataTokens.GetToken (reader, methodHandle); + } + + if (jnienv_initialize_method_token != -1 && jnienv_registerjninatives_method_token != -1) { + break; + } + } + + + bool TypeMatches (TypeDefinition td) + { + string ns = reader.GetString (td.Namespace); + if (String.Compare (ns, "Android.Runtime", StringComparison.Ordinal) != 0) { + return false; + } + + string name = reader.GetString (td.Name); + if (String.Compare (name, "JNIEnvInit", StringComparison.Ordinal) != 0) { + return false; + } + + return true; + } + } } } diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/ManifestDocument.cs b/src/Xamarin.Android.Build.Tasks/Utilities/ManifestDocument.cs index 416ccb3f78f..0deaab05fe6 100644 --- a/src/Xamarin.Android.Build.Tasks/Utilities/ManifestDocument.cs +++ b/src/Xamarin.Android.Build.Tasks/Utilities/ManifestDocument.cs @@ -581,6 +581,10 @@ XElement CreateApplicationElement (XElement manifest, string applicationClass, L List usesConfigurationAttr = []; foreach (var assemblyPath in Assemblies) { var assembly = Resolver.GetAssembly (assemblyPath); + if (assembly == null) { + continue; + } + if (ApplicationAttribute.FromCustomAttributeProvider (assembly, cache) is ApplicationAttribute a) { assemblyAttr.Add (a); } From 85d9a169d6bf48bc2f8f067722391950aa5f041c Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Wed, 23 Oct 2024 13:15:22 +0200 Subject: [PATCH 34/60] better --- .../Tasks/GeneratePackageManagerJava.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/GeneratePackageManagerJava.cs b/src/Xamarin.Android.Build.Tasks/Tasks/GeneratePackageManagerJava.cs index 053a07a5eca..538e796461c 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/GeneratePackageManagerJava.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/GeneratePackageManagerJava.cs @@ -443,10 +443,7 @@ bool ShouldIgnoreSplitConfigs () void GetRequiredTokens (string assemblyFilePath, out int android_runtime_jnienv_class_token, out int jnienv_initialize_method_token, out int jnienv_registerjninatives_method_token) { - if (File.Exists (assemblyFilePath)) { - using var pe = new PEReader (File.OpenRead (assemblyFilePath)); - GetRequiredTokens (pe.GetMetadataReader (), out android_runtime_jnienv_class_token, out jnienv_initialize_method_token, out jnienv_registerjninatives_method_token); - } else { + if (!File.Exists (assemblyFilePath)) { android_runtime_jnienv_class_token = -1; jnienv_initialize_method_token = -1; jnienv_registerjninatives_method_token = -1; @@ -454,6 +451,9 @@ void GetRequiredTokens (string assemblyFilePath, out int android_runtime_jnienv_ return; } + using var pe = new PEReader (File.OpenRead (assemblyFilePath)); + GetRequiredTokens (pe.GetMetadataReader (), out android_runtime_jnienv_class_token, out jnienv_initialize_method_token, out jnienv_registerjninatives_method_token); + if (android_runtime_jnienv_class_token == -1 || jnienv_initialize_method_token == -1 || jnienv_registerjninatives_method_token == -1) { throw new InvalidOperationException ($"Unable to find the required Android.Runtime.JNIEnvInit method tokens for {assemblyFilePath}"); } From bdc737e9710560eed500a6fef4cb811b6fd57ee9 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Wed, 23 Oct 2024 13:18:47 +0200 Subject: [PATCH 35/60] Update apkdesc files --- .../BuildReleaseArm64SimpleDotNet.apkdesc | 31 ++++---- .../BuildReleaseArm64XFormsDotNet.apkdesc | 78 +++++++++---------- 2 files changed, 53 insertions(+), 56 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64SimpleDotNet.apkdesc b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64SimpleDotNet.apkdesc index 0d09c5250f4..1a3c881a8eb 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64SimpleDotNet.apkdesc +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64SimpleDotNet.apkdesc @@ -5,49 +5,46 @@ "Size": 3036 }, "classes.dex": { - "Size": 22484 + "Size": 389676 }, "lib/arm64-v8a/lib__Microsoft.Android.Resource.Designer.dll.so": { - "Size": 18288 + "Size": 18296 }, "lib/arm64-v8a/lib_Java.Interop.dll.so": { "Size": 86688 }, "lib/arm64-v8a/lib_Mono.Android.dll.so": { - "Size": 117712 + "Size": 116080 }, "lib/arm64-v8a/lib_Mono.Android.Runtime.dll.so": { - "Size": 22384 + "Size": 22408 }, "lib/arm64-v8a/lib_System.Console.dll.so": { - "Size": 24392 + "Size": 24376 }, "lib/arm64-v8a/lib_System.Linq.dll.so": { "Size": 25336 }, "lib/arm64-v8a/lib_System.Private.CoreLib.dll.so": { - "Size": 628216 + "Size": 634344 }, "lib/arm64-v8a/lib_System.Runtime.dll.so": { - "Size": 20056 + "Size": 20040 }, "lib/arm64-v8a/lib_System.Runtime.InteropServices.dll.so": { - "Size": 21480 + "Size": 21584 }, "lib/arm64-v8a/lib_UnnamedProject.dll.so": { "Size": 20024 }, - "lib/arm64-v8a/libarc.bin.so": { - "Size": 18872 - }, "lib/arm64-v8a/libmono-component-marshal-ilgen.so": { "Size": 36440 }, "lib/arm64-v8a/libmonodroid.so": { - "Size": 1524752 + "Size": 493384 }, "lib/arm64-v8a/libmonosgen-2.0.so": { - "Size": 3101112 + "Size": 3196512 }, "lib/arm64-v8a/libSystem.Globalization.Native.so": { "Size": 71976 @@ -62,16 +59,16 @@ "Size": 165000 }, "lib/arm64-v8a/libxamarin-app.so": { - "Size": 19536 + "Size": 15144 }, "META-INF/BNDLTOOL.RSA": { "Size": 1221 }, "META-INF/BNDLTOOL.SF": { - "Size": 3266 + "Size": 3167 }, "META-INF/MANIFEST.MF": { - "Size": 3139 + "Size": 3040 }, "res/drawable-hdpi-v4/icon.png": { "Size": 2178 @@ -98,5 +95,5 @@ "Size": 1904 } }, - "PackageSize": 3078677 + "PackageSize": 2865612 } \ No newline at end of file diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64XFormsDotNet.apkdesc b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64XFormsDotNet.apkdesc index cf5b327b70c..e4bc24bb7e3 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64XFormsDotNet.apkdesc +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64XFormsDotNet.apkdesc @@ -35,22 +35,22 @@ "Size": 25424 }, "lib/arm64-v8a/lib_Java.Interop.dll.so": { - "Size": 96104 + "Size": 94648 }, "lib/arm64-v8a/lib_Mono.Android.dll.so": { - "Size": 562336 + "Size": 522008 }, "lib/arm64-v8a/lib_Mono.Android.Runtime.dll.so": { - "Size": 23224 + "Size": 22408 }, "lib/arm64-v8a/lib_mscorlib.dll.so": { - "Size": 21456 + "Size": 21432 }, "lib/arm64-v8a/lib_netstandard.dll.so": { - "Size": 23096 + "Size": 23072 }, "lib/arm64-v8a/lib_System.Collections.Concurrent.dll.so": { - "Size": 29896 + "Size": 29792 }, "lib/arm64-v8a/lib_System.Collections.dll.so": { "Size": 36304 @@ -59,40 +59,43 @@ "Size": 25776 }, "lib/arm64-v8a/lib_System.Collections.Specialized.dll.so": { - "Size": 23856 + "Size": 23840 }, "lib/arm64-v8a/lib_System.ComponentModel.dll.so": { "Size": 19608 }, "lib/arm64-v8a/lib_System.ComponentModel.Primitives.dll.so": { - "Size": 21336 + "Size": 21304 }, "lib/arm64-v8a/lib_System.ComponentModel.TypeConverter.dll.so": { - "Size": 42440 + "Size": 42456 }, "lib/arm64-v8a/lib_System.Console.dll.so": { "Size": 24440 }, "lib/arm64-v8a/lib_System.Core.dll.so": { - "Size": 19472 + "Size": 19448 + }, + "lib/arm64-v8a/lib_System.Diagnostics.DiagnosticSource.dll.so": { + "Size": 28440 }, "lib/arm64-v8a/lib_System.Diagnostics.TraceSource.dll.so": { "Size": 24704 }, "lib/arm64-v8a/lib_System.dll.so": { - "Size": 19856 + "Size": 19848 }, "lib/arm64-v8a/lib_System.Drawing.dll.so": { - "Size": 19456 + "Size": 19424 }, "lib/arm64-v8a/lib_System.Drawing.Primitives.dll.so": { - "Size": 30064 + "Size": 30040 }, "lib/arm64-v8a/lib_System.Formats.Asn1.dll.so": { - "Size": 50312 + "Size": 49928 }, "lib/arm64-v8a/lib_System.IO.Compression.Brotli.dll.so": { - "Size": 29496 + "Size": 29472 }, "lib/arm64-v8a/lib_System.IO.Compression.dll.so": { "Size": 33800 @@ -104,31 +107,31 @@ "Size": 40696 }, "lib/arm64-v8a/lib_System.Linq.Expressions.dll.so": { - "Size": 185864 + "Size": 185800 }, "lib/arm64-v8a/lib_System.Net.Http.dll.so": { - "Size": 85904 + "Size": 89488 }, "lib/arm64-v8a/lib_System.Net.Primitives.dll.so": { - "Size": 42184 + "Size": 41112 }, "lib/arm64-v8a/lib_System.Net.Requests.dll.so": { - "Size": 21568 + "Size": 21544 }, "lib/arm64-v8a/lib_System.ObjectModel.dll.so": { - "Size": 27088 + "Size": 27064 }, "lib/arm64-v8a/lib_System.Private.CoreLib.dll.so": { - "Size": 967200 + "Size": 956568 }, "lib/arm64-v8a/lib_System.Private.DataContractSerialization.dll.so": { - "Size": 216496 + "Size": 216720 }, "lib/arm64-v8a/lib_System.Private.Uri.dll.so": { - "Size": 62728 + "Size": 62184 }, "lib/arm64-v8a/lib_System.Private.Xml.dll.so": { - "Size": 236920 + "Size": 237120 }, "lib/arm64-v8a/lib_System.Private.Xml.Linq.dll.so": { "Size": 35600 @@ -137,7 +140,7 @@ "Size": 20264 }, "lib/arm64-v8a/lib_System.Runtime.InteropServices.dll.so": { - "Size": 21488 + "Size": 21584 }, "lib/arm64-v8a/lib_System.Runtime.Numerics.dll.so": { "Size": 55784 @@ -146,22 +149,22 @@ "Size": 19376 }, "lib/arm64-v8a/lib_System.Runtime.Serialization.Formatters.dll.so": { - "Size": 20352 + "Size": 20328 }, "lib/arm64-v8a/lib_System.Runtime.Serialization.Primitives.dll.so": { "Size": 21472 }, "lib/arm64-v8a/lib_System.Security.Cryptography.dll.so": { - "Size": 81288 + "Size": 80496 }, "lib/arm64-v8a/lib_System.Text.RegularExpressions.dll.so": { - "Size": 187056 + "Size": 183584 }, "lib/arm64-v8a/lib_System.Xml.dll.so": { - "Size": 19272 + "Size": 19248 }, "lib/arm64-v8a/lib_System.Xml.Linq.dll.so": { - "Size": 19288 + "Size": 19264 }, "lib/arm64-v8a/lib_UnnamedProject.dll.so": { "Size": 22096 @@ -235,17 +238,14 @@ "lib/arm64-v8a/lib_Xamarin.Google.Android.Material.dll.so": { "Size": 84912 }, - "lib/arm64-v8a/libarc.bin.so": { - "Size": 18936 - }, "lib/arm64-v8a/libmono-component-marshal-ilgen.so": { "Size": 36600 }, "lib/arm64-v8a/libmonodroid.so": { - "Size": 1516584 + "Size": 493384 }, "lib/arm64-v8a/libmonosgen-2.0.so": { - "Size": 3110944 + "Size": 3196512 }, "lib/arm64-v8a/libSystem.Globalization.Native.so": { "Size": 71952 @@ -260,7 +260,7 @@ "Size": 165000 }, "lib/arm64-v8a/libxamarin-app.so": { - "Size": 353048 + "Size": 122144 }, "META-INF/androidx.activity_activity.version": { "Size": 6 @@ -416,7 +416,7 @@ "Size": 1221 }, "META-INF/BNDLTOOL.SF": { - "Size": 98445 + "Size": 98562 }, "META-INF/com.android.tools/proguard/coroutines.pro": { "Size": 1345 @@ -443,7 +443,7 @@ "Size": 5 }, "META-INF/MANIFEST.MF": { - "Size": 98318 + "Size": 98435 }, "META-INF/maven/com.google.guava/listenablefuture/pom.properties": { "Size": 96 @@ -2483,5 +2483,5 @@ "Size": 812848 } }, - "PackageSize": 10955937 + "PackageSize": 10677500 } \ No newline at end of file From 5acd749e8ca0b7b899ba0269d64609b9977085f7 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Wed, 23 Oct 2024 18:23:47 +0200 Subject: [PATCH 36/60] Load embedded assembly store also in filesystem mode --- .../mono/monodroid/embedded-assemblies-zip.cc | 2 +- .../mono/monodroid/embedded-assemblies.cc | 24 ++++++++++++------- .../mono/monodroid/embedded-assemblies.hh | 6 +++++ src/native/mono/runtime-base/monodroid-dl.hh | 4 ++-- 4 files changed, 25 insertions(+), 11 deletions(-) diff --git a/src/native/mono/monodroid/embedded-assemblies-zip.cc b/src/native/mono/monodroid/embedded-assemblies-zip.cc index a554f3ef9bf..7da208e26b0 100644 --- a/src/native/mono/monodroid/embedded-assemblies-zip.cc +++ b/src/native/mono/monodroid/embedded-assemblies-zip.cc @@ -266,7 +266,7 @@ EmbeddedAssemblies::zip_load_assembly_store_entries (std::span const& b dynamic_local_string entry_name; bool assembly_store_found = embedded_assembly_store_size != 0; if (assembly_store_found) { - verify_assembly_store_and_set_info (embedded_assembly_store, "embedded"); + load_embedded_assembly_store (); log_debug (LOG_ASSEMBLY, "Looking for DSOs in APK"); } else { log_debug (LOG_ASSEMBLY, "Looking for assembly store ('%s') and DSOs in APK", assembly_store_file_path.data ()); diff --git a/src/native/mono/monodroid/embedded-assemblies.cc b/src/native/mono/monodroid/embedded-assemblies.cc index 98e80d8a289..261ee52e230 100644 --- a/src/native/mono/monodroid/embedded-assemblies.cc +++ b/src/native/mono/monodroid/embedded-assemblies.cc @@ -1405,13 +1405,21 @@ EmbeddedAssemblies::register_from_filesystem (const char *lib_dir_path,bool look size_t EmbeddedAssemblies::register_from_filesystem (monodroid_should_register should_register) noexcept { - log_debug (LOG_ASSEMBLY, "Registering assemblies from the filesystem"sv); - constexpr bool LookForMangledNames = true; - size_t assembly_count = register_from_filesystem ( - AndroidSystem::app_lib_directories[0], - LookForMangledNames, - should_register - ); + size_t assembly_count; + + if (embedded_assembly_store_size > 0) { + log_debug (LOG_ASSEMBLY, "Filesystem mode, but registering assemblies from the embedded assembly store"); + load_embedded_assembly_store (); + assembly_count = assembly_store.assembly_count; + } else { + log_debug (LOG_ASSEMBLY, "Registering assemblies from the filesystem"); + constexpr bool LookForMangledNames = true; + assembly_count = register_from_filesystem ( + AndroidSystem::app_lib_directories[0], + LookForMangledNames, + should_register + ); + } #if defined(DEBUG) constexpr bool DoNotLookForMangledNames = false; @@ -1423,6 +1431,6 @@ EmbeddedAssemblies::register_from_filesystem (monodroid_should_register should_r ); #endif - log_debug (LOG_ASSEMBLY, "Found {} assemblies on the filesystem", assembly_count); + log_debug (LOG_ASSEMBLY, "Found %zu assemblies", assembly_count); return assembly_count; } diff --git a/src/native/mono/monodroid/embedded-assemblies.hh b/src/native/mono/monodroid/embedded-assemblies.hh index db110d7f426..9b937c35c2a 100644 --- a/src/native/mono/monodroid/embedded-assemblies.hh +++ b/src/native/mono/monodroid/embedded-assemblies.hh @@ -417,6 +417,12 @@ namespace xamarin::android::internal { void set_debug_entry_data (XamarinAndroidBundledAssembly &entry, ZipEntryLoadState const& state, dynamic_local_string const& entry_name) noexcept; void verify_assembly_store_and_set_info (void *data_start, const char *name) noexcept; + + void load_embedded_assembly_store () noexcept + { + verify_assembly_store_and_set_info (embedded_assembly_store, "embedded"); + } + void map_assembly_store (dynamic_local_string const& entry_name, ZipEntryLoadState &state) noexcept; const AssemblyStoreIndexEntry* find_assembly_store_entry (hash_t hash, const AssemblyStoreIndexEntry *entries, size_t entry_count) noexcept; void store_individual_assembly_data (dynamic_local_string const& entry_name, ZipEntryLoadState const& state, monodroid_should_register should_register) noexcept; diff --git a/src/native/mono/runtime-base/monodroid-dl.hh b/src/native/mono/runtime-base/monodroid-dl.hh index 93cb8b70b48..4b5fbe1be0f 100644 --- a/src/native/mono/runtime-base/monodroid-dl.hh +++ b/src/native/mono/runtime-base/monodroid-dl.hh @@ -48,11 +48,11 @@ namespace xamarin::android::internal size_t arr_size; if constexpr (WhichCache == CacheKind::AOT) { - log_debug (LOG_ASSEMBLY, "Looking for hash {:x} in AOT cache", hash); + log_debug (LOG_ASSEMBLY, "Looking for hash 0x%zx in AOT cache", hash); arr = aot_dso_cache; arr_size = application_config.number_of_aot_cache_entries; } else if constexpr (WhichCache == CacheKind::DSO) { - log_debug (LOG_ASSEMBLY, "Looking for hash {:x} in DSO cache", hash); + log_debug (LOG_ASSEMBLY, "Looking for hash 0x%zx in DSO cache", hash); arr = dso_cache; arr_size = application_config.number_of_dso_cache_entries; } From 7ce1f65fca5c9db86441fbe2fa4341b9d27d8c2e Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Wed, 23 Oct 2024 18:29:51 +0200 Subject: [PATCH 37/60] Log it when an assembly is missing in ManifestDocument --- .../Utilities/ManifestDocument.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/ManifestDocument.cs b/src/Xamarin.Android.Build.Tasks/Utilities/ManifestDocument.cs index 0deaab05fe6..48369483e06 100644 --- a/src/Xamarin.Android.Build.Tasks/Utilities/ManifestDocument.cs +++ b/src/Xamarin.Android.Build.Tasks/Utilities/ManifestDocument.cs @@ -290,7 +290,7 @@ public IList Merge (TaskLoggingHelper log, TypeDefinitionCache cache, Li string.IsNullOrEmpty (VersionName) ? "1.0" : VersionName); } - app = CreateApplicationElement (manifest, applicationClass, subclasses, cache); + app = CreateApplicationElement (log, manifest, applicationClass, subclasses, cache); if (app.Attribute (androidNs + "label") == null && !string.IsNullOrEmpty (ApplicationLabel)) app.SetAttributeValue (androidNs + "label", ApplicationLabel); @@ -570,7 +570,7 @@ Func GetGenerator (T return null; } - XElement CreateApplicationElement (XElement manifest, string applicationClass, List subclasses, TypeDefinitionCache cache) + XElement CreateApplicationElement (TaskLoggingHelper log, XElement manifest, string applicationClass, List subclasses, TypeDefinitionCache cache) { var application = manifest.Descendants ("application").FirstOrDefault (); @@ -582,6 +582,7 @@ XElement CreateApplicationElement (XElement manifest, string applicationClass, L foreach (var assemblyPath in Assemblies) { var assembly = Resolver.GetAssembly (assemblyPath); if (assembly == null) { + log.LogDebugMessage ($"Assembly '{assemblyPath}' not found."); continue; } From b1adce328beb1d0a5838c7926f09a1347467df19 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Wed, 23 Oct 2024 21:02:49 +0200 Subject: [PATCH 38/60] Don't throw --- .../AssemblyStore/AssemblyStoreExplorer.cs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/tools/assembly-store-reader-mk2/AssemblyStore/AssemblyStoreExplorer.cs b/tools/assembly-store-reader-mk2/AssemblyStore/AssemblyStoreExplorer.cs index d6a5a638302..aef64a09d3d 100644 --- a/tools/assembly-store-reader-mk2/AssemblyStore/AssemblyStoreExplorer.cs +++ b/tools/assembly-store-reader-mk2/AssemblyStore/AssemblyStoreExplorer.cs @@ -140,7 +140,19 @@ public static (IList? explorers, string? errorMessage) Op ZipEntry entry = zip.ReadEntry (path); var stream = new MemoryStream (); entry.Extract (stream); - ret.Add (new AssemblyStoreExplorer (stream, $"{fi.FullName}!{path}")); + AssemblyStoreExplorer? explorer = null; + try { + // It may throw when opening an apk without any assembly stores, in which case the v2 store reader would + // always find `libxamarin-app.so` and try to read the embedded store and fail, throwing from the explorer + // constructor. + explorer = new AssemblyStoreExplorer (stream, $"{fi.FullName}!{path}"); + } catch (NotSupportedException) { + // Ignore + } + + if (explorer != null) { + ret.Add (explorer); + } } if (ret.Count == 0) { From 9f858831bedec844adc9b5727d9501163693dc6e Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Thu, 24 Oct 2024 15:49:21 +0200 Subject: [PATCH 39/60] Always create the destination directory --- src/Xamarin.Android.Build.Tasks/Utilities/ELFEmbeddingHelper.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/ELFEmbeddingHelper.cs b/src/Xamarin.Android.Build.Tasks/Utilities/ELFEmbeddingHelper.cs index 2d6a2551765..52704354a63 100644 --- a/src/Xamarin.Android.Build.Tasks/Utilities/ELFEmbeddingHelper.cs +++ b/src/Xamarin.Android.Build.Tasks/Utilities/ELFEmbeddingHelper.cs @@ -116,6 +116,7 @@ static void DoEmbed ( string asmSourceFile = NativeAssemblerItemsHelper.GetSourcePath (log, item.NativeAssemblerMode, outputDirectory, arch); + Directory.CreateDirectory (Path.GetDirectoryName (asmSourceFile)); using var fs = File.Open (asmSourceFile, FileMode.Create, FileAccess.Write, FileShare.Read); using var sw = new StreamWriter (fs, asmFileEncoding); From 0cfed0e13efb423f8830876314122bcfcb7f9aea Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Mon, 28 Oct 2024 12:26:17 +0100 Subject: [PATCH 40/60] Post-rebase fixups --- src/native/mono/monodroid/embedded-assemblies-zip.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/native/mono/monodroid/embedded-assemblies-zip.cc b/src/native/mono/monodroid/embedded-assemblies-zip.cc index 7da208e26b0..38f58276424 100644 --- a/src/native/mono/monodroid/embedded-assemblies-zip.cc +++ b/src/native/mono/monodroid/embedded-assemblies-zip.cc @@ -371,8 +371,10 @@ EmbeddedAssemblies::zip_load_entries (int fd, const char *apk_name, [[maybe_unus .max_assembly_file_name_size = 0u, }; + std::unique_ptr raw_data (new uint8_t[cd_size]); + std::span buf (raw_data.get (), cd_size); ssize_t nread = read (fd, buf.data (), buf.size ()); - if (static_cast(nread) != cd_size) { + if (static_cast(nread) != cd_size) [[unlikely]] { Helpers::abort_application ( LOG_ASSEMBLY, std::format ( From fe9d6cdde6f99314e5f47af8edeee22185afad1a Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Mon, 28 Oct 2024 14:29:50 +0100 Subject: [PATCH 41/60] Let's see what's in the override dir listing --- tests/MSBuildDeviceIntegration/Tests/InstallTests.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tests/MSBuildDeviceIntegration/Tests/InstallTests.cs b/tests/MSBuildDeviceIntegration/Tests/InstallTests.cs index b5b7f7628d3..c515e8a5c92 100644 --- a/tests/MSBuildDeviceIntegration/Tests/InstallTests.cs +++ b/tests/MSBuildDeviceIntegration/Tests/InstallTests.cs @@ -201,6 +201,7 @@ public void InstallWithoutSharedRuntime () //Assert.AreEqual (0, RunAdbCommand ("shell pm list packages Mono.Android.DebugRuntime").Trim ().Length, // "The Shared Runtime should not have been installed."); var directorylist = GetContentFromAllOverrideDirectories (proj.PackageName, DeviceAbi); + Console.WriteLine ($"InstallWithoutSharedRuntime: directoryList == '{directorylist}'"); StringAssert.Contains ($"{proj.ProjectName}.dll", directorylist, $"{proj.ProjectName}.dll should exist in the .__override__/{DeviceAbi} directory."); StringAssert.Contains ($"System.Private.CoreLib.dll", directorylist, $"System.Private.CoreLib.dll should exist in the .__override__/{DeviceAbi} directory."); StringAssert.Contains ($"Mono.Android.dll", directorylist, $"Mono.Android.dll should exist in the .__override__/{DeviceAbi} directory."); @@ -546,7 +547,7 @@ public void IncrementalFastDeployment (string packageFormat) } long lib1FirstBuildSize = new FileInfo (Path.Combine (rootPath, lib1.ProjectName, lib1.OutputPath, "Library1.dll")).Length; - + using (var builder = CreateApkBuilder (Path.Combine (rootPath, app.ProjectName))) { builder.Verbosity = LoggerVerbosity.Detailed; builder.ThrowOnBuildFailure = false; @@ -653,7 +654,7 @@ public void AppWithAndroidJavaSource () public class TestJavaClass2 { public String test(){ - + return ""Java is called""; } }", @@ -671,7 +672,7 @@ public String test(){ public class TestJavaClass { public String test(){ - + return ""Java is called""; } }", From d58026930831adcaadaf667ea0b1ef88c1f408c9 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Mon, 28 Oct 2024 20:13:04 +0100 Subject: [PATCH 42/60] Let's see --- .../targets/Microsoft.Android.Sdk.AssemblyResolution.targets | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.AssemblyResolution.targets b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.AssemblyResolution.targets index cc91d4a18d7..6c3a48b3131 100644 --- a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.AssemblyResolution.targets +++ b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.AssemblyResolution.targets @@ -204,7 +204,7 @@ _ResolveAssemblies MSBuild target. - + <_ResolvedAssemblies Include="@(ResolvedAssemblies->'$(MonoAndroidIntermediateAssemblyDir)%(DestinationSubPath)')" Condition=" '%(DestinationSubPath)' != '' " /> <_ResolvedUserAssemblies Include="@(ResolvedUserAssemblies->'$(MonoAndroidIntermediateAssemblyDir)%(DestinationSubPath)')" Condition=" '%(DestinationSubPath)' != '' " /> <_ResolvedFrameworkAssemblies Include="@(ResolvedFrameworkAssemblies->'$(MonoAndroidIntermediateAssemblyDir)%(DestinationSubPath)')" Condition=" '%(DestinationSubPath)' != '' " /> @@ -213,7 +213,7 @@ _ResolveAssemblies MSBuild target. <_ShrunkUserAssemblies Include="@(_ResolvedUserAssemblies)" /> <_ShrunkFrameworkAssemblies Include="@(_ResolvedFrameworkAssemblies)" /> - + <_ResolvedAssemblies Include="@(ResolvedAssemblies)" /> <_ResolvedUserAssemblies Include="@(ResolvedUserAssemblies)" /> <_ResolvedFrameworkAssemblies Include="@(ResolvedFrameworkAssemblies)" /> From 76295b657db88bf002b43735735689dd40642e03 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Tue, 29 Oct 2024 10:29:17 +0100 Subject: [PATCH 43/60] Cleanup --- .../Mono.Android/InstrumentationAttribute.Partial.cs | 2 +- .../Mono.Android/PermissionAttribute.Partial.cs | 2 +- .../Mono.Android/PermissionGroupAttribute.Partial.cs | 2 +- .../Mono.Android/PermissionTreeAttribute.Partial.cs | 2 +- .../Mono.Android/SupportsGLTextureAttribute.Partial.cs | 3 ++- .../Mono.Android/UsesFeatureAttribute.Partial.cs | 3 ++- tests/MSBuildDeviceIntegration/Tests/InstallTests.cs | 7 +++---- 7 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Mono.Android/InstrumentationAttribute.Partial.cs b/src/Xamarin.Android.Build.Tasks/Mono.Android/InstrumentationAttribute.Partial.cs index 8aff5daaa87..3cedac868db 100644 --- a/src/Xamarin.Android.Build.Tasks/Mono.Android/InstrumentationAttribute.Partial.cs +++ b/src/Xamarin.Android.Build.Tasks/Mono.Android/InstrumentationAttribute.Partial.cs @@ -13,7 +13,7 @@ namespace Android.App { partial class InstrumentationAttribute { - + ICollection specified; public static IEnumerable FromCustomAttributeProvider (ICustomAttributeProvider provider, TypeDefinitionCache cache) diff --git a/src/Xamarin.Android.Build.Tasks/Mono.Android/PermissionAttribute.Partial.cs b/src/Xamarin.Android.Build.Tasks/Mono.Android/PermissionAttribute.Partial.cs index 16d32e0bf5b..ebabfbc9562 100644 --- a/src/Xamarin.Android.Build.Tasks/Mono.Android/PermissionAttribute.Partial.cs +++ b/src/Xamarin.Android.Build.Tasks/Mono.Android/PermissionAttribute.Partial.cs @@ -16,7 +16,7 @@ namespace Android.App { partial class PermissionAttribute { - + ICollection specified; public static IEnumerable FromCustomAttributeProvider (ICustomAttributeProvider provider, TypeDefinitionCache cache) diff --git a/src/Xamarin.Android.Build.Tasks/Mono.Android/PermissionGroupAttribute.Partial.cs b/src/Xamarin.Android.Build.Tasks/Mono.Android/PermissionGroupAttribute.Partial.cs index 1cda1eefe1b..99cedace7d6 100644 --- a/src/Xamarin.Android.Build.Tasks/Mono.Android/PermissionGroupAttribute.Partial.cs +++ b/src/Xamarin.Android.Build.Tasks/Mono.Android/PermissionGroupAttribute.Partial.cs @@ -16,7 +16,7 @@ namespace Android.App { partial class PermissionGroupAttribute { - + ICollection specified; public static IEnumerable FromCustomAttributeProvider (ICustomAttributeProvider provider, TypeDefinitionCache cache) diff --git a/src/Xamarin.Android.Build.Tasks/Mono.Android/PermissionTreeAttribute.Partial.cs b/src/Xamarin.Android.Build.Tasks/Mono.Android/PermissionTreeAttribute.Partial.cs index 5447164294c..79ca7af4999 100644 --- a/src/Xamarin.Android.Build.Tasks/Mono.Android/PermissionTreeAttribute.Partial.cs +++ b/src/Xamarin.Android.Build.Tasks/Mono.Android/PermissionTreeAttribute.Partial.cs @@ -16,7 +16,7 @@ namespace Android.App { partial class PermissionTreeAttribute { - + ICollection specified; public static IEnumerable FromCustomAttributeProvider (ICustomAttributeProvider provider, TypeDefinitionCache cache) diff --git a/src/Xamarin.Android.Build.Tasks/Mono.Android/SupportsGLTextureAttribute.Partial.cs b/src/Xamarin.Android.Build.Tasks/Mono.Android/SupportsGLTextureAttribute.Partial.cs index 15bd12f175c..dcf0dedcec6 100644 --- a/src/Xamarin.Android.Build.Tasks/Mono.Android/SupportsGLTextureAttribute.Partial.cs +++ b/src/Xamarin.Android.Build.Tasks/Mono.Android/SupportsGLTextureAttribute.Partial.cs @@ -43,9 +43,10 @@ public static IEnumerable FromCustomAttributeProvide SupportsGLTextureAttribute self = new SupportsGLTextureAttribute((string)attr.ConstructorArguments[0].Value); self.specified = mapping.Load (self, attr, cache); self.specified.Add("Name"); - yield return self; + yield return self; } } } } } + diff --git a/src/Xamarin.Android.Build.Tasks/Mono.Android/UsesFeatureAttribute.Partial.cs b/src/Xamarin.Android.Build.Tasks/Mono.Android/UsesFeatureAttribute.Partial.cs index 90d4d29b7be..8ab6545d20d 100644 --- a/src/Xamarin.Android.Build.Tasks/Mono.Android/UsesFeatureAttribute.Partial.cs +++ b/src/Xamarin.Android.Build.Tasks/Mono.Android/UsesFeatureAttribute.Partial.cs @@ -48,7 +48,7 @@ public static IEnumerable FromCustomAttributeProvider (ICu UsesFeatureAttribute self = new UsesFeatureAttribute (); - if (attr.HasProperties) { + if (attr.HasProperties) { // handle the case where the user sets additional properties self.specified = mapping.Load (self, attr, cache); if (self.specified.Contains("GLESVersion") && self.GLESVersion==0) { @@ -72,3 +72,4 @@ public static IEnumerable FromCustomAttributeProvider (ICu } } } + diff --git a/tests/MSBuildDeviceIntegration/Tests/InstallTests.cs b/tests/MSBuildDeviceIntegration/Tests/InstallTests.cs index c515e8a5c92..b5b7f7628d3 100644 --- a/tests/MSBuildDeviceIntegration/Tests/InstallTests.cs +++ b/tests/MSBuildDeviceIntegration/Tests/InstallTests.cs @@ -201,7 +201,6 @@ public void InstallWithoutSharedRuntime () //Assert.AreEqual (0, RunAdbCommand ("shell pm list packages Mono.Android.DebugRuntime").Trim ().Length, // "The Shared Runtime should not have been installed."); var directorylist = GetContentFromAllOverrideDirectories (proj.PackageName, DeviceAbi); - Console.WriteLine ($"InstallWithoutSharedRuntime: directoryList == '{directorylist}'"); StringAssert.Contains ($"{proj.ProjectName}.dll", directorylist, $"{proj.ProjectName}.dll should exist in the .__override__/{DeviceAbi} directory."); StringAssert.Contains ($"System.Private.CoreLib.dll", directorylist, $"System.Private.CoreLib.dll should exist in the .__override__/{DeviceAbi} directory."); StringAssert.Contains ($"Mono.Android.dll", directorylist, $"Mono.Android.dll should exist in the .__override__/{DeviceAbi} directory."); @@ -547,7 +546,7 @@ public void IncrementalFastDeployment (string packageFormat) } long lib1FirstBuildSize = new FileInfo (Path.Combine (rootPath, lib1.ProjectName, lib1.OutputPath, "Library1.dll")).Length; - + using (var builder = CreateApkBuilder (Path.Combine (rootPath, app.ProjectName))) { builder.Verbosity = LoggerVerbosity.Detailed; builder.ThrowOnBuildFailure = false; @@ -654,7 +653,7 @@ public void AppWithAndroidJavaSource () public class TestJavaClass2 { public String test(){ - + return ""Java is called""; } }", @@ -672,7 +671,7 @@ public String test(){ public class TestJavaClass { public String test(){ - + return ""Java is called""; } }", From 1aebcf173722b54f68a76836c4eb923a36582f6d Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Thu, 31 Oct 2024 09:10:59 +0100 Subject: [PATCH 44/60] Address feedback --- .../Mono.Android/ApplicationAttribute.Partial.cs | 6 ------ .../Mono.Android/InstrumentationAttribute.Partial.cs | 6 ------ .../Mono.Android/PermissionAttribute.Partial.cs | 6 ------ .../Mono.Android/PermissionGroupAttribute.Partial.cs | 6 ------ .../Mono.Android/PermissionTreeAttribute.Partial.cs | 6 ------ .../Mono.Android/SupportsGLTextureAttribute.Partial.cs | 6 ------ .../Mono.Android/UsesFeatureAttribute.Partial.cs | 6 ------ .../Mono.Android/UsesPermissionAttribute.Partial.cs | 6 ------ 8 files changed, 48 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Mono.Android/ApplicationAttribute.Partial.cs b/src/Xamarin.Android.Build.Tasks/Mono.Android/ApplicationAttribute.Partial.cs index 1c8f86c9ac9..2997d50006e 100644 --- a/src/Xamarin.Android.Build.Tasks/Mono.Android/ApplicationAttribute.Partial.cs +++ b/src/Xamarin.Android.Build.Tasks/Mono.Android/ApplicationAttribute.Partial.cs @@ -60,12 +60,6 @@ static partial void AddManualMapping () public static ApplicationAttribute FromCustomAttributeProvider (ICustomAttributeProvider provider, TypeDefinitionCache cache) { - // `provider` might be null in situations when application configuration is broken, and it surfaces in a number of - // tests which check these situations. - if (provider == null) { - return null; - } - CustomAttribute attr = provider.GetCustomAttributes ("Android.App.ApplicationAttribute") .SingleOrDefault (); if (attr == null) diff --git a/src/Xamarin.Android.Build.Tasks/Mono.Android/InstrumentationAttribute.Partial.cs b/src/Xamarin.Android.Build.Tasks/Mono.Android/InstrumentationAttribute.Partial.cs index 3cedac868db..4a272d32110 100644 --- a/src/Xamarin.Android.Build.Tasks/Mono.Android/InstrumentationAttribute.Partial.cs +++ b/src/Xamarin.Android.Build.Tasks/Mono.Android/InstrumentationAttribute.Partial.cs @@ -18,12 +18,6 @@ partial class InstrumentationAttribute { public static IEnumerable FromCustomAttributeProvider (ICustomAttributeProvider provider, TypeDefinitionCache cache) { - // `provider` might be null in situations when application configuration is broken, and it surfaces in a number of - // tests which check these situations. - if (provider == null) { - yield break; - } - foreach (CustomAttribute attr in provider.GetCustomAttributes ("Android.App.InstrumentationAttribute")) { InstrumentationAttribute self = new InstrumentationAttribute (); self.specified = mapping.Load (self, attr, cache); diff --git a/src/Xamarin.Android.Build.Tasks/Mono.Android/PermissionAttribute.Partial.cs b/src/Xamarin.Android.Build.Tasks/Mono.Android/PermissionAttribute.Partial.cs index ebabfbc9562..1ca8b28ae39 100644 --- a/src/Xamarin.Android.Build.Tasks/Mono.Android/PermissionAttribute.Partial.cs +++ b/src/Xamarin.Android.Build.Tasks/Mono.Android/PermissionAttribute.Partial.cs @@ -21,12 +21,6 @@ partial class PermissionAttribute { public static IEnumerable FromCustomAttributeProvider (ICustomAttributeProvider provider, TypeDefinitionCache cache) { - // `provider` might be null in situations when application configuration is broken, and it surfaces in a number of - // tests which check these situations. - if (provider == null) { - yield break; - } - var attrs = provider.GetCustomAttributes ("Android.App.PermissionAttribute"); foreach (var attr in attrs) { PermissionAttribute self = new PermissionAttribute (); diff --git a/src/Xamarin.Android.Build.Tasks/Mono.Android/PermissionGroupAttribute.Partial.cs b/src/Xamarin.Android.Build.Tasks/Mono.Android/PermissionGroupAttribute.Partial.cs index 99cedace7d6..a1e00e4b68e 100644 --- a/src/Xamarin.Android.Build.Tasks/Mono.Android/PermissionGroupAttribute.Partial.cs +++ b/src/Xamarin.Android.Build.Tasks/Mono.Android/PermissionGroupAttribute.Partial.cs @@ -21,12 +21,6 @@ partial class PermissionGroupAttribute { public static IEnumerable FromCustomAttributeProvider (ICustomAttributeProvider provider, TypeDefinitionCache cache) { - // `provider` might be null in situations when application configuration is broken, and it surfaces in a number of - // tests which check these situations. - if (provider == null) { - yield break; - } - var attrs = provider.GetCustomAttributes ("Android.App.PermissionGroupAttribute"); foreach (var attr in attrs) { PermissionGroupAttribute self = new PermissionGroupAttribute (); diff --git a/src/Xamarin.Android.Build.Tasks/Mono.Android/PermissionTreeAttribute.Partial.cs b/src/Xamarin.Android.Build.Tasks/Mono.Android/PermissionTreeAttribute.Partial.cs index 79ca7af4999..0d388e440d3 100644 --- a/src/Xamarin.Android.Build.Tasks/Mono.Android/PermissionTreeAttribute.Partial.cs +++ b/src/Xamarin.Android.Build.Tasks/Mono.Android/PermissionTreeAttribute.Partial.cs @@ -21,12 +21,6 @@ partial class PermissionTreeAttribute { public static IEnumerable FromCustomAttributeProvider (ICustomAttributeProvider provider, TypeDefinitionCache cache) { - // `provider` might be null in situations when application configuration is broken, and it surfaces in a number of - // tests which check these situations. - if (provider == null) { - yield break; - } - var attrs = provider.GetCustomAttributes ("Android.App.PermissionTreeAttribute"); foreach (var attr in attrs) { PermissionTreeAttribute self = new PermissionTreeAttribute (); diff --git a/src/Xamarin.Android.Build.Tasks/Mono.Android/SupportsGLTextureAttribute.Partial.cs b/src/Xamarin.Android.Build.Tasks/Mono.Android/SupportsGLTextureAttribute.Partial.cs index dcf0dedcec6..b632f1e4717 100644 --- a/src/Xamarin.Android.Build.Tasks/Mono.Android/SupportsGLTextureAttribute.Partial.cs +++ b/src/Xamarin.Android.Build.Tasks/Mono.Android/SupportsGLTextureAttribute.Partial.cs @@ -31,12 +31,6 @@ internal XElement ToElement (string packageName, TypeDefinitionCache cache) public static IEnumerable FromCustomAttributeProvider (ICustomAttributeProvider provider, TypeDefinitionCache cache) { - // `provider` might be null in situations when application configuration is broken, and it surfaces in a number of - // tests which check these situations. - if (provider == null) { - yield break; - } - var attrs = provider.GetCustomAttributes ("Android.App.SupportsGLTextureAttribute"); foreach (var attr in attrs) { if (attr.HasConstructorArguments && attr.ConstructorArguments.Count == 1) { diff --git a/src/Xamarin.Android.Build.Tasks/Mono.Android/UsesFeatureAttribute.Partial.cs b/src/Xamarin.Android.Build.Tasks/Mono.Android/UsesFeatureAttribute.Partial.cs index 8ab6545d20d..86ecc5f825c 100644 --- a/src/Xamarin.Android.Build.Tasks/Mono.Android/UsesFeatureAttribute.Partial.cs +++ b/src/Xamarin.Android.Build.Tasks/Mono.Android/UsesFeatureAttribute.Partial.cs @@ -37,12 +37,6 @@ internal XElement ToElement (string packageName, TypeDefinitionCache cache) public static IEnumerable FromCustomAttributeProvider (ICustomAttributeProvider provider, TypeDefinitionCache cache) { - // `provider` might be null in situations when application configuration is broken, and it surfaces in a number of - // tests which check these situations. - if (provider == null) { - yield break; - } - var attrs = provider.GetCustomAttributes ("Android.App.UsesFeatureAttribute"); foreach (var attr in attrs) { diff --git a/src/Xamarin.Android.Build.Tasks/Mono.Android/UsesPermissionAttribute.Partial.cs b/src/Xamarin.Android.Build.Tasks/Mono.Android/UsesPermissionAttribute.Partial.cs index 48648aceefc..7b957979b72 100644 --- a/src/Xamarin.Android.Build.Tasks/Mono.Android/UsesPermissionAttribute.Partial.cs +++ b/src/Xamarin.Android.Build.Tasks/Mono.Android/UsesPermissionAttribute.Partial.cs @@ -16,12 +16,6 @@ partial class UsesPermissionAttribute { public static IEnumerable FromCustomAttributeProvider (ICustomAttributeProvider provider, TypeDefinitionCache cache) { - // `provider` might be null in situations when application configuration is broken, and it surfaces in a number of - // tests which check these situations. - if (provider == null) { - yield break; - } - var attrs = provider.GetCustomAttributes ("Android.App.UsesPermissionAttribute"); foreach (var attr in attrs) { UsesPermissionAttribute self; From 0f868e908d95206903c8f70a6345d280ad600d1a Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Mon, 4 Nov 2024 19:38:39 +0100 Subject: [PATCH 45/60] Let's see what breaks --- .../targets/Microsoft.Android.Sdk.BuildOrder.targets | 1 + src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.BuildOrder.targets b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.BuildOrder.targets index b3285c44966..17558b8efcd 100644 --- a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.BuildOrder.targets +++ b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.BuildOrder.targets @@ -62,6 +62,7 @@ properties that determine build ordering. <_PrepareBuildApkDependsOnTargets> _SetLatestTargetFrameworkVersion; _GetLibraryImports; + _RemoveRegisterAttribute; _ResolveAssemblies; _ResolveSatellitePaths; _CreatePackageWorkspace; diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets index f88a86453b5..8f883501559 100644 --- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets +++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets @@ -2023,7 +2023,6 @@ because xbuild doesn't support framework reference assemblies. <_CompileToDalvikDependsOnTargets> _CompileJava; - _RemoveRegisterAttribute; _CreateApplicationSharedLibraries; _GetMonoPlatformJarPath; _GetLibraryImports; From 98514e53f47274d91ad4541fcd55380d02626a4d Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Tue, 5 Nov 2024 09:32:05 +0100 Subject: [PATCH 46/60] Revert "Let's see what breaks" This reverts commit bc478708dd1afa809c4197a867ba018d0c6395e7. It broke 481 tests --- .../targets/Microsoft.Android.Sdk.BuildOrder.targets | 1 - src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.BuildOrder.targets b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.BuildOrder.targets index 17558b8efcd..b3285c44966 100644 --- a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.BuildOrder.targets +++ b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.BuildOrder.targets @@ -62,7 +62,6 @@ properties that determine build ordering. <_PrepareBuildApkDependsOnTargets> _SetLatestTargetFrameworkVersion; _GetLibraryImports; - _RemoveRegisterAttribute; _ResolveAssemblies; _ResolveSatellitePaths; _CreatePackageWorkspace; diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets index 8f883501559..f88a86453b5 100644 --- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets +++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets @@ -2023,6 +2023,7 @@ because xbuild doesn't support framework reference assemblies. <_CompileToDalvikDependsOnTargets> _CompileJava; + _RemoveRegisterAttribute; _CreateApplicationSharedLibraries; _GetMonoPlatformJarPath; _GetLibraryImports; From 1d9ad154b3454bdcb4e6dc29652e89bb3c21f79f Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Wed, 6 Nov 2024 13:33:26 +0100 Subject: [PATCH 47/60] Restore [Require] --- .../Tasks/GeneratePackageManagerJava.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/GeneratePackageManagerJava.cs b/src/Xamarin.Android.Build.Tasks/Tasks/GeneratePackageManagerJava.cs index 538e796461c..2e6b8146758 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/GeneratePackageManagerJava.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/GeneratePackageManagerJava.cs @@ -63,7 +63,7 @@ public override bool RunTask () public bool EnablePreloadAssembliesDefault { get; set; } // This property should be required but it will require modifying `monodroid` first - //[Required] + [Required] public string AndroidBinUtilsDirectory { get; set; } public bool EnableMarshalMethods { get; set; } From 3e5ca7d97d8eeefeb8410926174b349089fcf209 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Wed, 6 Nov 2024 16:41:18 +0100 Subject: [PATCH 48/60] Remove comment, no longer valid --- .../Tasks/GeneratePackageManagerJava.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/GeneratePackageManagerJava.cs b/src/Xamarin.Android.Build.Tasks/Tasks/GeneratePackageManagerJava.cs index 2e6b8146758..d91669ec0ee 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/GeneratePackageManagerJava.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/GeneratePackageManagerJava.cs @@ -62,7 +62,6 @@ public override bool RunTask () [Required] public bool EnablePreloadAssembliesDefault { get; set; } - // This property should be required but it will require modifying `monodroid` first [Required] public string AndroidBinUtilsDirectory { get; set; } From 5fd11d3339838e65e0e8036e86c56a65c2d92455 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Tue, 27 May 2025 14:54:33 +0200 Subject: [PATCH 49/60] Fix after rebase --- .../InstrumentationAttribute.Partial.cs | 2 +- .../PermissionAttribute.Partial.cs | 2 +- .../PermissionGroupAttribute.Partial.cs | 2 +- .../PermissionTreeAttribute.Partial.cs | 2 +- .../Tasks/CompileNativeAssembly.cs | 7 + .../Tasks/GeneratePackageManagerJava.cs | 471 +----------------- .../Tasks/PrepareAbiItems.cs | 3 + .../BuildReleaseArm64SimpleDotNet.apkdesc | 31 +- .../BuildReleaseArm64XFormsDotNet.apkdesc | 78 +-- .../Utilities/AssemblyCompression.cs | 3 +- .../Utilities/AssemblyStoreGenerator.cs | 2 + .../Utilities/MonoAndroidHelper.cs | 34 ++ .../Xamarin.Android.Common.targets | 324 ++++++------ .../mono/monodroid/embedded-assemblies-zip.cc | 15 +- .../mono/monodroid/embedded-assemblies.cc | 47 +- .../mono/monodroid/embedded-assemblies.hh | 47 +- src/native/mono/monodroid/monodroid-glue.cc | 5 +- src/native/mono/runtime-base/monodroid-dl.hh | 4 +- src/native/mono/runtime-base/util.cc | 2 +- .../mono/xamarin-app-stub/xamarin-app.hh | 4 + 20 files changed, 365 insertions(+), 720 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Mono.Android/InstrumentationAttribute.Partial.cs b/src/Xamarin.Android.Build.Tasks/Mono.Android/InstrumentationAttribute.Partial.cs index 4a272d32110..98b5a0611fc 100644 --- a/src/Xamarin.Android.Build.Tasks/Mono.Android/InstrumentationAttribute.Partial.cs +++ b/src/Xamarin.Android.Build.Tasks/Mono.Android/InstrumentationAttribute.Partial.cs @@ -14,7 +14,7 @@ namespace Android.App { partial class InstrumentationAttribute { - ICollection specified; + ICollection? specified; public static IEnumerable FromCustomAttributeProvider (ICustomAttributeProvider provider, TypeDefinitionCache cache) { diff --git a/src/Xamarin.Android.Build.Tasks/Mono.Android/PermissionAttribute.Partial.cs b/src/Xamarin.Android.Build.Tasks/Mono.Android/PermissionAttribute.Partial.cs index 1ca8b28ae39..2f85d446562 100644 --- a/src/Xamarin.Android.Build.Tasks/Mono.Android/PermissionAttribute.Partial.cs +++ b/src/Xamarin.Android.Build.Tasks/Mono.Android/PermissionAttribute.Partial.cs @@ -17,7 +17,7 @@ namespace Android.App { partial class PermissionAttribute { - ICollection specified; + ICollection? specified; public static IEnumerable FromCustomAttributeProvider (ICustomAttributeProvider provider, TypeDefinitionCache cache) { diff --git a/src/Xamarin.Android.Build.Tasks/Mono.Android/PermissionGroupAttribute.Partial.cs b/src/Xamarin.Android.Build.Tasks/Mono.Android/PermissionGroupAttribute.Partial.cs index a1e00e4b68e..51d1a9f0d95 100644 --- a/src/Xamarin.Android.Build.Tasks/Mono.Android/PermissionGroupAttribute.Partial.cs +++ b/src/Xamarin.Android.Build.Tasks/Mono.Android/PermissionGroupAttribute.Partial.cs @@ -17,7 +17,7 @@ namespace Android.App { partial class PermissionGroupAttribute { - ICollection specified; + ICollection? specified; public static IEnumerable FromCustomAttributeProvider (ICustomAttributeProvider provider, TypeDefinitionCache cache) { diff --git a/src/Xamarin.Android.Build.Tasks/Mono.Android/PermissionTreeAttribute.Partial.cs b/src/Xamarin.Android.Build.Tasks/Mono.Android/PermissionTreeAttribute.Partial.cs index 0d388e440d3..2c88bfdaaa7 100644 --- a/src/Xamarin.Android.Build.Tasks/Mono.Android/PermissionTreeAttribute.Partial.cs +++ b/src/Xamarin.Android.Build.Tasks/Mono.Android/PermissionTreeAttribute.Partial.cs @@ -17,7 +17,7 @@ namespace Android.App { partial class PermissionTreeAttribute { - ICollection specified; + ICollection? specified; public static IEnumerable FromCustomAttributeProvider (ICustomAttributeProvider provider, TypeDefinitionCache cache) { diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/CompileNativeAssembly.cs b/src/Xamarin.Android.Build.Tasks/Tasks/CompileNativeAssembly.cs index 4bfc03d9d26..8fed9a084b9 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/CompileNativeAssembly.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/CompileNativeAssembly.cs @@ -12,6 +12,13 @@ public class CompileNativeAssembly : AsyncTask { public override string TaskPrefix => "CNA"; + sealed class Config + { + public string? AssemblerPath; + public string? AssemblerOptions; + public string? InputSource; + } + [Required] public ITaskItem[] Sources { get; set; } = []; diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/GeneratePackageManagerJava.cs b/src/Xamarin.Android.Build.Tasks/Tasks/GeneratePackageManagerJava.cs index d91669ec0ee..a82c4c0408f 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/GeneratePackageManagerJava.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/GeneratePackageManagerJava.cs @@ -30,242 +30,10 @@ public override bool RunTask () pkgmgr.WriteLine ("public class MonoPackageManager_Resources {"); pkgmgr.WriteLine ("\tpublic static String[] Assemblies = new String[]{"); - public ITaskItem[] NativeLibraries { get; set; } - - public ITaskItem[] MonoComponents { get; set; } - - public ITaskItem[] SatelliteAssemblies { get; set; } - - public bool UseAssemblyStore { get; set; } - - [Required] - public string OutputDirectory { get; set; } - - [Required] - public string EnvironmentOutputDirectory { get; set; } - - [Required] - public string MainAssembly { get; set; } - - [Required] - public string TargetFrameworkVersion { get; set; } - - [Required] - public string Manifest { get; set; } - - [Required] - public string [] SupportedAbis { get; set; } - - [Required] - public string AndroidPackageName { get; set; } - - [Required] - public bool EnablePreloadAssembliesDefault { get; set; } - - [Required] - public string AndroidBinUtilsDirectory { get; set; } - - public bool EnableMarshalMethods { get; set; } - public string RuntimeConfigBinFilePath { get; set; } - public string BoundExceptionType { get; set; } - - public string PackageNamingPolicy { get; set; } - public string Debug { get; set; } - public ITaskItem[] Environments { get; set; } - public string AndroidAotMode { get; set; } - public bool AndroidAotEnableLazyLoad { get; set; } - public bool EnableLLVM { get; set; } - public string HttpClientHandlerType { get; set; } - public string TlsProvider { get; set; } - public string AndroidSequencePointsMode { get; set; } - public bool EnableSGenConcurrent { get; set; } - public string? CustomBundleConfigFile { get; set; } - - bool _Debug { - get { - return string.Equals (Debug, "true", StringComparison.OrdinalIgnoreCase); - } - } - - public override bool RunTask () - { - var doc = AndroidAppManifest.Load (Manifest, MonoAndroidHelper.SupportedVersions); - int minApiVersion = doc.MinSdkVersion == null ? 4 : (int) doc.MinSdkVersion; - // We need to include any special assemblies in the Assemblies list - var mainFileName = Path.GetFileName (MainAssembly); - - using (var pkgmgr = MemoryStreamPool.Shared.CreateStreamWriter ()) { - pkgmgr.WriteLine ("package mono;"); - - // Write all the user assemblies - pkgmgr.WriteLine ("public class MonoPackageManager_Resources {"); - pkgmgr.WriteLine ("\tpublic static String[] Assemblies = new String[]{"); - - pkgmgr.WriteLine ("\t\t/* We need to ensure that \"{0}\" comes first in this list. */", mainFileName); - pkgmgr.WriteLine ("\t\t\"" + mainFileName + "\","); - foreach (var assembly in ResolvedUserAssemblies) { - if (string.Compare (Path.GetFileName (assembly.ItemSpec), mainFileName, StringComparison.OrdinalIgnoreCase) == 0) - continue; - pkgmgr.WriteLine ("\t\t\"" + Path.GetFileName (assembly.ItemSpec) + "\","); - } - foreach (var assembly in MonoAndroidHelper.GetFrameworkAssembliesToTreatAsUserAssemblies (ResolvedAssemblies)) { - if (string.Compare (Path.GetFileName (assembly.ItemSpec), mainFileName, StringComparison.OrdinalIgnoreCase) == 0) - continue; - pkgmgr.WriteLine ("\t\t\"" + Path.GetFileName (assembly.ItemSpec) + "\","); - } - - // Write the assembly dependencies - pkgmgr.WriteLine ("\t};"); - pkgmgr.WriteLine ("\tpublic static String[] Dependencies = new String[]{"); - - //foreach (var assembly in assemblies.Except (args.Assemblies)) { - // if (args.SharedRuntime && !Toolbox.IsInSharedRuntime (assembly)) - // pkgmgr.WriteLine ("\t\t\"" + Path.GetFileName (assembly) + "\","); - //} - - pkgmgr.WriteLine ("\t};"); - - pkgmgr.WriteLine ("}"); - pkgmgr.Flush (); - - // Only copy to the real location if the contents actually changed - var dest = Path.GetFullPath (Path.Combine (OutputDirectory, "MonoPackageManager_Resources.java")); - - Files.CopyIfStreamChanged (pkgmgr.BaseStream, dest); - } - - AddEnvironment (); - - return !Log.HasLoggedErrors; - } - - static internal AndroidTargetArch GetAndroidTargetArchForAbi (string abi) => MonoAndroidHelper.AbiToTargetArch (abi); - - static readonly string[] defaultLogLevel = {"MONO_LOG_LEVEL", "info"}; - static readonly string[] defaultMonoDebug = {"MONO_DEBUG", "gen-compact-seq-points"}; - static readonly string[] defaultHttpMessageHandler = {"XA_HTTP_CLIENT_HANDLER_TYPE", "System.Net.Http.HttpClientHandler, System.Net.Http"}; - static readonly string[] defaultTlsProvider = {"XA_TLS_PROVIDER", "btls"}; - - void AddEnvironment () - { - bool usesMonoAOT = false; - var environmentVariables = new Dictionary (StringComparer.Ordinal); - var systemProperties = new Dictionary (StringComparer.Ordinal); - - if (!Enum.TryParse (PackageNamingPolicy, out PackageNamingPolicy pnp)) { - pnp = PackageNamingPolicyEnum.LowercaseCrc64; - } - - AotMode aotMode = AotMode.None; - if (!string.IsNullOrEmpty (AndroidAotMode) && Aot.GetAndroidAotMode (AndroidAotMode, out aotMode) && aotMode != AotMode.None) { - usesMonoAOT = true; - } - - SequencePointsMode sequencePointsMode; - if (!Aot.TryGetSequencePointsMode (AndroidSequencePointsMode, out sequencePointsMode)) - sequencePointsMode = SequencePointsMode.None; - - // Even though environment files were potentially parsed in GenerateJavaStubs, we need to do it here again because we might have additional environment - // files (generated by us) which weren't present by the time GeneratJavaStubs ran. - var environmentParser = new EnvironmentFilesParser { - BrokenExceptionTransitions = false, - UsesAssemblyPreload = EnablePreloadAssembliesDefault, - }; - environmentParser.Parse (Environments, sequencePointsMode, Log); - - foreach (string line in environmentParser.EnvironmentVariableLines) { - AddEnvironmentVariableLine (line); - } - - if (_Debug && !environmentParser.HaveLogLevel) { - AddEnvironmentVariable (defaultLogLevel[0], defaultLogLevel[1]); - } - - if (sequencePointsMode != SequencePointsMode.None && !environmentParser.HaveMonoDebug) { - AddEnvironmentVariable (defaultMonoDebug[0], defaultMonoDebug[1]); - } - - if (!environmentParser.HaveHttpMessageHandler) { - if (HttpClientHandlerType == null) - AddEnvironmentVariable (defaultHttpMessageHandler[0], defaultHttpMessageHandler[1]); - else - AddEnvironmentVariable ("XA_HTTP_CLIENT_HANDLER_TYPE", HttpClientHandlerType.Trim ()); - } - - if (!environmentParser.HaveMonoGCParams) { - if (EnableSGenConcurrent) - AddEnvironmentVariable ("MONO_GC_PARAMS", "major=marksweep-conc"); - else - AddEnvironmentVariable ("MONO_GC_PARAMS", "major=marksweep"); - } - - global::Android.Runtime.BoundExceptionType boundExceptionType; - if (String.IsNullOrEmpty (BoundExceptionType) || String.Compare (BoundExceptionType, "System", StringComparison.OrdinalIgnoreCase) == 0) { - boundExceptionType = global::Android.Runtime.BoundExceptionType.System; - } else if (String.Compare (BoundExceptionType, "Java", StringComparison.OrdinalIgnoreCase) == 0) { - boundExceptionType = global::Android.Runtime.BoundExceptionType.Java; - } else { - throw new InvalidOperationException ($"Unsupported BoundExceptionType value '{BoundExceptionType}'"); - } - - int assemblyNameWidth = 0; - Encoding assemblyNameEncoding = Encoding.UTF8; - - Action updateNameWidth = (ITaskItem assembly) => { - if (UseAssemblyStore) { - return; - } - - string assemblyName = Path.GetFileName (assembly.ItemSpec); - int nameBytes = assemblyNameEncoding.GetBytes (assemblyName).Length; - if (nameBytes > assemblyNameWidth) { - assemblyNameWidth = nameBytes; - } - }; - - int assemblyCount = 0; - bool enableMarshalMethods = EnableMarshalMethods; - HashSet archAssemblyNames = null; - HashSet uniqueAssemblyNames = new HashSet (StringComparer.OrdinalIgnoreCase); - Action updateAssemblyCount = (ITaskItem assembly) => { - string? culture = MonoAndroidHelper.GetAssemblyCulture (assembly); - string fileName = Path.GetFileName (assembly.ItemSpec); - string assemblyName; - - if (String.IsNullOrEmpty (culture)) { - assemblyName = fileName; - } else { - assemblyName = $"{culture}/{fileName}"; - } - - if (!uniqueAssemblyNames.Contains (assemblyName)) { - uniqueAssemblyNames.Add (assemblyName); - } - - string abi = MonoAndroidHelper.GetItemAbi (assembly); - archAssemblyNames ??= new HashSet (StringComparer.OrdinalIgnoreCase); - - if (!archAssemblyNames.Contains (assemblyName)) { - assemblyCount++; - archAssemblyNames.Add (assemblyName); - } - }; - - if (SatelliteAssemblies != null) { - foreach (ITaskItem assembly in SatelliteAssemblies) { - updateNameWidth (assembly); - updateAssemblyCount (assembly); - } - } - - int android_runtime_jnienv_class_token = -1; - int jnienv_initialize_method_token = -1; - int jnienv_registerjninatives_method_token = -1; - foreach (var assembly in ResolvedAssemblies) { - updateNameWidth (assembly); - updateAssemblyCount (assembly); - - if (android_runtime_jnienv_class_token != -1) { + pkgmgr.WriteLine ("\t\t/* We need to ensure that \"{0}\" comes first in this list. */", mainFileName); + pkgmgr.WriteLine ("\t\t\"" + mainFileName + "\","); + foreach (var assembly in ResolvedUserAssemblies) { + if (string.Compare (Path.GetFileName (assembly.ItemSpec), mainFileName, StringComparison.OrdinalIgnoreCase) == 0) continue; pkgmgr.WriteLine ("\t\t\"" + Path.GetFileName (assembly.ItemSpec) + "\","); } @@ -279,238 +47,17 @@ void AddEnvironment () // pkgmgr.WriteLine ("\t\t\"" + Path.GetFileName (assembly) + "\","); //} - var uniqueNativeLibraries = new List (); - - // Number of DSOs that will be packaged, it may be different to the number of items in the above - // `uniqueNativeLibraries` list. - uint packagedNativeLibrariesCount = 0; - var seenNativeLibraryNames = new HashSet (StringComparer.OrdinalIgnoreCase); - if (NativeLibraries != null) { - foreach (ITaskItem item in NativeLibraries) { - // We don't care about different ABIs here, just the file name - string name = Path.GetFileName (item.ItemSpec); - if (seenNativeLibraryNames.Contains (name)) { - continue; - } - - if (!ELFHelper.IsEmptyAOTLibrary (Log, item.ItemSpec)) { - packagedNativeLibrariesCount++; - } - - seenNativeLibraryNames.Add (name); - uniqueNativeLibraries.Add (item); - } + pkgmgr.WriteLine ("\t};"); - // libxamarin-app.so is not in NativeLibraries, but we must count it - if (!seenNativeLibraryNames.Contains ("libxamarin-app.so")) { - uniqueNativeLibraries.Add (new TaskItem ("libxamarin-app.so")); - packagedNativeLibrariesCount++; - } - } + pkgmgr.WriteLine ("}"); + pkgmgr.Flush (); // Only copy to the real location if the contents actually changed var dest = Path.GetFullPath (Path.Combine (OutputDirectory, "MonoPackageManager_Resources.java")); - bool haveRuntimeConfigBlob = !String.IsNullOrEmpty (RuntimeConfigBinFilePath) && File.Exists (RuntimeConfigBinFilePath); - ELFEmbeddingHelper.EmbedBinary ( - Log, - SupportedAbis, - AndroidBinUtilsDirectory, - RuntimeConfigBinFilePath, - ELFEmbeddingHelper.KnownEmbedItems.RuntimeConfig, - EnvironmentOutputDirectory, - missingContentOK: !haveRuntimeConfigBlob - ); - - var jniRemappingNativeCodeInfo = BuildEngine4.GetRegisteredTaskObjectAssemblyLocal (ProjectSpecificTaskObjectKey (GenerateJniRemappingNativeCode.JniRemappingNativeCodeInfoKey), RegisteredTaskObjectLifetime.Build); - var appConfigAsmGen = new ApplicationConfigNativeAssemblyGenerator (environmentVariables, systemProperties, Log) { - UsesMonoAOT = usesMonoAOT, - UsesMonoLLVM = EnableLLVM, - UsesAssemblyPreload = environmentParser.UsesAssemblyPreload, - MonoAOTMode = aotMode.ToString ().ToLowerInvariant (), - AotEnableLazyLoad = AndroidAotEnableLazyLoad, - AndroidPackageName = AndroidPackageName, - BrokenExceptionTransitions = environmentParser.BrokenExceptionTransitions, - PackageNamingPolicy = pnp, - BoundExceptionType = boundExceptionType, - JniAddNativeMethodRegistrationAttributePresent = NativeCodeGenState.Template != null ? NativeCodeGenState.Template.JniAddNativeMethodRegistrationAttributePresent : false, - HaveRuntimeConfigBlob = haveRuntimeConfigBlob, - NumberOfAssembliesInApk = assemblyCount, - BundledAssemblyNameWidth = assemblyNameWidth, - MonoComponents = (MonoComponent)monoComponents, - NativeLibraries = uniqueNativeLibraries, - PackagedNativeLibrariesCount = packagedNativeLibrariesCount, - HaveAssemblyStore = UseAssemblyStore, - AndroidRuntimeJNIEnvToken = android_runtime_jnienv_class_token, - JNIEnvInitializeToken = jnienv_initialize_method_token, - JNIEnvRegisterJniNativesToken = jnienv_registerjninatives_method_token, - JniRemappingReplacementTypeCount = jniRemappingNativeCodeInfo == null ? 0 : jniRemappingNativeCodeInfo.ReplacementTypeCount, - JniRemappingReplacementMethodIndexEntryCount = jniRemappingNativeCodeInfo == null ? 0 : jniRemappingNativeCodeInfo.ReplacementMethodIndexEntryCount, - MarshalMethodsEnabled = EnableMarshalMethods, - IgnoreSplitConfigs = ShouldIgnoreSplitConfigs (), - }; - LLVMIR.LlvmIrModule appConfigModule = appConfigAsmGen.Construct (); - - foreach (string abi in SupportedAbis) { - string targetAbi = abi.ToLowerInvariant (); - string environmentBaseAsmFilePath = Path.Combine (EnvironmentOutputDirectory, $"environment.{targetAbi}"); - string marshalMethodsBaseAsmFilePath = Path.Combine (EnvironmentOutputDirectory, $"marshal_methods.{targetAbi}"); - string environmentLlFilePath = $"{environmentBaseAsmFilePath}.ll"; - string marshalMethodsLlFilePath = $"{marshalMethodsBaseAsmFilePath}.ll"; - AndroidTargetArch targetArch = GetAndroidTargetArchForAbi (abi); - - using var appConfigWriter = MemoryStreamPool.Shared.CreateStreamWriter (); - try { - appConfigAsmGen.Generate (appConfigModule, targetArch, appConfigWriter, environmentLlFilePath); - } catch { - throw; - } finally { - appConfigWriter.Flush (); - Files.CopyIfStreamChanged (appConfigWriter.BaseStream, environmentLlFilePath); - } - - MarshalMethodsNativeAssemblyGenerator marshalMethodsAsmGen; - if (enableMarshalMethods) { - marshalMethodsAsmGen = new MarshalMethodsNativeAssemblyGenerator ( - Log, - assemblyCount, - uniqueAssemblyNames, - EnsureCodeGenState (targetArch) - ); - } else { - marshalMethodsAsmGen = new MarshalMethodsNativeAssemblyGenerator ( - Log, - targetArch, - assemblyCount, - uniqueAssemblyNames - ); - } - - LLVMIR.LlvmIrModule marshalMethodsModule = marshalMethodsAsmGen.Construct (); - using var marshalMethodsWriter = MemoryStreamPool.Shared.CreateStreamWriter (); - try { - marshalMethodsAsmGen.Generate (marshalMethodsModule, targetArch, marshalMethodsWriter, marshalMethodsLlFilePath); - } catch { - throw; - } finally { - marshalMethodsWriter.Flush (); - Files.CopyIfStreamChanged (marshalMethodsWriter.BaseStream, marshalMethodsLlFilePath); - } - } - - NativeCodeGenState EnsureCodeGenState (AndroidTargetArch targetArch) - { - if (nativeCodeGenStates == null || !nativeCodeGenStates.TryGetValue (targetArch, out NativeCodeGenState? state)) { - throw new InvalidOperationException ($"Internal error: missing native code generation state for architecture '{targetArch}'"); - } - - return state; - } - - void AddEnvironmentVariable (string name, string value) - { - if (Char.IsUpper(name [0]) || !Char.IsLetter(name [0])) - environmentVariables [ValidAssemblerString (name)] = ValidAssemblerString (value); - else - systemProperties [ValidAssemblerString (name)] = ValidAssemblerString (value); - } - - void AddEnvironmentVariableLine (string l) - { - string line = l?.Trim (); - if (String.IsNullOrEmpty (line) || line [0] == '#') - return; - - string[] nv = line.Split (new char[]{'='}, 2); - AddEnvironmentVariable (nv[0].Trim (), nv.Length < 2 ? String.Empty : nv[1].Trim ()); - } - - string ValidAssemblerString (string s) - { - return s.Replace ("\"", "\\\""); - } - } - - bool ShouldIgnoreSplitConfigs () - { - if (String.IsNullOrEmpty (CustomBundleConfigFile)) { - return false; - } - - return BundleConfigSplitConfigsChecker.ShouldIgnoreSplitConfigs (Log, CustomBundleConfigFile); - } - - void GetRequiredTokens (string assemblyFilePath, out int android_runtime_jnienv_class_token, out int jnienv_initialize_method_token, out int jnienv_registerjninatives_method_token) - { - if (!File.Exists (assemblyFilePath)) { - android_runtime_jnienv_class_token = -1; - jnienv_initialize_method_token = -1; - jnienv_registerjninatives_method_token = -1; - Log.LogDebugMessage ($"Assembly '{assemblyFilePath}' does not exist, unable to read required tokens from it"); - return; - } - - using var pe = new PEReader (File.OpenRead (assemblyFilePath)); - GetRequiredTokens (pe.GetMetadataReader (), out android_runtime_jnienv_class_token, out jnienv_initialize_method_token, out jnienv_registerjninatives_method_token); - - if (android_runtime_jnienv_class_token == -1 || jnienv_initialize_method_token == -1 || jnienv_registerjninatives_method_token == -1) { - throw new InvalidOperationException ($"Unable to find the required Android.Runtime.JNIEnvInit method tokens for {assemblyFilePath}"); - } + Files.CopyIfStreamChanged (pkgmgr.BaseStream, dest); } - void GetRequiredTokens (MetadataReader reader, out int android_runtime_jnienv_class_token, out int jnienv_initialize_method_token, out int jnienv_registerjninatives_method_token) - { - android_runtime_jnienv_class_token = -1; - jnienv_initialize_method_token = -1; - jnienv_registerjninatives_method_token = -1; - - TypeDefinition? typeDefinition = null; - - foreach (TypeDefinitionHandle typeHandle in reader.TypeDefinitions) { - TypeDefinition td = reader.GetTypeDefinition (typeHandle); - if (!TypeMatches (td)) { - continue; - } - - typeDefinition = td; - android_runtime_jnienv_class_token = MetadataTokens.GetToken (reader, typeHandle); - break; - } - - if (typeDefinition == null) { - return; - } - - foreach (MethodDefinitionHandle methodHandle in typeDefinition.Value.GetMethods ()) { - MethodDefinition md = reader.GetMethodDefinition (methodHandle); - string name = reader.GetString (md.Name); - - if (jnienv_initialize_method_token == -1 && String.Compare (name, "Initialize", StringComparison.Ordinal) == 0) { - jnienv_initialize_method_token = MetadataTokens.GetToken (reader, methodHandle); - } else if (jnienv_registerjninatives_method_token == -1 && String.Compare (name, "RegisterJniNatives", StringComparison.Ordinal) == 0) { - jnienv_registerjninatives_method_token = MetadataTokens.GetToken (reader, methodHandle); - } - - if (jnienv_initialize_method_token != -1 && jnienv_registerjninatives_method_token != -1) { - break; - } - } - - - bool TypeMatches (TypeDefinition td) - { - string ns = reader.GetString (td.Namespace); - if (String.Compare (ns, "Android.Runtime", StringComparison.Ordinal) != 0) { - return false; - } - - string name = reader.GetString (td.Name); - if (String.Compare (name, "JNIEnvInit", StringComparison.Ordinal) != 0) { - return false; - } - - return true; - } - } + return !Log.HasLoggedErrors; } } diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/PrepareAbiItems.cs b/src/Xamarin.Android.Build.Tasks/Tasks/PrepareAbiItems.cs index 41328dbf299..1f9148b4f9f 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/PrepareAbiItems.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/PrepareAbiItems.cs @@ -22,6 +22,9 @@ public class PrepareAbiItems : AndroidTask [Output] public ITaskItem[]? AssemblySources { get; set; } + [Output] + public ITaskItem[]? AssemblyIncludes { get; set; } + public override bool RunTask () { var sources = new List (); diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64SimpleDotNet.apkdesc b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64SimpleDotNet.apkdesc index 1a3c881a8eb..0d09c5250f4 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64SimpleDotNet.apkdesc +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64SimpleDotNet.apkdesc @@ -5,46 +5,49 @@ "Size": 3036 }, "classes.dex": { - "Size": 389676 + "Size": 22484 }, "lib/arm64-v8a/lib__Microsoft.Android.Resource.Designer.dll.so": { - "Size": 18296 + "Size": 18288 }, "lib/arm64-v8a/lib_Java.Interop.dll.so": { "Size": 86688 }, "lib/arm64-v8a/lib_Mono.Android.dll.so": { - "Size": 116080 + "Size": 117712 }, "lib/arm64-v8a/lib_Mono.Android.Runtime.dll.so": { - "Size": 22408 + "Size": 22384 }, "lib/arm64-v8a/lib_System.Console.dll.so": { - "Size": 24376 + "Size": 24392 }, "lib/arm64-v8a/lib_System.Linq.dll.so": { "Size": 25336 }, "lib/arm64-v8a/lib_System.Private.CoreLib.dll.so": { - "Size": 634344 + "Size": 628216 }, "lib/arm64-v8a/lib_System.Runtime.dll.so": { - "Size": 20040 + "Size": 20056 }, "lib/arm64-v8a/lib_System.Runtime.InteropServices.dll.so": { - "Size": 21584 + "Size": 21480 }, "lib/arm64-v8a/lib_UnnamedProject.dll.so": { "Size": 20024 }, + "lib/arm64-v8a/libarc.bin.so": { + "Size": 18872 + }, "lib/arm64-v8a/libmono-component-marshal-ilgen.so": { "Size": 36440 }, "lib/arm64-v8a/libmonodroid.so": { - "Size": 493384 + "Size": 1524752 }, "lib/arm64-v8a/libmonosgen-2.0.so": { - "Size": 3196512 + "Size": 3101112 }, "lib/arm64-v8a/libSystem.Globalization.Native.so": { "Size": 71976 @@ -59,16 +62,16 @@ "Size": 165000 }, "lib/arm64-v8a/libxamarin-app.so": { - "Size": 15144 + "Size": 19536 }, "META-INF/BNDLTOOL.RSA": { "Size": 1221 }, "META-INF/BNDLTOOL.SF": { - "Size": 3167 + "Size": 3266 }, "META-INF/MANIFEST.MF": { - "Size": 3040 + "Size": 3139 }, "res/drawable-hdpi-v4/icon.png": { "Size": 2178 @@ -95,5 +98,5 @@ "Size": 1904 } }, - "PackageSize": 2865612 + "PackageSize": 3078677 } \ No newline at end of file diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64XFormsDotNet.apkdesc b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64XFormsDotNet.apkdesc index e4bc24bb7e3..cf5b327b70c 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64XFormsDotNet.apkdesc +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64XFormsDotNet.apkdesc @@ -35,22 +35,22 @@ "Size": 25424 }, "lib/arm64-v8a/lib_Java.Interop.dll.so": { - "Size": 94648 + "Size": 96104 }, "lib/arm64-v8a/lib_Mono.Android.dll.so": { - "Size": 522008 + "Size": 562336 }, "lib/arm64-v8a/lib_Mono.Android.Runtime.dll.so": { - "Size": 22408 + "Size": 23224 }, "lib/arm64-v8a/lib_mscorlib.dll.so": { - "Size": 21432 + "Size": 21456 }, "lib/arm64-v8a/lib_netstandard.dll.so": { - "Size": 23072 + "Size": 23096 }, "lib/arm64-v8a/lib_System.Collections.Concurrent.dll.so": { - "Size": 29792 + "Size": 29896 }, "lib/arm64-v8a/lib_System.Collections.dll.so": { "Size": 36304 @@ -59,43 +59,40 @@ "Size": 25776 }, "lib/arm64-v8a/lib_System.Collections.Specialized.dll.so": { - "Size": 23840 + "Size": 23856 }, "lib/arm64-v8a/lib_System.ComponentModel.dll.so": { "Size": 19608 }, "lib/arm64-v8a/lib_System.ComponentModel.Primitives.dll.so": { - "Size": 21304 + "Size": 21336 }, "lib/arm64-v8a/lib_System.ComponentModel.TypeConverter.dll.so": { - "Size": 42456 + "Size": 42440 }, "lib/arm64-v8a/lib_System.Console.dll.so": { "Size": 24440 }, "lib/arm64-v8a/lib_System.Core.dll.so": { - "Size": 19448 - }, - "lib/arm64-v8a/lib_System.Diagnostics.DiagnosticSource.dll.so": { - "Size": 28440 + "Size": 19472 }, "lib/arm64-v8a/lib_System.Diagnostics.TraceSource.dll.so": { "Size": 24704 }, "lib/arm64-v8a/lib_System.dll.so": { - "Size": 19848 + "Size": 19856 }, "lib/arm64-v8a/lib_System.Drawing.dll.so": { - "Size": 19424 + "Size": 19456 }, "lib/arm64-v8a/lib_System.Drawing.Primitives.dll.so": { - "Size": 30040 + "Size": 30064 }, "lib/arm64-v8a/lib_System.Formats.Asn1.dll.so": { - "Size": 49928 + "Size": 50312 }, "lib/arm64-v8a/lib_System.IO.Compression.Brotli.dll.so": { - "Size": 29472 + "Size": 29496 }, "lib/arm64-v8a/lib_System.IO.Compression.dll.so": { "Size": 33800 @@ -107,31 +104,31 @@ "Size": 40696 }, "lib/arm64-v8a/lib_System.Linq.Expressions.dll.so": { - "Size": 185800 + "Size": 185864 }, "lib/arm64-v8a/lib_System.Net.Http.dll.so": { - "Size": 89488 + "Size": 85904 }, "lib/arm64-v8a/lib_System.Net.Primitives.dll.so": { - "Size": 41112 + "Size": 42184 }, "lib/arm64-v8a/lib_System.Net.Requests.dll.so": { - "Size": 21544 + "Size": 21568 }, "lib/arm64-v8a/lib_System.ObjectModel.dll.so": { - "Size": 27064 + "Size": 27088 }, "lib/arm64-v8a/lib_System.Private.CoreLib.dll.so": { - "Size": 956568 + "Size": 967200 }, "lib/arm64-v8a/lib_System.Private.DataContractSerialization.dll.so": { - "Size": 216720 + "Size": 216496 }, "lib/arm64-v8a/lib_System.Private.Uri.dll.so": { - "Size": 62184 + "Size": 62728 }, "lib/arm64-v8a/lib_System.Private.Xml.dll.so": { - "Size": 237120 + "Size": 236920 }, "lib/arm64-v8a/lib_System.Private.Xml.Linq.dll.so": { "Size": 35600 @@ -140,7 +137,7 @@ "Size": 20264 }, "lib/arm64-v8a/lib_System.Runtime.InteropServices.dll.so": { - "Size": 21584 + "Size": 21488 }, "lib/arm64-v8a/lib_System.Runtime.Numerics.dll.so": { "Size": 55784 @@ -149,22 +146,22 @@ "Size": 19376 }, "lib/arm64-v8a/lib_System.Runtime.Serialization.Formatters.dll.so": { - "Size": 20328 + "Size": 20352 }, "lib/arm64-v8a/lib_System.Runtime.Serialization.Primitives.dll.so": { "Size": 21472 }, "lib/arm64-v8a/lib_System.Security.Cryptography.dll.so": { - "Size": 80496 + "Size": 81288 }, "lib/arm64-v8a/lib_System.Text.RegularExpressions.dll.so": { - "Size": 183584 + "Size": 187056 }, "lib/arm64-v8a/lib_System.Xml.dll.so": { - "Size": 19248 + "Size": 19272 }, "lib/arm64-v8a/lib_System.Xml.Linq.dll.so": { - "Size": 19264 + "Size": 19288 }, "lib/arm64-v8a/lib_UnnamedProject.dll.so": { "Size": 22096 @@ -238,14 +235,17 @@ "lib/arm64-v8a/lib_Xamarin.Google.Android.Material.dll.so": { "Size": 84912 }, + "lib/arm64-v8a/libarc.bin.so": { + "Size": 18936 + }, "lib/arm64-v8a/libmono-component-marshal-ilgen.so": { "Size": 36600 }, "lib/arm64-v8a/libmonodroid.so": { - "Size": 493384 + "Size": 1516584 }, "lib/arm64-v8a/libmonosgen-2.0.so": { - "Size": 3196512 + "Size": 3110944 }, "lib/arm64-v8a/libSystem.Globalization.Native.so": { "Size": 71952 @@ -260,7 +260,7 @@ "Size": 165000 }, "lib/arm64-v8a/libxamarin-app.so": { - "Size": 122144 + "Size": 353048 }, "META-INF/androidx.activity_activity.version": { "Size": 6 @@ -416,7 +416,7 @@ "Size": 1221 }, "META-INF/BNDLTOOL.SF": { - "Size": 98562 + "Size": 98445 }, "META-INF/com.android.tools/proguard/coroutines.pro": { "Size": 1345 @@ -443,7 +443,7 @@ "Size": 5 }, "META-INF/MANIFEST.MF": { - "Size": 98435 + "Size": 98318 }, "META-INF/maven/com.google.guava/listenablefuture/pom.properties": { "Size": 96 @@ -2483,5 +2483,5 @@ "Size": 812848 } }, - "PackageSize": 10677500 + "PackageSize": 10955937 } \ No newline at end of file diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/AssemblyCompression.cs b/src/Xamarin.Android.Build.Tasks/Utilities/AssemblyCompression.cs index af7f97cdcd5..71da2ab254a 100644 --- a/src/Xamarin.Android.Build.Tasks/Utilities/AssemblyCompression.cs +++ b/src/Xamarin.Android.Build.Tasks/Utilities/AssemblyCompression.cs @@ -171,7 +171,8 @@ static string GetCompressedAssemblyOutputDirectory (ITaskItem assembly, string c string assemblyOutputDir; string subDirectory = assembly.GetMetadata ("DestinationSubDirectory"); string abi = MonoAndroidHelper.GetItemAbi (assembly); - if (!String.IsNullOrEmpty (subDirectory) && !(subDirectory.EndsWith ($"{abi}/", StringComparison.Ordinal) || subDirectory.EndsWith ($"{abi}\\", StringComparison.Ordinal))) { + + if (!string.IsNullOrEmpty (subDirectory) && !(subDirectory.EndsWith ($"{abi}/", StringComparison.Ordinal) || subDirectory.EndsWith ($"{abi}\\", StringComparison.Ordinal))) { assemblyOutputDir = Path.Combine (compressedOutputDir, abi, subDirectory); } else { assemblyOutputDir = Path.Combine (compressedOutputDir, abi); diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/AssemblyStoreGenerator.cs b/src/Xamarin.Android.Build.Tasks/Utilities/AssemblyStoreGenerator.cs index f061412a125..35c355a5872 100644 --- a/src/Xamarin.Android.Build.Tasks/Utilities/AssemblyStoreGenerator.cs +++ b/src/Xamarin.Android.Build.Tasks/Utilities/AssemblyStoreGenerator.cs @@ -106,6 +106,7 @@ string Generate (string baseOutputDirectory, AndroidTargetArch arch, List (); var descriptors = new List (); ulong namesSize = 0; @@ -120,6 +121,7 @@ string Generate (string baseOutputDirectory, AndroidTargetArch arch, List AbiToTargetArch (GetItemAbi (asmItem)); + + + public static AndroidTargetArch GetRequiredValidArchitecture (ITaskItem item) + { + AndroidTargetArch ret = GetTargetArch (item); + + if (ret == AndroidTargetArch.None) { + throw new InvalidOperationException ($"Internal error: assembly '{item}' doesn't target any architecture."); + } + + return ret; + } #endif // MSBUILD static string GetToolsRootDirectoryRelativePath (string androidBinUtilsDirectory) @@ -779,5 +791,27 @@ static string GetBinUtilsToolPath (string androidBinUtilsDirectory, string toolN { return Path.Combine (androidBinUtilsDirectory, MonoAndroidHelper.GetExecutablePath (androidBinUtilsDirectory, toolName)); } + + public static AndroidRuntime ParseAndroidRuntime (string androidRuntime) + { + if (string.Equals (androidRuntime, "CoreCLR", StringComparison.OrdinalIgnoreCase)) + return AndroidRuntime.CoreCLR; + if (string.Equals (androidRuntime, "NativeAOT", StringComparison.OrdinalIgnoreCase)) + return AndroidRuntime.NativeAOT; + + // Default runtime is MonoVM + return AndroidRuntime.MonoVM; + } + + public static JavaPeerStyle ParseCodeGenerationTarget (string codeGenerationTarget) + { + if (Enum.TryParse (codeGenerationTarget, ignoreCase: true, out JavaPeerStyle style)) + return style; + + // Default is XAJavaInterop1 + return JavaPeerStyle.XAJavaInterop1; + } + + public static object GetProjectBuildSpecificTaskObjectKey (object key, string workingDirectory, string intermediateOutputPath) => (key, workingDirectory, intermediateOutputPath); } } diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets index f88a86453b5..26cac5ff469 100644 --- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets +++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets @@ -313,6 +313,8 @@ Copyright (C) 2011-2012 Xamarin. All rights reserved. <_AndroidFastDeployEnvironmentFiles Condition=" '$(_AndroidFastDeployEnvironmentFiles)' == '' ">False <_AndroidCompressedAssembliesDir>$(IntermediateOutputPath)android\lz4 + <_AndroidUseCLR Condition=" '$(_AndroidRuntime)' == 'CoreCLR' ">True + <_AndroidUseCLR Condition=" '$(_AndroidRuntime)' != 'CoreCLR' ">False @@ -361,8 +363,12 @@ Copyright (C) 2011-2012 Xamarin. All rights reserved. <_AndroidUseMarshalMethods Condition=" '$(AndroidIncludeDebugSymbols)' == 'True' ">False <_AndroidUseMarshalMethods Condition=" '$(AndroidIncludeDebugSymbols)' != 'True' ">$(AndroidEnableMarshalMethods) + <_AndroidEmbedAssemblyStoreInRuntime Condition=" '$(AndroidUseAssemblyStore)' == 'True' And '$(EmbedAssembliesIntoApk)' == 'true' And '$(_AndroidEmbedAssemblyStoreInRuntime)' == '' ">True <_AndroidEmbedAssemblyStoreInRuntime Condition="'$(_AndroidEmbedAssemblyStoreInRuntime)' == '' ">False + + <_AndroidUseManagedMarshalMethodsLookup Condition=" '$(_AndroidUseManagedMarshalMethodsLookup)' == '' and '$(_AndroidUseMarshalMethods)' == 'True' and '$(_AndroidRuntime)' != 'MonoVM' ">True + <_AndroidUseManagedMarshalMethodsLookup Condition=" '$(_AndroidUseManagedMarshalMethodsLookup)' == '' ">False @@ -1878,35 +1884,50 @@ because xbuild doesn't support framework reference assemblies. + MainAssembly="$(TargetPath)" + OutputDirectory="$(_AndroidIntermediateJavaSourceDirectory)mono" + ResolvedUserAssemblies="@(_ResolvedUserAssemblies)"> + + + + + + + + @@ -2314,52 +2335,8 @@ because xbuild doesn't support framework reference assemblies. also need to have the args added to Xamarin.Android.Common.Debugging.targets in monodroid. --> - - - - - - + RuntimePackLibraryDirectories="@(_RuntimePackLibraryDirectory)"> + + + + + + + + + + + - - - - - - - - + <_ApkOutputPath>$(ApkFileIntermediate) + + + + <_NativeLibraries Include="@(_AndroidNativeLibraryForFastDev)" /> + <_DalvikClasses Include="@(_DexFileForFastDev)" /> + + + + <_ApkOutputPath>$(_BaseZipIntermediate) + <_BundleNativeLibraries>$(_BundleResultNativeLibraries) + + + + <_NativeLibraries Include="@(AndroidNativeLibrary)" /> + <_DalvikClasses Include="@(_DexFile)" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + const& buf, dynamic_local_string &entry_name, ZipEntryLoadState &state) noexcept { entry_name.clear (); @@ -142,7 +142,7 @@ EmbeddedAssemblies::store_individual_assembly_data (dynamic_local_string const& buf, uint32_t num_entries, [[maybe_unused]] monodroid_should_register should_register, ZipEntryLoadState &state) noexcept { // TODO: do away with all the string manipulation here. Replace it with generating xxhash for the entry name @@ -256,7 +256,7 @@ EmbeddedAssemblies::map_assembly_store (dynamic_local_string verify_assembly_store_and_set_info (payload_start, entry_name.get ()); } -force_inline void +[[gnu::always_inline]] void EmbeddedAssemblies::zip_load_assembly_store_entries (std::span const& buf, uint32_t num_entries, ZipEntryLoadState &state) noexcept { if (all_required_zip_entries_found ()) { @@ -272,6 +272,7 @@ EmbeddedAssemblies::zip_load_assembly_store_entries (std::span const& b log_debug (LOG_ASSEMBLY, "Looking for assembly store ('%s') and DSOs in APK", assembly_store_file_path.data ()); } + log_debug (LOG_ASSEMBLY, "Looking for assembly stores in APK ('{}')", assembly_store_file_path.data ()); for (size_t i = 0uz; i < num_entries; i++) { if (all_required_zip_entries_found ()) { need_to_scan_more_apks = false; @@ -345,12 +346,12 @@ EmbeddedAssemblies::zip_load_entries (int fd, const char *apk_name, [[maybe_unus if (retval < 0) [[unlikely]] { Helpers::abort_application ( LOG_ASSEMBLY, - Util::monodroid_strdup_printf ( - "Failed to seek to central directory position in APK: %s. retval=%d errno=%d, File=%s", + std::format ( + "Failed to seek to central directory position in APK: {}. retval={} errno={}, File={}", std::strerror (errno), retval, errno, - apk_name + optional_string (apk_name) ) ); } @@ -653,7 +654,7 @@ EmbeddedAssemblies::zip_read_field (T const& buf, size_t index, size_t count, dy } bool -EmbeddedAssemblies::zip_read_entry_info (std::span const& buf, dynamic_local_string& file_name, ZipEntryLoadState &state) +EmbeddedAssemblies::zip_read_entry_info (std::span const& buf, dynamic_local_string& file_name, ZipEntryLoadState &state) noexcept { constexpr size_t CD_COMPRESSION_METHOD_OFFSET = 10uz; constexpr size_t CD_UNCOMPRESSED_SIZE_OFFSET = 24uz; diff --git a/src/native/mono/monodroid/embedded-assemblies.cc b/src/native/mono/monodroid/embedded-assemblies.cc index 261ee52e230..443540226a1 100644 --- a/src/native/mono/monodroid/embedded-assemblies.cc +++ b/src/native/mono/monodroid/embedded-assemblies.cc @@ -910,6 +910,51 @@ EmbeddedAssemblies::typemap_managed_to_java (MonoReflectionType *reflection_type return ret; } +EmbeddedAssemblies::md_mmap_info +EmbeddedAssemblies::md_mmap_apk_file (int fd, uint32_t offset, size_t size, const char* filename) +{ + md_mmap_info file_info; + md_mmap_info mmap_info; + + size_t pageSize = static_cast(Util::monodroid_getpagesize ()); + size_t offsetFromPage = offset % pageSize; + size_t offsetPage = offset - offsetFromPage; + size_t offsetSize = size + offsetFromPage; + + mmap_info.area = mmap (nullptr, offsetSize, PROT_READ, MAP_PRIVATE, fd, static_cast(offsetPage)); + + if (mmap_info.area == MAP_FAILED) { + Helpers::abort_application ( + LOG_ASSEMBLY, + std::format ( + "Could not mmap APK fd {}: {}; File={}", + fd, + strerror (errno), + optional_string (filename) + ) + ); + } + + mmap_info.size = offsetSize; + file_info.area = pointer_add (mmap_info.area, offsetFromPage); + file_info.size = size; + + log_info ( + LOG_ASSEMBLY, + " mmap_start: {:<8p}; mmap_end: {:<8p} mmap_len: {:<12} file_start: {:<8p} file_end: {:<8p} file_len: {:<12} apk descriptor: {} file: {}", + mmap_info.area, + pointer_add (mmap_info.area, mmap_info.size), + mmap_info.size, + file_info.area, + pointer_add (file_info.area, file_info.size), + file_info.size, + fd, + optional_string (filename) + ); + + return file_info; +} + void EmbeddedAssemblies::gather_bundled_assemblies_from_apk (const char* apk, monodroid_should_register should_register) noexcept { @@ -1431,6 +1476,6 @@ EmbeddedAssemblies::register_from_filesystem (monodroid_should_register should_r ); #endif - log_debug (LOG_ASSEMBLY, "Found %zu assemblies", assembly_count); + log_debug (LOG_ASSEMBLY, "Found {} assemblies on the filesystem", assembly_count); return assembly_count; } diff --git a/src/native/mono/monodroid/embedded-assemblies.hh b/src/native/mono/monodroid/embedded-assemblies.hh index 9b937c35c2a..2087773b5c9 100644 --- a/src/native/mono/monodroid/embedded-assemblies.hh +++ b/src/native/mono/monodroid/embedded-assemblies.hh @@ -27,7 +27,7 @@ #include #include "cppcompat.hh" #include "shared-constants.hh" -#include "xxhash.hh" +#include #include "util.hh" #include @@ -305,12 +305,12 @@ namespace xamarin::android::internal { static void get_assembly_data (XamarinAndroidBundledAssembly const& e, uint8_t*& assembly_data, uint32_t& assembly_data_size) noexcept; static void get_assembly_data (AssemblyStoreSingleAssemblyRuntimeData const& e, uint8_t*& assembly_data, uint32_t& assembly_data_size) noexcept; - void zip_load_entries (int fd, const char *apk_name, monodroid_should_register should_register); - void zip_load_individual_assembly_entries (std::span const& buf, uint32_t num_entries, monodroid_should_register should_register, ZipEntryLoadState &state) noexcept; - void zip_load_assembly_store_entries (std::span const& buf, uint32_t num_entries, ZipEntryLoadState &state) noexcept; - bool zip_load_entry_common (size_t entry_index, std::span const& buf, dynamic_local_string &entry_name, ZipEntryLoadState &state) noexcept; - bool zip_read_cd_info (int fd, uint32_t& cd_offset, uint32_t& cd_size, uint16_t& cd_entries); - bool zip_adjust_data_offset (int fd, ZipEntryLoadState &state); + static void zip_load_entries (int fd, const char *apk_name, monodroid_should_register should_register); + static void zip_load_individual_assembly_entries (std::span const& buf, uint32_t num_entries, monodroid_should_register should_register, ZipEntryLoadState &state) noexcept; + static void zip_load_assembly_store_entries (std::span const& buf, uint32_t num_entries, ZipEntryLoadState &state) noexcept; + static bool zip_load_entry_common (size_t entry_index, std::span const& buf, dynamic_local_string &entry_name, ZipEntryLoadState &state) noexcept; + static bool zip_read_cd_info (int fd, uint32_t& cd_offset, uint32_t& cd_size, uint16_t& cd_entries); + static bool zip_adjust_data_offset (int fd, ZipEntryLoadState &state); template static bool zip_extract_cd_info (std::array const& buf, uint32_t& cd_offset, uint32_t& cd_size, uint16_t& cd_entries) noexcept; @@ -330,7 +330,7 @@ namespace xamarin::android::internal { template static bool zip_read_field (T const& buf, size_t index, size_t count, dynamic_local_string& characters) noexcept; - bool zip_read_entry_info (std::span const& buf, dynamic_local_string& file_name, ZipEntryLoadState &state); + static bool zip_read_entry_info (std::span const& buf, dynamic_local_string& file_name, ZipEntryLoadState &state); [[gnu::always_inline]] static std::tuple get_wrapper_dso_payload_pointer_and_size (md_mmap_info const& map_info, const char *file_name) noexcept @@ -412,20 +412,20 @@ namespace xamarin::android::internal { static const TypeMapModuleEntry* binary_search (uint32_t key, const TypeMapModuleEntry *arr, uint32_t n) noexcept; #endif template - void set_entry_data (XamarinAndroidBundledAssembly &entry, ZipEntryLoadState const& state, dynamic_local_string const& entry_name) noexcept; - void set_assembly_entry_data (XamarinAndroidBundledAssembly &entry, ZipEntryLoadState const& state, dynamic_local_string const& entry_name) noexcept; - void set_debug_entry_data (XamarinAndroidBundledAssembly &entry, ZipEntryLoadState const& state, dynamic_local_string const& entry_name) noexcept; + static void set_entry_data (XamarinAndroidBundledAssembly &entry, ZipEntryLoadState const& state, dynamic_local_string const& entry_name) noexcept; + static void set_assembly_entry_data (XamarinAndroidBundledAssembly &entry, ZipEntryLoadState const& state, dynamic_local_string const& entry_name) noexcept; + static void set_debug_entry_data (XamarinAndroidBundledAssembly &entry, ZipEntryLoadState const& state, dynamic_local_string const& entry_name) noexcept; - void verify_assembly_store_and_set_info (void *data_start, const char *name) noexcept; + static void verify_assembly_store_and_set_info (void *data_start, const char *name) noexcept; - void load_embedded_assembly_store () noexcept + static void load_embedded_assembly_store () noexcept { verify_assembly_store_and_set_info (embedded_assembly_store, "embedded"); } - void map_assembly_store (dynamic_local_string const& entry_name, ZipEntryLoadState &state) noexcept; - const AssemblyStoreIndexEntry* find_assembly_store_entry (hash_t hash, const AssemblyStoreIndexEntry *entries, size_t entry_count) noexcept; - void store_individual_assembly_data (dynamic_local_string const& entry_name, ZipEntryLoadState const& state, monodroid_should_register should_register) noexcept; + static void map_assembly_store (dynamic_local_string const& entry_name, ZipEntryLoadState &state) noexcept; + static const AssemblyStoreIndexEntry* find_assembly_store_entry (hash_t hash, const AssemblyStoreIndexEntry *entries, size_t entry_count) noexcept; + static void store_individual_assembly_data (dynamic_local_string const& entry_name, ZipEntryLoadState const& state, monodroid_should_register should_register) noexcept; constexpr static size_t get_mangled_name_max_size_overhead () { @@ -503,14 +503,13 @@ namespace xamarin::android::internal { size_t type_map_count; #endif // DEBUG static inline const char *assemblies_prefix_override = nullptr; - - md_mmap_info runtime_config_blob_mmap{}; - void *runtime_config_data = nullptr; - size_t runtime_config_data_size = 0uz; - bool runtime_config_blob_found = embedded_runtime_config_size > 0u; - uint32_t number_of_mapped_assembly_stores = 0u; - uint32_t number_of_zip_dso_entries = 0u; - bool need_to_scan_more_apks = true; + static inline md_mmap_info runtime_config_blob_mmap{}; + static inline void *runtime_config_data = nullptr; + static inline size_t runtime_config_data_size = 0uz; + static inline bool runtime_config_blob_found = embedded_runtime_config_size > 0u; + static inline uint32_t number_of_mapped_assembly_stores = 0u; + static inline uint32_t number_of_zip_dso_entries = 0u; + static inline bool need_to_scan_more_apks = true; static inline AssemblyStoreIndexEntry *assembly_store_hashes = nullptr; static inline xamarin::android::mutex assembly_decompress_mutex {}; diff --git a/src/native/mono/monodroid/monodroid-glue.cc b/src/native/mono/monodroid/monodroid-glue.cc index df82db42457..954661663a2 100644 --- a/src/native/mono/monodroid/monodroid-glue.cc +++ b/src/native/mono/monodroid/monodroid-glue.cc @@ -729,7 +729,6 @@ MonodroidRuntime::create_domain (JNIEnv *env, jstring_array_wrapper &runtimeApks gather_bundled_assemblies (runtimeApks, &user_assemblies_count, have_split_apks); if (embedded_runtime_config_size > 0) { - size_t blob_time_index; if (FastTiming::enabled ()) [[unlikely]] { internal_timing.start_event (TimingEventKind::RuntimeConfigBlob); } @@ -737,6 +736,7 @@ MonodroidRuntime::create_domain (JNIEnv *env, jstring_array_wrapper &runtimeApks runtime_config_args.kind = 1; runtime_config_args.runtimeconfig.data.data = reinterpret_cast(embedded_runtime_config); runtime_config_args.runtimeconfig.data.data_len = static_cast(embedded_runtime_config_size); + monovm_runtimeconfig_initialize (&runtime_config_args, cleanup_runtime_config, nullptr); if (FastTiming::enabled ()) [[unlikely]] { @@ -1157,8 +1157,9 @@ MonodroidRuntime::set_profile_options () noexcept .append (OUTPUT_ARG) .append (output_path.get (), output_path.length ()); } + if (Util::create_directory (AndroidSystem::override_dirs[0], 0777, 000) < 0) { - log_warn (LOG_DEFAULT, "Failed to create directory '%s'. %s", AndroidSystem::override_dirs[0], std::strerror (errno)); + log_warn (LOG_DEFAULT, "Failed to create directory '{}'. {}", optional_string (AndroidSystem::override_dirs[0]), std::strerror (errno)); } log_warn (LOG_DEFAULT, "Initializing profiler with options: {}", optional_string (value.get ())); diff --git a/src/native/mono/runtime-base/monodroid-dl.hh b/src/native/mono/runtime-base/monodroid-dl.hh index 4b5fbe1be0f..93cb8b70b48 100644 --- a/src/native/mono/runtime-base/monodroid-dl.hh +++ b/src/native/mono/runtime-base/monodroid-dl.hh @@ -48,11 +48,11 @@ namespace xamarin::android::internal size_t arr_size; if constexpr (WhichCache == CacheKind::AOT) { - log_debug (LOG_ASSEMBLY, "Looking for hash 0x%zx in AOT cache", hash); + log_debug (LOG_ASSEMBLY, "Looking for hash {:x} in AOT cache", hash); arr = aot_dso_cache; arr_size = application_config.number_of_aot_cache_entries; } else if constexpr (WhichCache == CacheKind::DSO) { - log_debug (LOG_ASSEMBLY, "Looking for hash 0x%zx in DSO cache", hash); + log_debug (LOG_ASSEMBLY, "Looking for hash {:x} in DSO cache", hash); arr = dso_cache; arr_size = application_config.number_of_dso_cache_entries; } diff --git a/src/native/mono/runtime-base/util.cc b/src/native/mono/runtime-base/util.cc index b017af23220..a5159f1f066 100644 --- a/src/native/mono/runtime-base/util.cc +++ b/src/native/mono/runtime-base/util.cc @@ -149,7 +149,7 @@ Util::create_public_directory (const char *dir) { int ret = create_directory (dir, 0777, 0); if (ret < 0) { - log_warn (LOG_DEFAULT, "Failed to create public directory '%s'. %s", dir, std::strerror (errno)); + log_warn (LOG_DEFAULT, "Failed to create directory '{}'. {}", dir, std::strerror (errno)); } } diff --git a/src/native/mono/xamarin-app-stub/xamarin-app.hh b/src/native/mono/xamarin-app-stub/xamarin-app.hh index 3e89c184057..860d59a263e 100644 --- a/src/native/mono/xamarin-app-stub/xamarin-app.hh +++ b/src/native/mono/xamarin-app-stub/xamarin-app.hh @@ -399,4 +399,8 @@ MONO_API MONO_API_EXPORT uint8_t embedded_runtime_config[]; MONO_API MONO_API_EXPORT size_t embedded_assembly_store_size; MONO_API MONO_API_EXPORT uint8_t embedded_assembly_store[]; + +using get_function_pointer_fn = void(*)(uint32_t mono_image_index, uint32_t class_index, uint32_t method_token, void*& target_ptr); +MONO_API MONO_API_EXPORT void xamarin_app_init (JNIEnv *env, get_function_pointer_fn fn) noexcept; + #endif // __XAMARIN_ANDROID_TYPEMAP_H From 5a344664f6a8d509e2261215d5cbf7d043c84df9 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Tue, 27 May 2025 17:09:48 +0200 Subject: [PATCH 50/60] Post-rebase fixes --- .../mono/monodroid/embedded-assemblies.cc | 45 ------------------- .../mono/monodroid/embedded-assemblies.hh | 24 ++++++---- 2 files changed, 16 insertions(+), 53 deletions(-) diff --git a/src/native/mono/monodroid/embedded-assemblies.cc b/src/native/mono/monodroid/embedded-assemblies.cc index 443540226a1..73bb98e4751 100644 --- a/src/native/mono/monodroid/embedded-assemblies.cc +++ b/src/native/mono/monodroid/embedded-assemblies.cc @@ -910,51 +910,6 @@ EmbeddedAssemblies::typemap_managed_to_java (MonoReflectionType *reflection_type return ret; } -EmbeddedAssemblies::md_mmap_info -EmbeddedAssemblies::md_mmap_apk_file (int fd, uint32_t offset, size_t size, const char* filename) -{ - md_mmap_info file_info; - md_mmap_info mmap_info; - - size_t pageSize = static_cast(Util::monodroid_getpagesize ()); - size_t offsetFromPage = offset % pageSize; - size_t offsetPage = offset - offsetFromPage; - size_t offsetSize = size + offsetFromPage; - - mmap_info.area = mmap (nullptr, offsetSize, PROT_READ, MAP_PRIVATE, fd, static_cast(offsetPage)); - - if (mmap_info.area == MAP_FAILED) { - Helpers::abort_application ( - LOG_ASSEMBLY, - std::format ( - "Could not mmap APK fd {}: {}; File={}", - fd, - strerror (errno), - optional_string (filename) - ) - ); - } - - mmap_info.size = offsetSize; - file_info.area = pointer_add (mmap_info.area, offsetFromPage); - file_info.size = size; - - log_info ( - LOG_ASSEMBLY, - " mmap_start: {:<8p}; mmap_end: {:<8p} mmap_len: {:<12} file_start: {:<8p} file_end: {:<8p} file_len: {:<12} apk descriptor: {} file: {}", - mmap_info.area, - pointer_add (mmap_info.area, mmap_info.size), - mmap_info.size, - file_info.area, - pointer_add (file_info.area, file_info.size), - file_info.size, - fd, - optional_string (filename) - ); - - return file_info; -} - void EmbeddedAssemblies::gather_bundled_assemblies_from_apk (const char* apk, monodroid_should_register should_register) noexcept { diff --git a/src/native/mono/monodroid/embedded-assemblies.hh b/src/native/mono/monodroid/embedded-assemblies.hh index 2087773b5c9..807437c62cb 100644 --- a/src/native/mono/monodroid/embedded-assemblies.hh +++ b/src/native/mono/monodroid/embedded-assemblies.hh @@ -194,7 +194,7 @@ namespace xamarin::android::internal { runtime_config_data_size = 0uz; } - bool keep_scanning () const noexcept + static bool keep_scanning () noexcept { return need_to_scan_more_apks; } @@ -280,9 +280,17 @@ namespace xamarin::android::internal { adjusted_info.area = (void*)((const char*)original_info.area + offsetFromPage); adjusted_info.size = size; - log_info (LOG_ASSEMBLY, "mmap_start: %08p mmap_end: %08p mmap_len: % 12u file_start: %08p file_end: %08p file_len: % 12u; apk descriptor: %d; file: %s", - original_info.area, reinterpret_cast (original_info.area) + original_info.size, original_info.size, - adjusted_info.area, reinterpret_cast (adjusted_info.area) + adjusted_info.size, adjusted_info.size, fd, filename + log_info ( + LOG_ASSEMBLY, + " mmap_start: {:<8p}; mmap_end: {:<8p} mmap_len: {:<12} file_start: {:<8p} file_end: {:<8p} file_len: {:<12} apk descriptor: {} file: {}", + original_info.area, + pointer_add (original_info.area, original_info.size), + original_info.size, + adjusted_info.area, + pointer_add (adjusted_info.area, adjusted_info.size), + adjusted_info.size, + fd, + optional_string (filename) ); return adjusted_info; @@ -305,12 +313,12 @@ namespace xamarin::android::internal { static void get_assembly_data (XamarinAndroidBundledAssembly const& e, uint8_t*& assembly_data, uint32_t& assembly_data_size) noexcept; static void get_assembly_data (AssemblyStoreSingleAssemblyRuntimeData const& e, uint8_t*& assembly_data, uint32_t& assembly_data_size) noexcept; - static void zip_load_entries (int fd, const char *apk_name, monodroid_should_register should_register); + static void zip_load_entries (int fd, const char *apk_name, monodroid_should_register should_register) noexcept; static void zip_load_individual_assembly_entries (std::span const& buf, uint32_t num_entries, monodroid_should_register should_register, ZipEntryLoadState &state) noexcept; static void zip_load_assembly_store_entries (std::span const& buf, uint32_t num_entries, ZipEntryLoadState &state) noexcept; static bool zip_load_entry_common (size_t entry_index, std::span const& buf, dynamic_local_string &entry_name, ZipEntryLoadState &state) noexcept; - static bool zip_read_cd_info (int fd, uint32_t& cd_offset, uint32_t& cd_size, uint16_t& cd_entries); - static bool zip_adjust_data_offset (int fd, ZipEntryLoadState &state); + static bool zip_read_cd_info (int fd, uint32_t& cd_offset, uint32_t& cd_size, uint16_t& cd_entries) noexcept; + static bool zip_adjust_data_offset (int fd, ZipEntryLoadState &state) noexcept; template static bool zip_extract_cd_info (std::array const& buf, uint32_t& cd_offset, uint32_t& cd_size, uint16_t& cd_entries) noexcept; @@ -330,7 +338,7 @@ namespace xamarin::android::internal { template static bool zip_read_field (T const& buf, size_t index, size_t count, dynamic_local_string& characters) noexcept; - static bool zip_read_entry_info (std::span const& buf, dynamic_local_string& file_name, ZipEntryLoadState &state); + static bool zip_read_entry_info (std::span const& buf, dynamic_local_string& file_name, ZipEntryLoadState &state) noexcept; [[gnu::always_inline]] static std::tuple get_wrapper_dso_payload_pointer_and_size (md_mmap_info const& map_info, const char *file_name) noexcept From c73b422d4f5beaa0908cb6d90ddf177d2c2aed5d Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Wed, 28 May 2025 12:38:21 +0200 Subject: [PATCH 51/60] A handful of NRT fixes + reuse shared code --- .../Tasks/CreateAssemblyStore.cs | 39 +---------- .../Tasks/CreateEmbeddedAssemblyStore.cs | 67 +++++-------------- .../Utilities/AssemblyPackagingHelper.cs | 48 ++++++++++--- .../Utilities/ELFEmbeddingHelper.cs | 8 ++- 4 files changed, 64 insertions(+), 98 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/CreateAssemblyStore.cs b/src/Xamarin.Android.Build.Tasks/Tasks/CreateAssemblyStore.cs index eb0a3724295..55ef0d7252d 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/CreateAssemblyStore.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/CreateAssemblyStore.cs @@ -36,49 +36,16 @@ public class CreateAssemblyStore : AndroidTask public override bool RunTask () { // Get all the user and framework assemblies we may need to package - var assemblies = ResolvedFrameworkAssemblies.Concat (ResolvedUserAssemblies).Where (asm => !(ShouldSkipAssembly (asm))).ToArray (); + var assemblies = ResolvedFrameworkAssemblies.Concat (ResolvedUserAssemblies).Where (asm => !(AssemblyPackagingHelper.ShouldSkipAssembly (Log, asm))); if (!UseAssemblyStore) { - AssembliesToAddToArchive = assemblies; + AssembliesToAddToArchive = assemblies.ToArray (); return !Log.HasLoggedErrors; } - var store_builder = new AssemblyStoreBuilder (Log); - var per_arch_assemblies = MonoAndroidHelper.GetPerArchAssemblies (assemblies, SupportedAbis, true); - - foreach (var kvp in per_arch_assemblies) { - Log.LogDebugMessage ($"Adding assemblies for architecture '{kvp.Key}'"); - - foreach (var assembly in kvp.Value.Values) { - var sourcePath = assembly.GetMetadataOrDefault ("CompressedAssembly", assembly.ItemSpec); - store_builder.AddAssembly (sourcePath, assembly, includeDebugSymbols: IncludeDebugSymbols); - - Log.LogDebugMessage ($"Added '{sourcePath}' to assembly store."); - } - } - - var assembly_store_paths = store_builder.Generate (AppSharedLibrariesDir); - - if (assembly_store_paths.Count == 0) { - throw new InvalidOperationException ("Assembly store generator did not generate any stores"); - } - - if (assembly_store_paths.Count != SupportedAbis.Length) { - throw new InvalidOperationException ("Internal error: assembly store did not generate store for each supported ABI"); - } - + var assembly_store_paths = AssemblyPackagingHelper.CreateAssemblyStore (Log, assemblies, AppSharedLibrariesDir, SupportedAbis, IncludeDebugSymbols); AssembliesToAddToArchive = assembly_store_paths.Select (kvp => new TaskItem (kvp.Value, new Dictionary { { "Abi", MonoAndroidHelper.ArchToAbi (kvp.Key) } })).ToArray (); return !Log.HasLoggedErrors; } - - bool ShouldSkipAssembly (ITaskItem asm) - { - var should_skip = asm.GetMetadataOrDefault ("AndroidSkipAddToPackage", false); - - if (should_skip) - Log.LogDebugMessage ($"Skipping {asm.ItemSpec} due to 'AndroidSkipAddToPackage' == 'true' "); - - return should_skip; - } } diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/CreateEmbeddedAssemblyStore.cs b/src/Xamarin.Android.Build.Tasks/Tasks/CreateEmbeddedAssemblyStore.cs index d6eda689509..c75474ef7aa 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/CreateEmbeddedAssemblyStore.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/CreateEmbeddedAssemblyStore.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.Linq; using Microsoft.Android.Build.Tasks; using Microsoft.Build.Framework; @@ -14,37 +15,28 @@ public class CreateEmbeddedAssemblyStore : AndroidTask public override string TaskPrefix => "CEAS"; [Required] - public string AndroidBinUtilsDirectory { get; set; } + public string AndroidBinUtilsDirectory { get; set; } = ""; [Required] - public string AppSharedLibrariesDir { get; set; } + public string AppSharedLibrariesDir { get; set; } = ""; [Required] - public string AssemblySourcesDir { get; set; } - - [Required] - public string CompressedAssembliesDir { get; set; } + public string AssemblySourcesDir { get; set; } = ""; [Required] public bool AssemblyStoreEmbeddedInRuntime { get; set; } [Required] - public bool Debug { get; set; } - - [Required] - public bool EnableCompression { get; set; } + public bool IncludeDebugSymbols { get; set; } [Required] - public string ProjectFullPath { get; set; } + public ITaskItem[] ResolvedUserAssemblies { get; set; } = []; [Required] - public ITaskItem[] ResolvedUserAssemblies { get; set; } + public ITaskItem[] ResolvedFrameworkAssemblies { get; set; } = []; [Required] - public ITaskItem[] ResolvedFrameworkAssemblies { get; set; } - - [Required] - public string [] SupportedAbis { get; set; } + public string [] SupportedAbis { get; set; } = []; public override bool RunTask () { @@ -70,27 +62,14 @@ public override bool RunTask () bool EmbedAssemblyStore () { - bool compress = !Debug && EnableCompression; - IDictionary>? compressedAssembliesInfo = null; - - if (compress) { - string key = CompressedAssemblyInfo.GetKey (ProjectFullPath); - Log.LogDebugMessage ($"[{TaskPrefix}] Retrieving assembly compression info with key '{key}'"); - compressedAssembliesInfo = BuildEngine4.GetRegisteredTaskObjectAssemblyLocal>> (key, RegisteredTaskObjectLifetime.Build); - if (compressedAssembliesInfo == null) { - throw new InvalidOperationException ($"Assembly compression info not found for key '{key}'. Compression will not be performed."); - } - } - - var storeBuilder = new AssemblyStoreBuilder (Log); + var assemblies = ResolvedFrameworkAssemblies.Concat (ResolvedUserAssemblies).Where (asm => !(AssemblyPackagingHelper.ShouldSkipAssembly (Log, asm))); + var assemblyStorePaths = AssemblyPackagingHelper.CreateAssemblyStore ( + Log, assemblies, + Path.Combine (AppSharedLibrariesDir, "embedded"), + SupportedAbis, + IncludeDebugSymbols + ); - // Add user assemblies - AssemblyPackagingHelper.AddAssembliesFromCollection (Log, SupportedAbis, ResolvedUserAssemblies, DoAddAssembliesFromArchCollection); - - // Add framework assemblies - AssemblyPackagingHelper.AddAssembliesFromCollection (Log, SupportedAbis, ResolvedFrameworkAssemblies, DoAddAssembliesFromArchCollection); - - Dictionary assemblyStorePaths = storeBuilder.Generate (Path.Combine (AppSharedLibrariesDir, "embedded")); foreach (var kvp in assemblyStorePaths) { string abi = MonoAndroidHelper.ArchToAbi (kvp.Key); string inputFile = kvp.Value; @@ -107,21 +86,5 @@ bool EmbedAssemblyStore () } return !Log.HasLoggedErrors; - - void DoAddAssembliesFromArchCollection (TaskLoggingHelper log, AndroidTargetArch arch, ITaskItem assembly) - { - string sourcePath = CompressAssembly (assembly); - storeBuilder.AddAssembly (sourcePath, assembly, includeDebugSymbols: Debug); - return; - } - - string CompressAssembly (ITaskItem assembly) - { - if (!compress) { - return assembly.ItemSpec; - } - - return AssemblyCompression.Compress (Log, assembly, compressedAssembliesInfo, CompressedAssembliesDir); - } } } diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/AssemblyPackagingHelper.cs b/src/Xamarin.Android.Build.Tasks/Utilities/AssemblyPackagingHelper.cs index 1599a8e581e..572af36521b 100644 --- a/src/Xamarin.Android.Build.Tasks/Utilities/AssemblyPackagingHelper.cs +++ b/src/Xamarin.Android.Build.Tasks/Utilities/AssemblyPackagingHelper.cs @@ -10,20 +10,52 @@ namespace Xamarin.Android.Tasks; static class AssemblyPackagingHelper { + public static bool ShouldSkipAssembly (TaskLoggingHelper log, ITaskItem asm) + { + var should_skip = asm.GetMetadataOrDefault ("AndroidSkipAddToPackage", false); + + if (should_skip) { + log.LogDebugMessage ($"Skipping {asm.ItemSpec} due to 'AndroidSkipAddToPackage' == 'true' "); + } + + return should_skip; + } + + public static Dictionary CreateAssemblyStore (TaskLoggingHelper log, IEnumerable assemblies, string outputDir, string[] supportedAbis, bool includeDebugSymbols) + { + var storeBuilder = new AssemblyStoreBuilder (log); + var per_arch_assemblies = MonoAndroidHelper.GetPerArchAssemblies (assemblies, supportedAbis, true); + + foreach (var kvp in per_arch_assemblies) { + log.LogDebugMessage ($"Adding assemblies for architecture '{kvp.Key}'"); + + foreach (var assembly in kvp.Value.Values) { + var sourcePath = assembly.GetMetadataOrDefault ("CompressedAssembly", assembly.ItemSpec); + storeBuilder.AddAssembly (sourcePath, assembly, includeDebugSymbols: includeDebugSymbols); + + log.LogDebugMessage ($"Added '{sourcePath}' to assembly store."); + } + } + + Dictionary assemblyStorePaths = storeBuilder.Generate (outputDir); + if (assemblyStorePaths.Count == 0) { + throw new InvalidOperationException ("Assembly store generator did not generate any stores"); + } + + if (assemblyStorePaths.Count != supportedAbis.Length) { + throw new InvalidOperationException ("Internal error: assembly store did not generate store for each supported ABI"); + } + + return assemblyStorePaths; + } + public static void AddAssembliesFromCollection (TaskLoggingHelper Log, ICollection SupportedAbis, ICollection assemblies, Action doAddAssembly) { Dictionary> perArchAssemblies = MonoAndroidHelper.GetPerArchAssemblies ( assemblies, SupportedAbis, validate: true, - shouldSkip: (ITaskItem asm) => { - if (bool.TryParse (asm.GetMetadata ("AndroidSkipAddToPackage"), out bool value) && value) { - Log.LogDebugMessage ($"Skipping {asm.ItemSpec} due to 'AndroidSkipAddToPackage' == 'true' "); - return true; - } - - return false; - } + shouldSkip: (ITaskItem asm) => ShouldSkipAssembly (Log, asm) ); foreach (var kvp in perArchAssemblies) { diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/ELFEmbeddingHelper.cs b/src/Xamarin.Android.Build.Tasks/Utilities/ELFEmbeddingHelper.cs index 52704354a63..7481164a829 100644 --- a/src/Xamarin.Android.Build.Tasks/Utilities/ELFEmbeddingHelper.cs +++ b/src/Xamarin.Android.Build.Tasks/Utilities/ELFEmbeddingHelper.cs @@ -108,13 +108,17 @@ static void DoEmbed ( var fi = new FileInfo (inputFile); if (fi.Exists) { inputFileSize = fi.Length; - sanitizedInputFilePath = inputFile.Replace ("\\", "\\\\"); + sanitizedInputFilePath = inputFile!.Replace ("\\", "\\\\"); } else if (!missingContentOK) { throw new InvalidOperationException ($"Internal error: input file '{inputFile}' does not exist"); } } - string asmSourceFile = NativeAssemblerItemsHelper.GetSourcePath (log, item.NativeAssemblerMode, outputDirectory, arch); + string? asmSourceFile = NativeAssemblerItemsHelper.GetSourcePath (log, item.NativeAssemblerMode, outputDirectory, arch); + if (String.IsNullOrEmpty (asmSourceFile)) { + log.LogError ("Unable to embed a binary file in native assembly, no assembly source path given."); + return; + } Directory.CreateDirectory (Path.GetDirectoryName (asmSourceFile)); using var fs = File.Open (asmSourceFile, FileMode.Create, FileAccess.Write, FileShare.Read); From 0af08487a493853b0968da94f06d6090cd9e53db Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Wed, 28 May 2025 13:00:00 +0200 Subject: [PATCH 52/60] MSBuild updates + cleanup --- .../Microsoft.Android.Sdk.AssemblyStores.targets | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.AssemblyStores.targets b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.AssemblyStores.targets index 22fa9dca278..07360e4deec 100644 --- a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.AssemblyStores.targets +++ b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.AssemblyStores.targets @@ -21,15 +21,17 @@ DependsOnTargets="_PrepareCreateEmbeddedAssemblyStoreOutputItems" Inputs="@(_CreateEmbeddedAssemblyStoreAssembly)" Outputs="@(_EmbeddedAssemblyStoreSourceFiles)"> + + <_EmbedAssemblyStoreInRuntime Condition=" '$(_AndroidUseAssemblyStore)' And '$(_AndroidEmbedAssemblyStoreInRuntime)' ">true + <_EmbedAssemblyStoreInRuntime Condition=" '$(_EmbedAssemblyStoreInRuntime)' != 'true' ">false + + From f1b5ccc89bba9e09a75175be455c5e28fddd4162 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Wed, 28 May 2025 13:52:25 +0200 Subject: [PATCH 53/60] Embed runtime config for MonoVM --- ...crosoft.Android.Sdk.AssemblyStores.targets | 5 -- .../CollectRuntimeConfigFilesForArchive.cs | 59 ------------------- .../GenerateNativeApplicationConfigSources.cs | 15 ++++- .../Xamarin.Android.Common.targets | 25 +++----- 4 files changed, 23 insertions(+), 81 deletions(-) delete mode 100644 src/Xamarin.Android.Build.Tasks/Tasks/CollectRuntimeConfigFilesForArchive.cs diff --git a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.AssemblyStores.targets b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.AssemblyStores.targets index 07360e4deec..1547a850e7a 100644 --- a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.AssemblyStores.targets +++ b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.AssemblyStores.targets @@ -21,11 +21,6 @@ DependsOnTargets="_PrepareCreateEmbeddedAssemblyStoreOutputItems" Inputs="@(_CreateEmbeddedAssemblyStoreAssembly)" Outputs="@(_EmbeddedAssemblyStoreSourceFiles)"> - - <_EmbedAssemblyStoreInRuntime Condition=" '$(_AndroidUseAssemblyStore)' And '$(_AndroidEmbedAssemblyStoreInRuntime)' ">true - <_EmbedAssemblyStoreInRuntime Condition=" '$(_EmbedAssemblyStoreInRuntime)' != 'true' ">false - - -/// Collects rc.bin to be added to the final archive. -/// -public class CollectRuntimeConfigFilesForArchive : AndroidTask -{ - const string ArchiveLibPath = "lib"; - - public override string TaskPrefix => "CRF"; - - [Required] - public string AndroidBinUtilsDirectory { get; set; } = ""; - - [Required] - public ITaskItem[] RuntimePackLibraryDirectories { get; set; } = Array.Empty (); - - [Required] - public string IntermediateOutputPath { get; set; } = ""; - - public string RuntimeConfigBinFilePath { get; set; } = ""; - - [Required] - public string [] SupportedAbis { get; set; } = []; - - [Output] - public ITaskItem [] FilesToAddToArchive { get; set; } = []; - - public override bool RunTask () - { - var files = new PackageFileListBuilder (); - var dsoWrapperConfig = DSOWrapperGenerator.GetConfig (Log, AndroidBinUtilsDirectory, RuntimePackLibraryDirectories, IntermediateOutputPath); - - // We will place rc.bin in the `lib` directory next to the blob, to make startup slightly faster, as we will find the config file right after we encounter - // our assembly store. Not only that, but also we'll be able to skip scanning the `base.apk` archive when split configs are enabled (which they are in 99% - // of cases these days, since AAB enforces that split). `base.apk` contains only ABI-agnostic file, while one of the split config files contains only - // ABI-specific data+code. - if (!string.IsNullOrEmpty (RuntimeConfigBinFilePath) && File.Exists (RuntimeConfigBinFilePath)) { - foreach (var abi in SupportedAbis) { - // Prefix it with `a` because bundletool sorts entries alphabetically, and this will place it right next to `assemblies.*.blob.so`, which is what we - // like since we can finish scanning the zip central directory earlier at startup. - var inArchivePath = MakeArchiveLibPath (abi, "libarc.bin.so"); - var wrappedSourcePath = DSOWrapperGenerator.WrapIt (Log, dsoWrapperConfig, MonoAndroidHelper.AbiToTargetArch (abi), RuntimeConfigBinFilePath, Path.GetFileName (inArchivePath)); - files.AddItem (wrappedSourcePath, inArchivePath); - } - } - - FilesToAddToArchive = files.ToArray (); - - return !Log.HasLoggedErrors; - } - - static string MakeArchiveLibPath (string abi, string fileName) => MonoAndroidHelper.MakeZipArchivePath (ArchiveLibPath, abi, fileName); -} diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/GenerateNativeApplicationConfigSources.cs b/src/Xamarin.Android.Build.Tasks/Tasks/GenerateNativeApplicationConfigSources.cs index c905016a9c3..09fe12b1c24 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/GenerateNativeApplicationConfigSources.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/GenerateNativeApplicationConfigSources.cs @@ -50,6 +50,9 @@ public class GenerateNativeApplicationConfigSources : AndroidTask [Required] public bool TargetsCLR { get; set; } + [Required] + public string AndroidBinUtilsDirectory { get; set; } = ""; + public bool EnableMarshalMethods { get; set; } public bool EnableManagedMarshalMethodsLookup { get; set; } public string? RuntimeConfigBinFilePath { get; set; } @@ -248,7 +251,6 @@ public override bool RunTask () } } - bool haveRuntimeConfigBlob = !String.IsNullOrEmpty (RuntimeConfigBinFilePath) && File.Exists (RuntimeConfigBinFilePath); var jniRemappingNativeCodeInfo = BuildEngine4.GetRegisteredTaskObjectAssemblyLocal (ProjectSpecificTaskObjectKey (GenerateJniRemappingNativeCode.JniRemappingNativeCodeInfoKey), RegisteredTaskObjectLifetime.Build); LLVMIR.LlvmIrComposer appConfigAsmGen; @@ -272,6 +274,17 @@ public override bool RunTask () IgnoreSplitConfigs = ShouldIgnoreSplitConfigs (), }; } else { + bool haveRuntimeConfigBlob = !String.IsNullOrEmpty (RuntimeConfigBinFilePath) && File.Exists (RuntimeConfigBinFilePath); + ELFEmbeddingHelper.EmbedBinary ( + Log, + SupportedAbis, + AndroidBinUtilsDirectory, + RuntimeConfigBinFilePath, + ELFEmbeddingHelper.KnownEmbedItems.RuntimeConfig, + EnvironmentOutputDirectory, + missingContentOK: !haveRuntimeConfigBlob + ); + appConfigAsmGen = new ApplicationConfigNativeAssemblyGenerator (environmentVariables, systemProperties, Log) { UsesMonoAOT = usesMonoAOT, UsesMonoLLVM = EnableLLVM, diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets index 26cac5ff469..47c6ac9a62d 100644 --- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets +++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets @@ -344,6 +344,9 @@ Copyright (C) 2011-2012 Xamarin. All rights reserved. false true <_AndroidUseAssemblyStore>$(AndroidUseAssemblyStore) + + <_EmbedAssemblyStoreInRuntime Condition=" '$(_AndroidUseAssemblyStore)' == 'True' And '$(_AndroidEmbedAssemblyStoreInRuntime)' == 'True' ">true + <_EmbedAssemblyStoreInRuntime Condition=" '$(_EmbedAssemblyStoreInRuntime)' != 'true' ">false + ProjectRuntimeConfigFilePath="$(ProjectRuntimeConfigFilePath)" + AndroidBinUtilsDirectory="$(AndroidBinUtilsDirectory)"> - + @@ -2336,7 +2340,7 @@ because xbuild doesn't support framework reference assemblies. in monodroid. --> - - - - - Date: Wed, 28 May 2025 14:14:27 +0200 Subject: [PATCH 54/60] Fix DSO counts --- .../GenerateNativeApplicationConfigSources.cs | 17 +++++++++++++++++ ...plicationConfigNativeAssemblyGeneratorCLR.cs | 3 ++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/GenerateNativeApplicationConfigSources.cs b/src/Xamarin.Android.Build.Tasks/Tasks/GenerateNativeApplicationConfigSources.cs index 09fe12b1c24..e4dda651f24 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/GenerateNativeApplicationConfigSources.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/GenerateNativeApplicationConfigSources.cs @@ -8,6 +8,7 @@ using System.Reflection.PortableExecutable; using System.Text; using Microsoft.Build.Framework; +using Microsoft.Build.Utilities; using Java.Interop.Tools.TypeNameMappings; using Xamarin.Android.Tools; @@ -237,6 +238,10 @@ public override bool RunTask () } var uniqueNativeLibraries = new List (); + + // Number of DSOs that will be packaged, it may be different to the number of items in the above + // `uniqueNativeLibraries` list. + uint packagedNativeLibrariesCount = 0; var seenNativeLibraryNames = new HashSet (StringComparer.OrdinalIgnoreCase); if (NativeLibraries != null) { foreach (ITaskItem item in NativeLibraries) { @@ -246,9 +251,19 @@ public override bool RunTask () continue; } + if (!ELFHelper.IsEmptyAOTLibrary (Log, item.ItemSpec)) { + packagedNativeLibrariesCount++; + } + seenNativeLibraryNames.Add (name); uniqueNativeLibraries.Add (item); } + + // libxamarin-app.so is not in NativeLibraries, but we must count it + if (!seenNativeLibraryNames.Contains ("libxamarin-app.so")) { + uniqueNativeLibraries.Add (new TaskItem ("libxamarin-app.so")); + packagedNativeLibrariesCount++; + } } var jniRemappingNativeCodeInfo = BuildEngine4.GetRegisteredTaskObjectAssemblyLocal (ProjectSpecificTaskObjectKey (GenerateJniRemappingNativeCode.JniRemappingNativeCodeInfoKey), RegisteredTaskObjectLifetime.Build); @@ -264,6 +279,7 @@ public override bool RunTask () NumberOfAssembliesInApk = assemblyCount, BundledAssemblyNameWidth = assemblyNameWidth, NativeLibraries = uniqueNativeLibraries, + PackagedNativeLibrariesCount = packagedNativeLibrariesCount, AndroidRuntimeJNIEnvToken = android_runtime_jnienv_class_token, JNIEnvInitializeToken = jnienv_initialize_method_token, JNIEnvRegisterJniNativesToken = jnienv_registerjninatives_method_token, @@ -301,6 +317,7 @@ public override bool RunTask () BundledAssemblyNameWidth = assemblyNameWidth, MonoComponents = (MonoComponent)monoComponents, NativeLibraries = uniqueNativeLibraries, + PackagedNativeLibrariesCount = packagedNativeLibrariesCount, HaveAssemblyStore = UseAssemblyStore, AndroidRuntimeJNIEnvToken = android_runtime_jnienv_class_token, JNIEnvInitializeToken = jnienv_initialize_method_token, diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/ApplicationConfigNativeAssemblyGeneratorCLR.cs b/src/Xamarin.Android.Build.Tasks/Utilities/ApplicationConfigNativeAssemblyGeneratorCLR.cs index ca8bc0d5f55..88bd177000c 100644 --- a/src/Xamarin.Android.Build.Tasks/Utilities/ApplicationConfigNativeAssemblyGeneratorCLR.cs +++ b/src/Xamarin.Android.Build.Tasks/Utilities/ApplicationConfigNativeAssemblyGeneratorCLR.cs @@ -211,6 +211,7 @@ sealed class XamarinAndroidBundledAssembly public bool MarshalMethodsEnabled { get; set; } public bool ManagedMarshalMethodsLookupEnabled { get; set; } public bool IgnoreSplitConfigs { get; set; } + public uint PackagedNativeLibrariesCount { get; set; } public ApplicationConfigNativeAssemblyGeneratorCLR (IDictionary environmentVariables, IDictionary systemProperties, IDictionary? runtimeProperties, TaskLoggingHelper log) @@ -266,7 +267,7 @@ protected override void Construct (LlvmIrModule module) environment_variable_count = (uint)(environmentVariables == null ? 0 : environmentVariables.Count * 2), system_property_count = (uint)(systemProperties == null ? 0 : systemProperties.Count * 2), number_of_assemblies_in_apk = (uint)NumberOfAssembliesInApk, - number_of_shared_libraries = (uint)NativeLibraries.Count, + number_of_shared_libraries = PackagedNativeLibrariesCount, bundled_assembly_name_width = (uint)BundledAssemblyNameWidth, number_of_dso_cache_entries = (uint)dsoCache.Count, number_of_aot_cache_entries = (uint)aotDsoCache.Count, From 642167072c0acf85541b05b3c7fd4c2cd2c42888 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Wed, 28 May 2025 15:38:11 +0200 Subject: [PATCH 55/60] Fix MonoVM diagnostic messages --- .../mono/monodroid/embedded-assemblies-zip.cc | 21 +++++++++---------- .../mono/monodroid/embedded-assemblies.hh | 1 + 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/native/mono/monodroid/embedded-assemblies-zip.cc b/src/native/mono/monodroid/embedded-assemblies-zip.cc index 42cf610ab3e..30e01a25fbd 100644 --- a/src/native/mono/monodroid/embedded-assemblies-zip.cc +++ b/src/native/mono/monodroid/embedded-assemblies-zip.cc @@ -184,9 +184,9 @@ EmbeddedAssemblies::verify_assembly_store_and_set_info (void *data_start, const if (header->magic != ASSEMBLY_STORE_MAGIC) { Helpers::abort_application ( LOG_ASSEMBLY, - Util::monodroid_strdup_printf ( - "Assembly store '%s' is not a valid .NET for Android assembly store file", - name + std::format ( + "Assembly store '{}' is not a valid .NET for Android assembly store file", + optional_string (name) ) ); } @@ -194,9 +194,9 @@ EmbeddedAssemblies::verify_assembly_store_and_set_info (void *data_start, const if (header->version != ASSEMBLY_STORE_FORMAT_VERSION) { Helpers::abort_application ( LOG_ASSEMBLY, - Util::monodroid_strdup_printf ( - "Assembly store '%s' uses format version 0x%x, instead of the expected 0x%x", - name, + std::format ( + "Assembly store '{}' uses format version 0x{:x}, instead of the expected 0x{:x}", + optional_string (name), header->version, ASSEMBLY_STORE_FORMAT_VERSION ) @@ -269,10 +269,9 @@ EmbeddedAssemblies::zip_load_assembly_store_entries (std::span const& b load_embedded_assembly_store (); log_debug (LOG_ASSEMBLY, "Looking for DSOs in APK"); } else { - log_debug (LOG_ASSEMBLY, "Looking for assembly store ('%s') and DSOs in APK", assembly_store_file_path.data ()); + log_debug (LOG_ASSEMBLY, "Looking for assembly store ('{}') and DSOs in APK", assembly_store_file_path); } - log_debug (LOG_ASSEMBLY, "Looking for assembly stores in APK ('{}')", assembly_store_file_path.data ()); for (size_t i = 0uz; i < num_entries; i++) { if (all_required_zip_entries_found ()) { need_to_scan_more_apks = false; @@ -338,9 +337,9 @@ EmbeddedAssemblies::zip_load_entries (int fd, const char *apk_name, [[maybe_unus ); } - log_debug (LOG_ASSEMBLY, "Central directory offset: %u", cd_offset); - log_debug (LOG_ASSEMBLY, "Central directory size: %u", cd_size); - log_debug (LOG_ASSEMBLY, "Central directory entries: %u", cd_entries); + log_debug (LOG_ASSEMBLY, "Central directory offset: {}", cd_offset); + log_debug (LOG_ASSEMBLY, "Central directory size: {}", cd_size); + log_debug (LOG_ASSEMBLY, "Central directory entries: {}", cd_entries); off_t retval = ::lseek (fd, static_cast(cd_offset), SEEK_SET); if (retval < 0) [[unlikely]] { diff --git a/src/native/mono/monodroid/embedded-assemblies.hh b/src/native/mono/monodroid/embedded-assemblies.hh index 807437c62cb..da3a86328f6 100644 --- a/src/native/mono/monodroid/embedded-assemblies.hh +++ b/src/native/mono/monodroid/embedded-assemblies.hh @@ -428,6 +428,7 @@ namespace xamarin::android::internal { static void load_embedded_assembly_store () noexcept { + log_debug (LOG_ASSEMBLY, "Loading embedded assembly store"); verify_assembly_store_and_set_info (embedded_assembly_store, "embedded"); } From 3714379916f9f13db58a4475516eb10233bb20e1 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Thu, 29 May 2025 11:42:05 +0200 Subject: [PATCH 56/60] Add support for CoreCLR --- .../Xamarin.Android.Common.targets | 7 ++- src/native/clr/host/assembly-store.cc | 56 ++++++++++--------- src/native/clr/host/host.cc | 12 ++++ src/native/clr/include/host/assembly-store.hh | 3 + src/native/clr/include/host/host.hh | 5 +- src/native/clr/include/xamarin-app.hh | 8 ++- .../xamarin-app-stub/application_dso_stub.cc | 3 + 7 files changed, 63 insertions(+), 31 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets index 47c6ac9a62d..35f410656c9 100644 --- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets +++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets @@ -344,9 +344,6 @@ Copyright (C) 2011-2012 Xamarin. All rights reserved. false true <_AndroidUseAssemblyStore>$(AndroidUseAssemblyStore) - - <_EmbedAssemblyStoreInRuntime Condition=" '$(_AndroidUseAssemblyStore)' == 'True' And '$(_AndroidEmbedAssemblyStoreInRuntime)' == 'True' ">true - <_EmbedAssemblyStoreInRuntime Condition=" '$(_EmbedAssemblyStoreInRuntime)' != 'true' ">false - - - - Date: Thu, 29 May 2025 15:30:42 +0200 Subject: [PATCH 58/60] Remove unnecessary app config field --- .../GenerateNativeApplicationConfigSources.cs | 1 - .../Utilities/EnvironmentHelper.cs | 48 ++++++++----------- .../Utilities/ApplicationConfig.cs | 1 - ...pplicationConfigNativeAssemblyGenerator.cs | 2 - .../xamarin-app-stub/application_dso_stub.cc | 1 - .../mono/xamarin-app-stub/xamarin-app.hh | 1 - 6 files changed, 21 insertions(+), 33 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/GenerateNativeApplicationConfigSources.cs b/src/Xamarin.Android.Build.Tasks/Tasks/GenerateNativeApplicationConfigSources.cs index e4dda651f24..acb45995b70 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/GenerateNativeApplicationConfigSources.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/GenerateNativeApplicationConfigSources.cs @@ -312,7 +312,6 @@ public override bool RunTask () PackageNamingPolicy = pnp, BoundExceptionType = boundExceptionType, JniAddNativeMethodRegistrationAttributePresent = NativeCodeGenState.TemplateJniAddNativeMethodRegistrationAttributePresent, - HaveRuntimeConfigBlob = haveRuntimeConfigBlob, NumberOfAssembliesInApk = assemblyCount, BundledAssemblyNameWidth = assemblyNameWidth, MonoComponents = (MonoComponent)monoComponents, diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Utilities/EnvironmentHelper.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Utilities/EnvironmentHelper.cs index 7a86601ce43..7aff38ae573 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Utilities/EnvironmentHelper.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Utilities/EnvironmentHelper.cs @@ -45,7 +45,6 @@ public sealed class ApplicationConfig public bool uses_assembly_preload; public bool broken_exception_transitions; public bool jni_add_native_method_registration_attribute_present; - public bool have_runtime_config_blob; public bool have_assemblies_blob; public bool marshal_methods_enabled; public bool ignore_split_configs; @@ -68,7 +67,7 @@ public sealed class ApplicationConfig public bool managed_marshal_methods_lookup_enabled; } - const uint ApplicationConfigFieldCount = 27; + const uint ApplicationConfigFieldCount = 26; const string ApplicationConfigSymbolName = "application_config"; const string AppEnvironmentVariablesSymbolName = "app_environment_variables"; @@ -237,107 +236,102 @@ static ApplicationConfig ReadApplicationConfig (EnvironmentFile envFile) ret.jni_add_native_method_registration_attribute_present = ConvertFieldToBool ("jni_add_native_method_registration_attribute_present", envFile.Path, parser.SourceFilePath, item.LineNumber, field [1]); break; - case 6: // have_runtime_config_blob: bool / .byte - AssertFieldType (envFile.Path, parser.SourceFilePath, ".byte", field [0], item.LineNumber); - ret.have_runtime_config_blob = ConvertFieldToBool ("have_runtime_config_blob", envFile.Path, parser.SourceFilePath, item.LineNumber, field [1]); - break; - - case 7: // have_assemblies_blob: bool / .byte + case 6: // have_assemblies_blob: bool / .byte AssertFieldType (envFile.Path, parser.SourceFilePath, ".byte", field [0], item.LineNumber); ret.have_assemblies_blob = ConvertFieldToBool ("have_assemblies_blob", envFile.Path, parser.SourceFilePath, item.LineNumber, field [1]); break; - case 8: // marshal_methods_enabled: bool / .byte + case 7: // marshal_methods_enabled: bool / .byte AssertFieldType (envFile.Path, parser.SourceFilePath, ".byte", field [0], item.LineNumber); ret.marshal_methods_enabled = ConvertFieldToBool ("marshal_methods_enabled", envFile.Path, parser.SourceFilePath, item.LineNumber, field [1]); break; - case 9: // ignore_split_configs: bool / .byte + case 8: // ignore_split_configs: bool / .byte AssertFieldType (envFile.Path, parser.SourceFilePath, ".byte", field [0], item.LineNumber); ret.ignore_split_configs = ConvertFieldToBool ("ignore_split_configs", envFile.Path, parser.SourceFilePath, item.LineNumber, field [1]); break; - case 10: // bound_stream_io_exception_type: byte / .byte + case 9: // bound_stream_io_exception_type: byte / .byte AssertFieldType (envFile.Path, parser.SourceFilePath, ".byte", field [0], item.LineNumber); ret.bound_stream_io_exception_type = ConvertFieldToByte ("bound_stream_io_exception_type", envFile.Path, parser.SourceFilePath, item.LineNumber, field [1]); break; - case 11: // package_naming_policy: uint32_t / .word | .long + case 10: // package_naming_policy: uint32_t / .word | .long Assert.IsTrue (expectedUInt32Types.Contains (field [0]), $"Unexpected uint32_t field type in '{envFile.Path}:{item.LineNumber}': {field [0]}"); ret.package_naming_policy = ConvertFieldToUInt32 ("package_naming_policy", envFile.Path, parser.SourceFilePath, item.LineNumber, field [1]); break; - case 12: // environment_variable_count: uint32_t / .word | .long + case 11: // environment_variable_count: uint32_t / .word | .long Assert.IsTrue (expectedUInt32Types.Contains (field [0]), $"Unexpected uint32_t field type in '{envFile.Path}:{item.LineNumber}': {field [0]}"); ret.environment_variable_count = ConvertFieldToUInt32 ("environment_variable_count", envFile.Path, parser.SourceFilePath, item.LineNumber, field [1]); break; - case 13: // system_property_count: uint32_t / .word | .long + case 12: // system_property_count: uint32_t / .word | .long Assert.IsTrue (expectedUInt32Types.Contains (field [0]), $"Unexpected uint32_t field type in '{envFile.Path}:{item.LineNumber}': {field [0]}"); ret.system_property_count = ConvertFieldToUInt32 ("system_property_count", envFile.Path, parser.SourceFilePath, item.LineNumber, field [1]); break; - case 14: // number_of_assemblies_in_apk: uint32_t / .word | .long + case 13: // number_of_assemblies_in_apk: uint32_t / .word | .long Assert.IsTrue (expectedUInt32Types.Contains (field [0]), $"Unexpected uint32_t field type in '{envFile.Path}:{item.LineNumber}': {field [0]}"); ret.number_of_assemblies_in_apk = ConvertFieldToUInt32 ("number_of_assemblies_in_apk", envFile.Path, parser.SourceFilePath, item.LineNumber, field [1]); break; - case 15: // bundled_assembly_name_width: uint32_t / .word | .long + case 14: // bundled_assembly_name_width: uint32_t / .word | .long Assert.IsTrue (expectedUInt32Types.Contains (field [0]), $"Unexpected uint32_t field type in '{envFile.Path}:{item.LineNumber}': {field [0]}"); ret.bundled_assembly_name_width = ConvertFieldToUInt32 ("bundled_assembly_name_width", envFile.Path, parser.SourceFilePath, item.LineNumber, field [1]); break; - case 16: // number_of_assembly_store_files: uint32_t / .word | .long + case 15: // number_of_assembly_store_files: uint32_t / .word | .long Assert.IsTrue (expectedUInt32Types.Contains (field [0]), $"Unexpected uint32_t field type in '{envFile.Path}:{item.LineNumber}': {field [0]}"); ret.number_of_assembly_store_files = ConvertFieldToUInt32 ("number_of_assembly_store_files", envFile.Path, parser.SourceFilePath, item.LineNumber, field [1]); break; - case 17: // number_of_dso_cache_entries: uint32_t / .word | .long + case 16: // number_of_dso_cache_entries: uint32_t / .word | .long Assert.IsTrue (expectedUInt32Types.Contains (field [0]), $"Unexpected uint32_t field type in '{envFile.Path}:{item.LineNumber}': {field [0]}"); ret.number_of_dso_cache_entries = ConvertFieldToUInt32 ("number_of_dso_cache_entries", envFile.Path, parser.SourceFilePath, item.LineNumber, field [1]); break; - case 18: // number_of_aot_cache_entries: uint32_t / .word | .long + case 17: // number_of_aot_cache_entries: uint32_t / .word | .long Assert.IsTrue (expectedUInt32Types.Contains (field [0]), $"Unexpected uint32_t field type in '{envFile.Path}:{item.LineNumber}': {field [0]}"); ret.number_of_aot_cache_entries = ConvertFieldToUInt32 ("number_of_aot_cache_entries", envFile.Path, parser.SourceFilePath, item.LineNumber, field [1]); break; - case 19: // android_runtime_jnienv_class_token: uint32_t / .word | .long + case 18: // android_runtime_jnienv_class_token: uint32_t / .word | .long Assert.IsTrue (expectedUInt32Types.Contains (field [0]), $"Unexpected uint32_t field type in '{envFile.Path}:{item.LineNumber}': {field [0]}"); ret.android_runtime_jnienv_class_token = ConvertFieldToUInt32 ("android_runtime_jnienv_class_token", envFile.Path, parser.SourceFilePath, item.LineNumber, field [1]); break; - case 20: // jnienv_initialize_method_token: uint32_t / .word | .long + case 19: // jnienv_initialize_method_token: uint32_t / .word | .long Assert.IsTrue (expectedUInt32Types.Contains (field [0]), $"Unexpected uint32_t field type in '{envFile.Path}:{item.LineNumber}': {field [0]}"); ret.jnienv_initialize_method_token = ConvertFieldToUInt32 ("jnienv_initialize_method_token", envFile.Path, parser.SourceFilePath, item.LineNumber, field [1]); break; - case 21: // jnienv_registerjninatives_method_token: uint32_t / .word | .long + case 20: // jnienv_registerjninatives_method_token: uint32_t / .word | .long Assert.IsTrue (expectedUInt32Types.Contains (field [0]), $"Unexpected uint32_t field type in '{envFile.Path}:{item.LineNumber}': {field [0]}"); ret.jnienv_registerjninatives_method_token = ConvertFieldToUInt32 ("jnienv_registerjninatives_method_token", envFile.Path, parser.SourceFilePath, item.LineNumber, field [1]); break; - case 22: // jni_remapping_replacement_type_count: uint32_t / .word | .long + case 21: // jni_remapping_replacement_type_count: uint32_t / .word | .long Assert.IsTrue (expectedUInt32Types.Contains (field [0]), $"Unexpected uint32_t field type in '{envFile.Path}:{item.LineNumber}': {field [0]}"); ret.jni_remapping_replacement_type_count = ConvertFieldToUInt32 ("jni_remapping_replacement_type_count", envFile.Path, parser.SourceFilePath, item.LineNumber, field [1]); break; - case 23: // jni_remapping_replacement_method_index_entry_count: uint32_t / .word | .long + case 22: // jni_remapping_replacement_method_index_entry_count: uint32_t / .word | .long Assert.IsTrue (expectedUInt32Types.Contains (field [0]), $"Unexpected uint32_t field type in '{envFile.Path}:{item.LineNumber}': {field [0]}"); ret.jni_remapping_replacement_method_index_entry_count = ConvertFieldToUInt32 ("jni_remapping_replacement_method_index_entry_count", envFile.Path, parser.SourceFilePath, item.LineNumber, field [1]); break; - case 24: // mono_components_mask: uint32_t / .word | .long + case 23: // mono_components_mask: uint32_t / .word | .long Assert.IsTrue (expectedUInt32Types.Contains (field [0]), $"Unexpected uint32_t field type in '{envFile.Path}:{item.LineNumber}': {field [0]}"); ret.mono_components_mask = ConvertFieldToUInt32 ("mono_components_mask", envFile.Path, parser.SourceFilePath, item.LineNumber, field [1]); break; - case 25: // android_package_name: string / [pointer type] + case 24: // android_package_name: string / [pointer type] Assert.IsTrue (expectedPointerTypes.Contains (field [0]), $"Unexpected pointer field type in '{envFile.Path}:{item.LineNumber}': {field [0]}"); pointers.Add (field [1].Trim ()); break; - case 26: // managed_marshal_methods_lookup_enabled: bool / .byte + case 25: // managed_marshal_methods_lookup_enabled: bool / .byte AssertFieldType (envFile.Path, parser.SourceFilePath, ".byte", field [0], item.LineNumber); ret.managed_marshal_methods_lookup_enabled = ConvertFieldToBool ("managed_marshal_methods_lookup_enabled", envFile.Path, parser.SourceFilePath, item.LineNumber, field [1]); break; diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/ApplicationConfig.cs b/src/Xamarin.Android.Build.Tasks/Utilities/ApplicationConfig.cs index 40ea29ee665..f9fcecb7e44 100644 --- a/src/Xamarin.Android.Build.Tasks/Utilities/ApplicationConfig.cs +++ b/src/Xamarin.Android.Build.Tasks/Utilities/ApplicationConfig.cs @@ -30,7 +30,6 @@ sealed class ApplicationConfig public bool uses_assembly_preload; public bool broken_exception_transitions; public bool jni_add_native_method_registration_attribute_present; - public bool have_runtime_config_blob; public bool have_assemblies_blob; public bool marshal_methods_enabled; public bool ignore_split_configs; diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/ApplicationConfigNativeAssemblyGenerator.cs b/src/Xamarin.Android.Build.Tasks/Utilities/ApplicationConfigNativeAssemblyGenerator.cs index d374df67dbb..c45eb1fcaf6 100644 --- a/src/Xamarin.Android.Build.Tasks/Utilities/ApplicationConfigNativeAssemblyGenerator.cs +++ b/src/Xamarin.Android.Build.Tasks/Utilities/ApplicationConfigNativeAssemblyGenerator.cs @@ -182,7 +182,6 @@ sealed class XamarinAndroidBundledAssembly public bool BrokenExceptionTransitions { get; set; } public global::Android.Runtime.BoundExceptionType BoundExceptionType { get; set; } public bool JniAddNativeMethodRegistrationAttributePresent { get; set; } - public bool HaveRuntimeConfigBlob { get; set; } public bool HaveAssemblyStore { get; set; } public int NumberOfAssembliesInApk { get; set; } public int BundledAssemblyNameWidth { get; set; } // including the trailing NUL @@ -238,7 +237,6 @@ protected override void Construct (LlvmIrModule module) uses_assembly_preload = UsesAssemblyPreload, broken_exception_transitions = BrokenExceptionTransitions, jni_add_native_method_registration_attribute_present = JniAddNativeMethodRegistrationAttributePresent, - have_runtime_config_blob = HaveRuntimeConfigBlob, have_assemblies_blob = HaveAssemblyStore, marshal_methods_enabled = MarshalMethodsEnabled, managed_marshal_methods_lookup_enabled = ManagedMarshalMethodsLookupEnabled, diff --git a/src/native/mono/xamarin-app-stub/application_dso_stub.cc b/src/native/mono/xamarin-app-stub/application_dso_stub.cc index 49588a88e38..d60e11c82c9 100644 --- a/src/native/mono/xamarin-app-stub/application_dso_stub.cc +++ b/src/native/mono/xamarin-app-stub/application_dso_stub.cc @@ -48,7 +48,6 @@ const ApplicationConfig application_config = { .uses_assembly_preload = false, .broken_exception_transitions = false, .jni_add_native_method_registration_attribute_present = false, - .have_runtime_config_blob = false, .have_assembly_store = false, .marshal_methods_enabled = false, .ignore_split_configs = false, diff --git a/src/native/mono/xamarin-app-stub/xamarin-app.hh b/src/native/mono/xamarin-app-stub/xamarin-app.hh index 860d59a263e..d8badede691 100644 --- a/src/native/mono/xamarin-app-stub/xamarin-app.hh +++ b/src/native/mono/xamarin-app-stub/xamarin-app.hh @@ -238,7 +238,6 @@ struct ApplicationConfig bool uses_assembly_preload; bool broken_exception_transitions; bool jni_add_native_method_registration_attribute_present; - bool have_runtime_config_blob; bool have_assembly_store; bool marshal_methods_enabled; bool ignore_split_configs; From ac649062915c28c4d2dfb617b14a76f3d3585a47 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Thu, 29 May 2025 16:43:17 +0200 Subject: [PATCH 59/60] Update apkdesc files --- .../BuildReleaseArm64SimpleDotNet.apkdesc | 43 ++++++------ .../BuildReleaseArm64XFormsDotNet.apkdesc | 69 +++++++++---------- 2 files changed, 53 insertions(+), 59 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64SimpleDotNet.apkdesc b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64SimpleDotNet.apkdesc index 0d09c5250f4..53233030a42 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64SimpleDotNet.apkdesc +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64SimpleDotNet.apkdesc @@ -5,31 +5,31 @@ "Size": 3036 }, "classes.dex": { - "Size": 22484 + "Size": 22488 }, "lib/arm64-v8a/lib__Microsoft.Android.Resource.Designer.dll.so": { "Size": 18288 }, "lib/arm64-v8a/lib_Java.Interop.dll.so": { - "Size": 86688 + "Size": 87624 }, "lib/arm64-v8a/lib_Mono.Android.dll.so": { - "Size": 117712 + "Size": 120768 }, "lib/arm64-v8a/lib_Mono.Android.Runtime.dll.so": { - "Size": 22384 + "Size": 23160 }, "lib/arm64-v8a/lib_System.Console.dll.so": { - "Size": 24392 + "Size": 24408 }, "lib/arm64-v8a/lib_System.Linq.dll.so": { - "Size": 25336 + "Size": 25344 }, "lib/arm64-v8a/lib_System.Private.CoreLib.dll.so": { - "Size": 628216 + "Size": 636760 }, "lib/arm64-v8a/lib_System.Runtime.dll.so": { - "Size": 20056 + "Size": 20096 }, "lib/arm64-v8a/lib_System.Runtime.InteropServices.dll.so": { "Size": 21480 @@ -37,41 +37,38 @@ "lib/arm64-v8a/lib_UnnamedProject.dll.so": { "Size": 20024 }, - "lib/arm64-v8a/libarc.bin.so": { - "Size": 18872 - }, "lib/arm64-v8a/libmono-component-marshal-ilgen.so": { - "Size": 36440 + "Size": 36616 }, "lib/arm64-v8a/libmonodroid.so": { - "Size": 1524752 + "Size": 1525968 }, "lib/arm64-v8a/libmonosgen-2.0.so": { - "Size": 3101112 + "Size": 3118632 }, "lib/arm64-v8a/libSystem.Globalization.Native.so": { - "Size": 71976 + "Size": 71952 }, "lib/arm64-v8a/libSystem.IO.Compression.Native.so": { - "Size": 758896 + "Size": 759304 }, "lib/arm64-v8a/libSystem.Native.so": { - "Size": 103520 + "Size": 104312 }, "lib/arm64-v8a/libSystem.Security.Cryptography.Native.Android.so": { - "Size": 165000 + "Size": 165240 }, "lib/arm64-v8a/libxamarin-app.so": { - "Size": 19536 + "Size": 22384 }, "META-INF/BNDLTOOL.RSA": { - "Size": 1221 + "Size": 1223 }, "META-INF/BNDLTOOL.SF": { - "Size": 3266 + "Size": 3167 }, "META-INF/MANIFEST.MF": { - "Size": 3139 + "Size": 3040 }, "res/drawable-hdpi-v4/icon.png": { "Size": 2178 @@ -98,5 +95,5 @@ "Size": 1904 } }, - "PackageSize": 3078677 + "PackageSize": 3099084 } \ No newline at end of file diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64XFormsDotNet.apkdesc b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64XFormsDotNet.apkdesc index cf5b327b70c..c397f8e99d2 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64XFormsDotNet.apkdesc +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64XFormsDotNet.apkdesc @@ -5,7 +5,7 @@ "Size": 6652 }, "classes.dex": { - "Size": 9179108 + "Size": 9173200 }, "kotlin/annotation/annotation.kotlin_builtins": { "Size": 928 @@ -35,13 +35,13 @@ "Size": 25424 }, "lib/arm64-v8a/lib_Java.Interop.dll.so": { - "Size": 96104 + "Size": 96320 }, "lib/arm64-v8a/lib_Mono.Android.dll.so": { - "Size": 562336 + "Size": 562416 }, "lib/arm64-v8a/lib_Mono.Android.Runtime.dll.so": { - "Size": 23224 + "Size": 23200 }, "lib/arm64-v8a/lib_mscorlib.dll.so": { "Size": 21456 @@ -50,25 +50,25 @@ "Size": 23096 }, "lib/arm64-v8a/lib_System.Collections.Concurrent.dll.so": { - "Size": 29896 + "Size": 29904 }, "lib/arm64-v8a/lib_System.Collections.dll.so": { "Size": 36304 }, "lib/arm64-v8a/lib_System.Collections.NonGeneric.dll.so": { - "Size": 25776 + "Size": 25784 }, "lib/arm64-v8a/lib_System.Collections.Specialized.dll.so": { "Size": 23856 }, "lib/arm64-v8a/lib_System.ComponentModel.dll.so": { - "Size": 19608 + "Size": 19600 }, "lib/arm64-v8a/lib_System.ComponentModel.Primitives.dll.so": { - "Size": 21336 + "Size": 21328 }, "lib/arm64-v8a/lib_System.ComponentModel.TypeConverter.dll.so": { - "Size": 42440 + "Size": 42432 }, "lib/arm64-v8a/lib_System.Console.dll.so": { "Size": 24440 @@ -80,25 +80,25 @@ "Size": 24704 }, "lib/arm64-v8a/lib_System.dll.so": { - "Size": 19856 + "Size": 19864 }, "lib/arm64-v8a/lib_System.Drawing.dll.so": { - "Size": 19456 + "Size": 19448 }, "lib/arm64-v8a/lib_System.Drawing.Primitives.dll.so": { "Size": 30064 }, "lib/arm64-v8a/lib_System.Formats.Asn1.dll.so": { - "Size": 50312 + "Size": 50320 }, "lib/arm64-v8a/lib_System.IO.Compression.Brotli.dll.so": { - "Size": 29496 + "Size": 29504 }, "lib/arm64-v8a/lib_System.IO.Compression.dll.so": { "Size": 33800 }, "lib/arm64-v8a/lib_System.IO.IsolatedStorage.dll.so": { - "Size": 28336 + "Size": 28328 }, "lib/arm64-v8a/lib_System.Linq.dll.so": { "Size": 40696 @@ -107,7 +107,7 @@ "Size": 185864 }, "lib/arm64-v8a/lib_System.Net.Http.dll.so": { - "Size": 85904 + "Size": 85856 }, "lib/arm64-v8a/lib_System.Net.Primitives.dll.so": { "Size": 42184 @@ -116,13 +116,13 @@ "Size": 21568 }, "lib/arm64-v8a/lib_System.ObjectModel.dll.so": { - "Size": 27088 + "Size": 27096 }, "lib/arm64-v8a/lib_System.Private.CoreLib.dll.so": { - "Size": 967200 + "Size": 968480 }, "lib/arm64-v8a/lib_System.Private.DataContractSerialization.dll.so": { - "Size": 216496 + "Size": 216504 }, "lib/arm64-v8a/lib_System.Private.Uri.dll.so": { "Size": 62728 @@ -137,10 +137,10 @@ "Size": 20264 }, "lib/arm64-v8a/lib_System.Runtime.InteropServices.dll.so": { - "Size": 21488 + "Size": 21480 }, "lib/arm64-v8a/lib_System.Runtime.Numerics.dll.so": { - "Size": 55784 + "Size": 55840 }, "lib/arm64-v8a/lib_System.Runtime.Serialization.dll.so": { "Size": 19376 @@ -149,16 +149,16 @@ "Size": 20352 }, "lib/arm64-v8a/lib_System.Runtime.Serialization.Primitives.dll.so": { - "Size": 21472 + "Size": 21464 }, "lib/arm64-v8a/lib_System.Security.Cryptography.dll.so": { - "Size": 81288 + "Size": 81280 }, "lib/arm64-v8a/lib_System.Text.RegularExpressions.dll.so": { - "Size": 187056 + "Size": 187120 }, "lib/arm64-v8a/lib_System.Xml.dll.so": { - "Size": 19272 + "Size": 19264 }, "lib/arm64-v8a/lib_System.Xml.Linq.dll.so": { "Size": 19288 @@ -235,17 +235,14 @@ "lib/arm64-v8a/lib_Xamarin.Google.Android.Material.dll.so": { "Size": 84912 }, - "lib/arm64-v8a/libarc.bin.so": { - "Size": 18936 - }, "lib/arm64-v8a/libmono-component-marshal-ilgen.so": { - "Size": 36600 + "Size": 36616 }, "lib/arm64-v8a/libmonodroid.so": { - "Size": 1516584 + "Size": 1525968 }, "lib/arm64-v8a/libmonosgen-2.0.so": { - "Size": 3110944 + "Size": 3118632 }, "lib/arm64-v8a/libSystem.Globalization.Native.so": { "Size": 71952 @@ -254,13 +251,13 @@ "Size": 759304 }, "lib/arm64-v8a/libSystem.Native.so": { - "Size": 103520 + "Size": 104312 }, "lib/arm64-v8a/libSystem.Security.Cryptography.Native.Android.so": { - "Size": 165000 + "Size": 165240 }, "lib/arm64-v8a/libxamarin-app.so": { - "Size": 353048 + "Size": 357088 }, "META-INF/androidx.activity_activity.version": { "Size": 6 @@ -416,7 +413,7 @@ "Size": 1221 }, "META-INF/BNDLTOOL.SF": { - "Size": 98445 + "Size": 98346 }, "META-INF/com.android.tools/proguard/coroutines.pro": { "Size": 1345 @@ -443,7 +440,7 @@ "Size": 5 }, "META-INF/MANIFEST.MF": { - "Size": 98318 + "Size": 98219 }, "META-INF/maven/com.google.guava/listenablefuture/pom.properties": { "Size": 96 @@ -2483,5 +2480,5 @@ "Size": 812848 } }, - "PackageSize": 10955937 + "PackageSize": 10959960 } \ No newline at end of file From 9b79c81ab29fee034d07cf027d4fbf14b5279675 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Fri, 30 May 2025 14:13:44 +0200 Subject: [PATCH 60/60] Add a couple of tests --- .../PackagingTest.cs | 41 +++++++++++++++++++ .../Tests/InstallAndRunTests.cs | 21 ++++++++++ 2 files changed, 62 insertions(+) diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/PackagingTest.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/PackagingTest.cs index 23cca31ecbe..5931e9843e5 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/PackagingTest.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/PackagingTest.cs @@ -796,5 +796,46 @@ void CreateEmptyFile (string path) } } + [Test] + [TestCase (false)] + [TestCase (true)] + public void CheckEmbeddedAssemblyStorePackaging (bool useCLR) + { + var proj = new XamarinAndroidApplicationProject { + IsRelease = true + }; + + AndroidTargetArch[] supportedArches = new[] { + AndroidTargetArch.Arm64, + AndroidTargetArch.X86_64, + }; + + proj.SetRuntimeIdentifiers (supportedArches); + proj.SetProperty ("AndroidUseAssemblyStore", "true"); + proj.SetProperty ("_AndroidEmbedAssemblyStoreInRuntime", "true"); + proj.SetProperty ("UseMonoRuntime", useCLR ? "false" : "true"); + + using var b = CreateApkBuilder (); + Assert.IsTrue (b.Build (proj), "build should have succeeded."); + string apk = Path.Combine (Root, b.ProjectDirectory, proj.OutputPath, $"{proj.PackageName}-Signed.apk"); + + var knownAssemblyStoreFiles = new HashSet (StringComparer.Ordinal); + foreach (AndroidTargetArch arch in supportedArches) { + string archName = MonoAndroidHelper.ArchToAbi (arch); + knownAssemblyStoreFiles.Add ($"lib/{archName}/libassemblies.{archName}.blob.so"); + } + + var foundAssemblyStoreFiles = new HashSet (StringComparer.Ordinal); + using var zip = ZipHelper.OpenZip (apk); + + foreach (var entry in zip) { + if (knownAssemblyStoreFiles.Contains (entry.FullName)) { + foundAssemblyStoreFiles.Add (entry.FullName); + } + } + + Assert.IsFalse (foundAssemblyStoreFiles.Count != 0, $"APK should not contain any of the files: {FoundFiles ()}"); + string FoundFiles () => String.Join (", ", foundAssemblyStoreFiles); + } } } diff --git a/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs b/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs index d179740e994..92593ce63c1 100644 --- a/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs +++ b/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs @@ -1380,5 +1380,26 @@ public void AppStartsWithManagedMarshalMethodsLookupEnabled () Path.Combine (Root, builder.ProjectDirectory, "logcat.log"), 30); Assert.IsTrue (didLaunch, "Activity should have started."); } + + [Test] + [TestCase (false)] + [TestCase (true)] + public void AppStartsWithEmbeddedAssemblyStore (bool useCLR) + { + var proj = new XamarinAndroidApplicationProject { IsRelease = true }; + proj.SetProperty ("_AndroidEmbedAssemblyStoreInRuntime", "true"); + proj.SetProperty ("UseMonoRuntime", useCLR ? "false" : "true"); + + using var builder = CreateApkBuilder (); + builder.Save (proj); + + var dotnet = new DotNetCLI (Path.Combine (Root, builder.ProjectDirectory, proj.ProjectFilePath)); + Assert.IsTrue (dotnet.Build (), "`dotnet build` should succeed"); + Assert.IsTrue (dotnet.Run (), "`dotnet run --no-build` should succeed"); + + bool didLaunch = WaitForActivityToStart (proj.PackageName, "MainActivity", + Path.Combine (Root, builder.ProjectDirectory, "logcat.log"), 30); + Assert.IsTrue (didLaunch, "Activity should have started."); + } } } pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy