Skip to content

Commit

Permalink
Another set of changes from #9572
Browse files Browse the repository at this point in the history
  • Loading branch information
grendello committed Feb 20, 2025
1 parent d012fb8 commit 59cbd30
Show file tree
Hide file tree
Showing 34 changed files with 506 additions and 187 deletions.
8 changes: 5 additions & 3 deletions Configuration.props
Original file line number Diff line number Diff line change
Expand Up @@ -56,16 +56,18 @@
<MicrosoftAndroidSdkPackName Condition="$([MSBuild]::IsOSPlatform('osx'))">Microsoft.Android.Sdk.Darwin</MicrosoftAndroidSdkPackName>
</PropertyGroup>
<PropertyGroup>
<MicrosoftAndroidPacksRootDir>$(BuildOutputDirectory)lib\packs\</MicrosoftAndroidPacksRootDir>
<AutoProvision Condition=" '$(AutoProvision)' == '' ">False</AutoProvision>
<AutoProvisionUsesSudo Condition=" '$(AutoProvisionUsesSudo)' == '' ">False</AutoProvisionUsesSudo>
<_XABinRelativeInstallPrefix>lib\xamarin.android</_XABinRelativeInstallPrefix>
<XAInstallPrefix Condition=" '$(XAInstallPrefix)' == '' ">$(MSBuildThisFileDirectory)bin\$(Configuration)\$(_XABinRelativeInstallPrefix)\</XAInstallPrefix>
<_MonoAndroidNETOutputRoot>$(XAInstallPrefix)xbuild-frameworks\Microsoft.Android\</_MonoAndroidNETOutputRoot>
<_MonoAndroidNETDefaultOutDir>$(_MonoAndroidNETOutputRoot)$(AndroidApiLevel)\</_MonoAndroidNETDefaultOutDir>
<MicrosoftAndroidRefPackDir>$(BuildOutputDirectory)lib\packs\Microsoft.Android.Ref.$(AndroidApiLevel)\$(AndroidPackVersion)\ref\$(DotNetTargetFramework)\</MicrosoftAndroidRefPackDir>
<MicrosoftAndroidSdkPackDir>$(BuildOutputDirectory)lib\packs\$(MicrosoftAndroidSdkPackName)\$(AndroidPackVersion)\</MicrosoftAndroidSdkPackDir>
<NativeRuntimeOutputRootDir>$(BuildOutputDirectory)lib\runtimes\</NativeRuntimeOutputRootDir>
<MicrosoftAndroidRefPackDir>$(MicrosoftAndroidPacksRootDir)Microsoft.Android.Ref.$(AndroidApiLevel)\$(AndroidPackVersion)\ref\$(DotNetTargetFramework)\</MicrosoftAndroidRefPackDir>
<MicrosoftAndroidSdkPackDir>$(MicrosoftAndroidPacksRootDir)$(MicrosoftAndroidSdkPackName)\$(AndroidPackVersion)\</MicrosoftAndroidSdkPackDir>
<MicrosoftAndroidSdkOutDir>$(MicrosoftAndroidSdkPackDir)\tools\</MicrosoftAndroidSdkOutDir>
<MicrosoftAndroidSdkAnalysisOutDir>$(BuildOutputDirectory)lib\packs\Microsoft.Android.Ref.$(AndroidLatestStableApiLevel)\$(AndroidPackVersion)\analyzers\dotnet\cs\</MicrosoftAndroidSdkAnalysisOutDir>
<MicrosoftAndroidSdkAnalysisOutDir>$(MicrosoftAndroidPacksRootDir)Microsoft.Android.Ref.$(AndroidLatestStableApiLevel)\$(AndroidPackVersion)\analyzers\dotnet\cs\</MicrosoftAndroidSdkAnalysisOutDir>
<MakeConcurrency Condition=" '$(MakeConcurrency)' == '' And '$(HostCpuCount)' != '' ">-j$(HostCpuCount)</MakeConcurrency>
<ManagedRuntime Condition=" '$(ManagedRuntime)' == '' And '$(OS)' != 'Windows_NT' ">mono</ManagedRuntime>
<ManagedRuntimeArgs Condition=" '$(ManagedRuntimeArgs)' == '' And '$(ManagedRuntime)' == 'mono' ">--debug=casts</ManagedRuntimeArgs>
Expand Down
27 changes: 22 additions & 5 deletions build-tools/create-packs/Microsoft.Android.Runtime.proj
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ projects that use the Microsoft.Android framework in .NET 6+.
DependsOnTargets="_GetLicense">
<PropertyGroup>
<FrameworkListFile Condition="'$(FrameworkListFile)' == ''">$(IntermediateOutputPath)$(AndroidRID)\RuntimeList.xml</FrameworkListFile>
<_RuntimeFlavorDirName Condition=" '$(AndroidRuntime)' == 'CoreCLR' ">clr</_RuntimeFlavorDirName>
<_RuntimeFlavorDirName Condition=" '$(AndroidRuntime)' == 'Mono' Or '$(AndroidRuntime)' == '' ">mono</_RuntimeFlavorDirName>
</PropertyGroup>

<ItemGroup>
Expand All @@ -45,12 +47,27 @@ projects that use the Microsoft.Android framework in .NET 6+.
<_AndroidRuntimePackAssemblies Include="$(_MonoAndroidNETOutputRoot)$(AndroidLatestStableApiLevel)\Mono.Android.Export.dll" />
</ItemGroup>

<ItemGroup Condition=" '$(AndroidRuntime)' == 'CoreCLR' ">
<_AndroidRuntimePackAssets Condition=" Exists('$(NativeRuntimeOutputRootDir)$(_RuntimeFlavorDirName)\$(AndroidRID)\libnet-android.debug.so') " Include="$(NativeRuntimeOutputRootDir)$(_RuntimeFlavorDirName)\$(AndroidRID)\libnet-android.debug.so" />
<_AndroidRuntimePackAssets Condition=" Exists('$(NativeRuntimeOutputRootDir)$(_RuntimeFlavorDirName)\$(AndroidRID)\libnet-android.release.so') " Include="$(NativeRuntimeOutputRootDir)$(_RuntimeFlavorDirName)\$(AndroidRID)\libnet-android.release.so" />
</ItemGroup>

<ItemGroup Condition=" '$(AndroidRuntime)' == 'Mono' ">
<_AndroidRuntimePackAssets Include="$(MicrosoftAndroidSdkOutDir)lib\$(AndroidRID)\libmono-android.debug.so" />
<_AndroidRuntimePackAssets Include="$(MicrosoftAndroidSdkOutDir)lib\$(AndroidRID)\libmono-android.release.so" />
<_AndroidRuntimePackAssets Include="$(MicrosoftAndroidSdkOutDir)lib\$(AndroidRID)\libxamarin-debug-app-helper.so" />
<_AndroidRuntimePackAssets Include="$(MicrosoftAndroidSdkOutDir)lib\$(AndroidRID)\libxamarin-native-tracing.so" />
<_AndroidRuntimePackAssets Include="$(MicrosoftAndroidSdkOutDir)lib\$(AndroidRID)\libunwind_xamarin.a" />
<_AndroidRuntimePackAssets Include="$(NativeRuntimeOutputRootDir)$(_RuntimeFlavorDirName)\$(AndroidRID)\libmono-android.debug.so" />
<_AndroidRuntimePackAssets Include="$(NativeRuntimeOutputRootDir)$(_RuntimeFlavorDirName)\$(AndroidRID)\libmono-android.release.so" />
<_AndroidRuntimePackAssets Include="$(NativeRuntimeOutputRootDir)$(_RuntimeFlavorDirName)\$(AndroidRID)\libxamarin-debug-app-helper.so" />
<_AndroidRuntimePackAssets Include="$(NativeRuntimeOutputRootDir)$(_RuntimeFlavorDirName)\$(AndroidRID)\libxamarin-native-tracing.so" />
<_AndroidRuntimePackAssets Include="$(NativeRuntimeOutputRootDir)$(_RuntimeFlavorDirName)\$(AndroidRID)\libunwind_xamarin.a" />
</ItemGroup>

<ItemGroup Condition=" '$(AndroidRuntime)' != 'NativeAOT' ">
<!-- TODO: the Exists() checks must go away once we build CoreCLR host for all the targets -->
<_AndroidRuntimePackAssets Condition=" Exists('$(NativeRuntimeOutputRootDir)$(_RuntimeFlavorDirName)\$(AndroidRID)\libc.so') " Include="$(NativeRuntimeOutputRootDir)$(_RuntimeFlavorDirName)\$(AndroidRID)\libc.so" />
<_AndroidRuntimePackAssets Condition=" Exists('$(NativeRuntimeOutputRootDir)$(_RuntimeFlavorDirName)\$(AndroidRID)\libdl.so') " Include="$(NativeRuntimeOutputRootDir)$(_RuntimeFlavorDirName)\$(AndroidRID)\libdl.so" />
<_AndroidRuntimePackAssets Condition=" Exists('$(NativeRuntimeOutputRootDir)$(_RuntimeFlavorDirName)\$(AndroidRID)\liblog.so') " Include="$(NativeRuntimeOutputRootDir)$(_RuntimeFlavorDirName)\$(AndroidRID)\liblog.so" />
<_AndroidRuntimePackAssets Condition=" Exists('$(NativeRuntimeOutputRootDir)$(_RuntimeFlavorDirName)\$(AndroidRID)\libm.so') " Include="$(NativeRuntimeOutputRootDir)$(_RuntimeFlavorDirName)\$(AndroidRID)\libm.so" />
<_AndroidRuntimePackAssets Condition=" Exists('$(NativeRuntimeOutputRootDir)$(_RuntimeFlavorDirName)\$(AndroidRID)\libz.so') " Include="$(NativeRuntimeOutputRootDir)$(_RuntimeFlavorDirName)\$(AndroidRID)\libz.so" />
<_AndroidRuntimePackAssets Condition=" Exists('$(NativeRuntimeOutputRootDir)$(_RuntimeFlavorDirName)\$(AndroidRID)\libarchive-dso-stub.so') " Include="$(NativeRuntimeOutputRootDir)$(_RuntimeFlavorDirName)\$(AndroidRID)\libarchive-dso-stub.so" />
</ItemGroup>

<ItemGroup>
Expand Down
32 changes: 32 additions & 0 deletions src/Mono.Android/Android.Runtime/DotNetRuntimeType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using System;

namespace Android.Runtime;

enum DotNetRuntimeType
{
Unknown,
MonoVM,
CoreCLR,
NativeAOT,
}

// This looks weird, see comments in RuntimeTypeInternal.cs
class DotNetRuntimeTypeConverter
{
// Values for the JnienvInitializeArgs.runtimeType field
//
// NOTE: Keep this in sync with managed side in src/native/common/include/managed-interface.hh
const uint RuntimeTypeMonoVM = 0x0001;
const uint RuntimeTypeCoreCLR = 0x0002;
const uint RuntimeTypeNativeAOT = 0x0004;

public static DotNetRuntimeType Convert (uint runtimeType)
{
return runtimeType switch {
RuntimeTypeMonoVM => DotNetRuntimeType.MonoVM,
RuntimeTypeCoreCLR => DotNetRuntimeType.CoreCLR,
RuntimeTypeNativeAOT => DotNetRuntimeType.NativeAOT,
_ => throw new NotSupportedException ($"Internal error: unsupported runtime type {runtimeType:x}")
};
}
}
7 changes: 6 additions & 1 deletion src/Mono.Android/Android.Runtime/JNIEnvInit.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ namespace Android.Runtime
static internal class JNIEnvInit
{
#pragma warning disable 0649
// NOTE: Keep this in sync with the native side in src/native/monodroid/monodroid-glue-internal.hh
// NOTE: Keep this in sync with the native side in src/native/common/include/managed-interface.hh
internal struct JnienvInitializeArgs {
public IntPtr javaVm;
public IntPtr env;
Expand All @@ -32,6 +32,7 @@ internal struct JnienvInitializeArgs {
public bool jniRemappingInUse;
public bool marshalMethodsEnabled;
public IntPtr grefGCUserPeerable;
public uint runtimeType;
}
#pragma warning restore 0649

Expand All @@ -48,6 +49,8 @@ internal struct JnienvInitializeArgs {

internal static JniRuntime? androidRuntime;

public static DotNetRuntimeType RuntimeType { get; private set; } = DotNetRuntimeType.Unknown;

[UnmanagedCallersOnly]
static unsafe void RegisterJniNatives (IntPtr typeName_ptr, int typeName_len, IntPtr jniClass, IntPtr methods_ptr, int methods_len)
{
Expand Down Expand Up @@ -87,6 +90,8 @@ internal static void InitializeJniRuntime (JniRuntime runtime)
[UnmanagedCallersOnly]
internal static unsafe void Initialize (JnienvInitializeArgs* args)
{
RuntimeType = DotNetRuntimeTypeConverter.Convert (args->runtimeType);

IntPtr total_timing_sequence = IntPtr.Zero;
IntPtr partial_timing_sequence = IntPtr.Zero;

Expand Down
1 change: 1 addition & 0 deletions src/Mono.Android/Mono.Android.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,7 @@
<Compile Include="Android.Runtime\BoundExceptionType.cs" />
<Compile Include="Android.Runtime\CharSequence.cs" />
<Compile Include="Android.Runtime\CPUArchitecture.cs" />
<Compile Include="Android.Runtime\DotNetRuntimeType.cs" />
<Compile Include="Android.Runtime\Extensions.cs" />
<Compile Include="Android.Runtime\GeneratedEnumAttribute.cs" />
<Compile Include="Android.Runtime\IJavaObject.cs" />
Expand Down
2 changes: 1 addition & 1 deletion src/Xamarin.Android.Build.Tasks/Tasks/GenerateJavaStubs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -480,7 +480,7 @@ void SaveResource (string resource, string filename, string destDir, Func<string
void WriteTypeMappings (NativeCodeGenState state)
{
Log.LogDebugMessage ($"Generating type maps for architecture '{state.TargetArch}'");
var tmg = new TypeMapGenerator (Log, state);
var tmg = new TypeMapGenerator (Log, state, androidRuntime);
if (!tmg.Generate (Debug, SkipJniAddNativeMethodRegistrationAttributeScan, TypemapOutputDirectory, GenerateNativeAssembly)) {
throw new XamarinAndroidException (4308, Properties.Resources.XA4308);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@ public override string GetComment (object data, string fieldName)
}
}

// Disable "Field 'X' is never assigned to, and will always have its default value Y"
// Classes below are used in native code generation, thus all the fields must be present
// but they aren't always assigned values (which is fine).
#pragma warning disable CS0649

// Order of fields and their type must correspond *exactly* (with exception of the
// ignored managed members) to that in
// src/monodroid/jni/xamarin-app.hh DSOCacheEntry structure
Expand Down Expand Up @@ -147,6 +152,7 @@ sealed class XamarinAndroidBundledAssembly
[NativeAssembler (UsesDataProvider = true), NativePointer (PointsToPreAllocatedBuffer = true)]
public string name;
}
#pragma warning restore CS0649

// Keep in sync with FORMAT_TAG in src/monodroid/jni/xamarin-app.hh
const ulong FORMAT_TAG = 0x00025E6972616D58; // 'Xmari^XY' where XY is the format version
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -781,6 +781,9 @@ void WriteStructureValue (GeneratorWriteContext context, StructureInstance? inst

for (int i = 0; i < info.Members.Count; i++) {
StructureMemberInfo smi = info.Members[i];
if (!smi.IsSupportedForTarget (context.Target)) {
continue;
}

context.Output.Write (context.CurrentIndent);
WriteType (context, instance, smi, out _);
Expand Down Expand Up @@ -810,7 +813,7 @@ void WriteStructureValue (GeneratorWriteContext context, StructureInstance? inst
var sb = new StringBuilder (" ");
sb.Append (MapManagedTypeToNative (context, smi));
sb.Append (' ');
sb.Append (smi.Info.Name);
sb.Append (smi.MappedName);
comment = sb.ToString ();
}
WriteCommentLine (context, comment);
Expand Down Expand Up @@ -848,6 +851,7 @@ void WriteArrayEntries (GeneratorWriteContext context, LlvmIrVariable variable,
bool ignoreComments = stride > 1;
string? prevItemComment = null;
ulong counter = 0;
bool writeStringInComment = !ignoreComments && (elementType == typeof(string) || elementType == typeof(StringHolder));

if (entries != null) {
foreach (object entry in entries) {
Expand All @@ -871,7 +875,13 @@ void WriteArrayEntries (GeneratorWriteContext context, LlvmIrVariable variable,
}

if (writeIndices && String.IsNullOrEmpty (prevItemComment)) {
prevItemComment = $" {counter}";
string stringComment = String.Empty;
if (writeStringInComment) {
var holder = StringHolder.AsHolder (entry);
stringComment = $" ('{holder.Data}')";
}

prevItemComment = $" {counter}{stringComment}";
}
}

Expand Down Expand Up @@ -1098,6 +1108,10 @@ void WriteStructureDeclaration (GeneratorWriteContext context, StructureInfo si)
context.IncreaseIndent ();
for (int i = 0; i < si.Members.Count; i++) {
StructureMemberInfo info = si.Members[i];
if (!info.IsSupportedForTarget (context.Target)) {
continue;
}

string nativeType = MapManagedTypeToNative (info.MemberType);

// TODO: nativeType can be an array, update to indicate that (and get the size)
Expand All @@ -1108,7 +1122,7 @@ void WriteStructureDeclaration (GeneratorWriteContext context, StructureInfo si)
arraySize = String.Empty;
}

var comment = $" {nativeType} {info.Info.Name}{arraySize}";
var comment = $" {nativeType} {info.MappedName}{arraySize}";
WriteStructureDeclarationField (info.IRType, comment, i == si.Members.Count - 1);
}
context.DecreaseIndent ();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,18 @@ public static LlvmIrStringEncoding GetStringEncoding (this MemberInfo mi, LlvmIr
return attr.IsUTF16 ? LlvmIrStringEncoding.Unicode : DefaultStringEncoding;
}

public static string? GetOverriddenName (this MemberInfo mi, LlvmIrTypeCache cache)
{
var attr = cache.GetNativeAssemblerAttribute (mi);
return attr != null ? attr.MemberName : null;
}

public static NativeAssemblerValidTarget GetValidTarget (this MemberInfo mi, LlvmIrTypeCache cache)
{
var attr = cache.GetNativeAssemblerAttribute (mi);
return attr != null ? attr.ValidTarget : NativeAssemblerValidTarget.Any;
}

public static bool ShouldBeIgnored (this MemberInfo mi, LlvmIrTypeCache cache)
{
var attr = cache.GetNativeAssemblerAttribute (mi);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@

namespace Xamarin.Android.Tasks
{
enum NativeAssemblerValidTarget
{
Any,
ThirtyTwoBit,
SixtyFourBit,
}

[AttributeUsage (AttributeTargets.Field | AttributeTargets.Property, Inherited = true)]
class NativeAssemblerAttribute : Attribute
{
Expand Down Expand Up @@ -41,6 +48,22 @@ class NativeAssemblerAttribute : Attribute
/// the native assembly file.
/// </summary>
public bool IsUTF16 { get; set; }

/// <summary>
/// Allows choosing that a structure/class field/property will be considered only for the target of
/// specific bitness. Mainly useful when dealing with hash fields.
/// </summary>
public NativeAssemblerValidTarget ValidTarget { get; set; } = NativeAssemblerValidTarget.Any;

/// <summary>
/// Allows overriding of the field name when mapping the structure. This is purely cosmetic, but allows to avoid
/// confusion when dealing with fields/properties that have a different size for 32-bit and 64-bit targets. In such
/// case the structure being mapped will have a separate member per bitness, with the members requiring different names
/// while in reality they have the same name in the native world, regardless of bitness.
///
/// This field is only considered only when <see cref="ValidTarget" /> is not set to <see cref="NativeAssemblerValidTarget.Any"/>
/// </summary>
public string? MemberName { get; set; }
}

[AttributeUsage (AttributeTargets.Class, Inherited = true)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,25 @@ sealed class StructureMemberInfo
public bool IsInlineArray { get; }
public bool NeedsPadding { get; }

/// <summary>
/// Some fields/properties may override their name for presentation purposes, <see cref="NativeAssemblerAttribute.MemberName" />.
/// In such instances, this property will return the overridden/mapped name, otherwise it returns <see cref="Info.Name"/>.
/// This property should be used only for "presentation" purposes - for instance when generating comments which refer to
/// native field names.
/// </summary>
public string MappedName {
get {
string? name = Info.GetOverriddenName (typeCache);
return String.IsNullOrEmpty (name) ? Info.Name : name;
}
}

readonly LlvmIrTypeCache typeCache;

public StructureMemberInfo (MemberInfo mi, LlvmIrModule module, LlvmIrTypeCache cache)
{
Info = mi;
typeCache = cache;

MemberType = mi switch {
FieldInfo fi => fi.FieldType,
Expand Down Expand Up @@ -97,6 +113,17 @@ public StructureMemberInfo (MemberInfo mi, LlvmIrModule module, LlvmIrTypeCache
}
}

public bool IsSupportedForTarget (LlvmIrModuleTarget target)
{
NativeAssemblerValidTarget validTarget = Info.GetValidTarget (typeCache);
return validTarget switch {
NativeAssemblerValidTarget.Any => true,
NativeAssemblerValidTarget.ThirtyTwoBit => !target.Is64Bit,
NativeAssemblerValidTarget.SixtyFourBit => target.Is64Bit,
_ => throw new NotSupportedException ($"Internal error: unsupported native assembler valid target value: {validTarget}")
};
}

public object? GetValue (object instance)
{
if (Info is FieldInfo fi) {
Expand Down
13 changes: 6 additions & 7 deletions src/Xamarin.Android.Build.Tasks/Utilities/ManifestDocument.cs
Original file line number Diff line number Diff line change
Expand Up @@ -673,14 +673,13 @@ XElement CreateApplicationElement (XElement manifest, string applicationClass, L

IList<string> AddMonoRuntimeProviders (XElement app)
{
if (AndroidRuntime == AndroidRuntime.CoreCLR) {
//TODO: implement provider logic for CoreCLR
return [];
}
(string packageName, string className) = AndroidRuntime switch {
AndroidRuntime.MonoVM => ("mono", "MonoRuntimeProvider"),
AndroidRuntime.CoreCLR => ("mono", "MonoRuntimeProvider"),
AndroidRuntime.NativeAOT => ("net.dot.jni.nativeaot", "NativeAotRuntimeProvider"),
_ => throw new NotSupportedException ($"Internal error: unsupported runtime type: {AndroidRuntime}")
};

bool isMonoVM = AndroidRuntime == AndroidRuntime.MonoVM;
string packageName = isMonoVM ? "mono" : "net.dot.jni.nativeaot";
string className = isMonoVM ? "MonoRuntimeProvider" : "NativeAotRuntimeProvider";
app.Add (CreateMonoRuntimeProvider ($"{packageName}.{className}", null, --AppInitOrder));

var providerNames = new List<string> ();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ public static string ArchToAbi (AndroidTargetArch arch)
}

public static bool IsValidAbi (string abi) => AbiToRidMap.ContainsKey (abi);
public static bool IsValidRID (string rid) => RidToAbiMap.ContainsKey (rid);

public static string? CultureInvariantToString (object? obj)
{
Expand Down Expand Up @@ -228,6 +229,7 @@ public static ulong GetMangledAssemblyNameSizeOverhead ()
}

public static byte[] Utf8StringToBytes (string str) => Encoding.UTF8.GetBytes (str);
public static byte[] Utf16StringToBytes (string str) => Encoding.Unicode.GetBytes (str);

public static ulong GetXxHash (string str, bool is64Bit) => GetXxHash (Utf8StringToBytes (str), is64Bit);

Expand Down
Loading

0 comments on commit 59cbd30

Please sign in to comment.