Skip to content
Draft
6 changes: 5 additions & 1 deletion build-tools/create-packs/Microsoft.Android.Runtime.proj
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ projects that use the Microsoft.Android.Runtimes framework in .NET 6+.
DependsOnTargets="_GetLicense;_GetDefaultPackageVersion"
BeforeTargets="GetFilesToPackage" >
<PropertyGroup>
<_RuntimeFlavorDirName Condition=" '$(AndroidRuntime)' == 'CoreCLR' ">$(_CLRRuntimeFlavorDirName)</_RuntimeFlavorDirName>
<_RuntimeFlavorDirName Condition=" '$(AndroidRuntime)' == 'CoreCLR' or '$(AndroidRuntime)' == 'NativeAOT' ">$(_CLRRuntimeFlavorDirName)</_RuntimeFlavorDirName>
<_RuntimeFlavorDirName Condition=" '$(AndroidRuntime)' == 'Mono' Or '$(AndroidRuntime)' == '' ">$(_MonoRuntimeFlavorDirName)</_RuntimeFlavorDirName>
<_ClangArch Condition=" '$(AndroidRID)' == 'android-arm64' ">aarch64</_ClangArch>
<_ClangArch Condition=" '$(AndroidRID)' == 'android-arm' ">arm</_ClangArch>
Expand Down Expand Up @@ -103,6 +103,10 @@ projects that use the Microsoft.Android.Runtimes framework in .NET 6+.

<ItemGroup Condition=" '$(AndroidRuntime)' == 'NativeAOT' ">
<_AndroidRuntimePackAssemblies Include="$(_MonoAndroidNETOutputRoot)$(AndroidLatestStableApiLevel)\Microsoft.Android.Runtime.NativeAOT.dll" />
<NativeRuntimeAsset Condition=" Exists('$(NativeRuntimeOutputRootDir)$(_RuntimeFlavorDirName)\$(AndroidRID)\libxa-shared-bits-debug.a') " Include="$(NativeRuntimeOutputRootDir)$(_RuntimeFlavorDirName)\$(AndroidRID)\libxa-shared-bits-debug.a" />
<NativeRuntimeAsset Condition=" Exists('$(NativeRuntimeOutputRootDir)$(_RuntimeFlavorDirName)\$(AndroidRID)\libxa-shared-bits-release.a') " Include="$(NativeRuntimeOutputRootDir)$(_RuntimeFlavorDirName)\$(AndroidRID)\libxa-shared-bits-release.a" />
<NativeRuntimeAsset Condition=" Exists('$(NativeRuntimeOutputRootDir)$(_RuntimeFlavorDirName)\$(AndroidRID)\libnet-android-nativeaot.debug.a') " Include="$(NativeRuntimeOutputRootDir)$(_RuntimeFlavorDirName)\$(AndroidRID)\libnet-android-nativeaot.debug.a" />
<NativeRuntimeAsset Condition=" Exists('$(NativeRuntimeOutputRootDir)$(_RuntimeFlavorDirName)\$(AndroidRID)\libnet-android-nativeaot.release.a') " Include="$(NativeRuntimeOutputRootDir)$(_RuntimeFlavorDirName)\$(AndroidRID)\libnet-android-nativeaot.release.a" />
</ItemGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,43 +14,6 @@ struct DiagnosticSettings {
public bool LogJniGlobalReferences;
private string? GrefPath;

private TextWriter? GrefLrefLog;


public TextWriter? GrefLog {
get {
if (!LogJniGlobalReferences) {
return null;
}
return ((LrefPath != null && LrefPath == GrefPath)
? GrefLrefLog ??= CreateWriter (LrefPath)
: null)
??
((GrefPath != null)
? CreateWriter (GrefPath)
: null)
??
new LogcatTextWriter (AndroidLogLevel.Debug, "NativeAot:GREF");
}
}

public TextWriter? LrefLog {
get {
if (!LogJniLocalReferences) {
return null;
}
return ((LrefPath != null && LrefPath == GrefPath)
? GrefLrefLog ??= CreateWriter (LrefPath)
: null)
??
((LrefPath != null)
? CreateWriter (LrefPath)
: null)
??
new LogcatTextWriter (AndroidLogLevel.Debug, "NativeAot:LREF");
}
}

TextWriter? CreateWriter (string path)
{
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ static int JNI_OnLoad (IntPtr vm, IntPtr reserved)
{
try {
AndroidLog.Print (AndroidLogLevel.Info, "JavaInteropRuntime", "JNI_OnLoad()");
LogcatTextWriter.Init ();
AndroidCryptoNative_InitLibraryOnLoad(vm, reserved);
return (int) JniVersion.v1_6;
}
catch (Exception e) {
Expand All @@ -22,6 +22,9 @@ static int JNI_OnLoad (IntPtr vm, IntPtr reserved)
}
}

[DllImport("*")]
static extern int AndroidCryptoNative_InitLibraryOnLoad (IntPtr vm, IntPtr reserved);

[UnmanagedCallersOnly (EntryPoint="JNI_OnUnload")]
static void JNI_OnUnload (IntPtr vm, IntPtr reserved)
{
Expand All @@ -38,15 +41,12 @@ static void init (IntPtr jnienv, IntPtr klass, IntPtr classLoader)
var settings = new DiagnosticSettings ();
settings.AddDebugDotnetLog ();

var typeManager = new ManagedTypeManager ();
var options = new NativeAotRuntimeOptions {
EnvironmentPointer = jnienv,
ClassLoader = new JniObjectReference (classLoader),
TypeManager = typeManager,
ValueManager = new SimpleValueManager (),
ClassLoader = new JniObjectReference (classLoader, JniObjectReferenceType.Global),
TypeManager = new ManagedTypeManager (),
ValueManager = ManagedValueManager.GetOrCreateInstance (),
UseMarshalMemberBuilder = false,
JniGlobalReferenceLogWriter = settings.GrefLog,
JniLocalReferenceLogWriter = settings.LrefLog,
};
runtime = options.CreateJreVM ();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,51 +8,6 @@

namespace Microsoft.Android.Runtime;

internal sealed class LogcatTextWriter : TextWriter {

public static void Init ()
{
// This method is a no-op, but it's necessary to ensure the static
// constructor is executed.
}

static LogcatTextWriter ()
{
Console.SetOut (new LogcatTextWriter (AndroidLogLevel.Info));
Console.SetError (new LogcatTextWriter (AndroidLogLevel.Error));
}

AndroidLogLevel Level;
string Tag;

internal LogcatTextWriter (AndroidLogLevel level, string tag = "NativeAotFromAndroid")
{
Level = level;
Tag = tag;
}

public override Encoding Encoding => Encoding.UTF8;
public override string NewLine => "\n";

public override void WriteLine (string? value)
{
if (value == null) {
AndroidLog.Print (Level, Tag, "");
return;
}
ReadOnlySpan<char> span = value;
while (!span.IsEmpty) {
if (span.IndexOf ('\n') is int n && n < 0) {
break;
}
var line = span.Slice (0, n);
AndroidLog.Print (Level, Tag, line.ToString ());
span = span.Slice (n + 1);
}
AndroidLog.Print (Level, Tag, span.ToString ());
}
}

static class AndroidLog {

[DllImport ("log", EntryPoint = "__android_log_print", CallingConvention = CallingConvention.Cdecl)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,6 @@ class NativeAotRuntimeOptions : JniRuntime.CreationOptions {

public bool IgnoreUnrecognizedOptions {get; set;}

public TextWriter? JniGlobalReferenceLogWriter {get; set;}
public TextWriter? JniLocalReferenceLogWriter {get; set;}

public NativeAotRuntimeOptions ()
{
JniVersion = JniVersion.v1_2;
Expand Down Expand Up @@ -61,8 +58,8 @@ static NativeAotRuntimeOptions CreateJreVM (NativeAotRuntimeOptions builder)
builder.TypeManager ??= new ManagedTypeManager ();
#endif // NET

builder.ValueManager ??= new SimpleValueManager ();
builder.ObjectReferenceManager ??= new ManagedObjectReferenceManager (builder.JniGlobalReferenceLogWriter, builder.JniLocalReferenceLogWriter);
builder.ValueManager ??= ManagedValueManager.GetOrCreateInstance();
builder.ObjectReferenceManager ??= new Android.Runtime.AndroidObjectReferenceManager ();

if (builder.InvocationPointer != IntPtr.Zero || builder.EnvironmentPointer != IntPtr.Zero)
return builder;
Expand Down
2 changes: 1 addition & 1 deletion src/Mono.Android/Android.Runtime/AndroidRuntime.cs
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ public AndroidRuntimeOptions (IntPtr jnienv,
}
}

class AndroidObjectReferenceManager : JniRuntime.JniObjectReferenceManager {
public class AndroidObjectReferenceManager : JniRuntime.JniObjectReferenceManager {
public override int GlobalReferenceCount {
get {return RuntimeNativeMethods._monodroid_gref_get ();}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ This file contains the NativeAOT-specific MSBuild logic for .NET for Android.
<AllowPublishAotWithoutRuntimeIdentifier Condition=" '$(AllowPublishAotWithoutRuntimeIdentifier)' == '' ">true</AllowPublishAotWithoutRuntimeIdentifier>
<!-- NativeAOT's targets currently gives an error about cross-compilation -->
<DisableUnsupportedError Condition=" $([MSBuild]::IsOSPlatform('windows')) and '$(DisableUnsupportedError)' == '' ">true</DisableUnsupportedError>
<!-- HACK: make dotnet restore include Microsoft.NETCore.App.Runtime.NativeAOT.linux-bionic-arm64 -->
<!-- HACK: make dotnet restore include Microsoft.NETCore.App.Runtime.NativeAOT.android-arm64 -->
<_IsPublishing Condition=" '$(_IsPublishing)' == '' ">true</_IsPublishing>
</PropertyGroup>

Expand Down Expand Up @@ -80,18 +80,6 @@ This file contains the NativeAOT-specific MSBuild logic for .NET for Android.
<SuppressTrimAnalysisWarnings>true</SuppressTrimAnalysisWarnings>
<!-- Ensure ILLink respects the value of SuppressTrimAnalysisWarnings -->
<_ExtraTrimmerArgs>$(_ExtraTrimmerArgs) --notrimwarn</_ExtraTrimmerArgs>

<!-- The list of hacks below should go away when we have NativeAOT.android-* packs -->
<!-- HACK: we are android-arm64, so this is required for the right path(s) to be found -->
<_OriginalRuntimeIdentifier>$(RuntimeIdentifier)</_OriginalRuntimeIdentifier>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are some usages of _OriginalRuntimeIdentifier below that need to be updated.

<RuntimeIdentifier Condition=" '$(RuntimeIdentifier)' == 'android-arm64' ">linux-bionic-arm64</RuntimeIdentifier>
<RuntimeIdentifier Condition=" '$(RuntimeIdentifier)' == 'android-x64' ">linux-bionic-x64</RuntimeIdentifier>
<!-- HACK: -targetos:android results in error, so use linux -->
<_targetOS>linux</_targetOS>
<!-- HACK: prevents libSystem.Net.Security.Native.a from being added -->
<_linuxLibcFlavor>bionic</_linuxLibcFlavor>
<!-- HACK: prevents: java.lang.UnsatisfiedLinkError: dlopen failed: cannot locate symbol "__start___modules" -->
<LinkerFlavor Condition=" '$(LinkerFlavor)' == '' ">lld</LinkerFlavor>
</PropertyGroup>

<SetNdkPathForIlc NdkBinDirectory="$(_NdkBinDir)" />
Expand Down Expand Up @@ -122,16 +110,13 @@ This file contains the NativeAOT-specific MSBuild logic for .NET for Android.
<ResolvedFileToPublish Include="$(_NdkSysrootDir)libc++_shared.so" RuntimeIdentifier="$(_OriginalRuntimeIdentifier)" />
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line and the one above need to use RuntimeIdentifier instead of _OriginalRuntimeIdentifier.

<!-- Satellite assemblies -->
<IlcSatelliteAssembly Include="$(_OuterIntermediateSatelliteAssembliesWithTargetPath)" />
<!-- Native support libraries -->
<NativeLibrary Include="@(RuntimePackAsset->WithMetadataValue('Filename', 'libnet-android-nativeaot.$(Configuration.ToLower())'))" />
<NativeLibrary Include="@(RuntimePackAsset->WithMetadataValue('Filename', 'libxa-shared-bits.$(Configuration.ToLower())'))" />
<DirectPInvoke Include="xa-internal-api" />
</ItemGroup>
</Target>

<Target Name="_AndroidAfterLinkNative" AfterTargets="LinkNative">
<PropertyGroup>
<!-- Turn $(RuntimeIdentifier) back to original value -->
<RuntimeIdentifier>$(_OriginalRuntimeIdentifier)</RuntimeIdentifier>
</PropertyGroup>
</Target>

<Target Name="_AndroidFixNativeLibraryFileName" AfterTargets="ComputeFilesToPublish">
<ItemGroup>
<!-- Fix paths to contain lib-prefix -->
Expand Down
25 changes: 24 additions & 1 deletion src/native/clr/host/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,18 @@ string(TOLOWER ${CMAKE_BUILD_TYPE} XAMARIN_NET_ANDROID_SUFFIX)
set(XAMARIN_NET_ANDROID_LIB "net-android${CHECKED_BUILD_INFIX}.${XAMARIN_NET_ANDROID_SUFFIX}")
set(XAMARIN_NET_ANDROID_STATIC_LIB "${XAMARIN_NET_ANDROID_LIB}-static")

set(XAMARIN_NET_ANDROID_NATIVEAOT_LIB "net-android-nativeaot${CHECKED_BUILD_INFIX}.${XAMARIN_NET_ANDROID_SUFFIX}")

set(XAMARIN_NET_ANDROID_NATIVEAOT_SOURCES
bridge-processing.cc
gc-bridge.cc
internal-pinvokes.cc
os-bridge.cc
runtime-util.cc
typemap.cc
xamarin_getifaddrs.cc
Copy link
Member

@filipnavara filipnavara Aug 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will produce conflict with #10385. Not a big deal, just wanted to avoid dragging unused code into newly supported runtimes.

)

set(XAMARIN_MONODROID_SOURCES
assembly-store.cc
bridge-processing.cc
Expand Down Expand Up @@ -71,6 +83,11 @@ if(BUILD_STATIC_LIBRARY)
)
endif()

add_library(${XAMARIN_NET_ANDROID_NATIVEAOT_LIB}
STATIC
${XAMARIN_NET_ANDROID_NATIVEAOT_SOURCES}
)

macro(lib_target_options TARGET_NAME)
target_compile_definitions(
${TARGET_NAME}
Expand Down Expand Up @@ -154,11 +171,13 @@ macro(lib_target_options TARGET_NAME)
xa::pinvoke-override-precompiled
xa::lz4
-llog
-lcoreclr
)
endmacro ()

lib_target_options(${XAMARIN_NET_ANDROID_LIB})
target_link_libraries(${XAMARIN_NET_ANDROID_LIB}
-lcoreclr
)
xa_add_compile_definitions(${XAMARIN_NET_ANDROID_LIB})
xa_add_include_directories(${XAMARIN_NET_ANDROID_LIB})

Expand All @@ -173,3 +192,7 @@ if(BUILD_STATIC_LIBRARY)
xa_add_compile_definitions(${XAMARIN_NET_ANDROID_STATIC_LIB})
xa_add_include_directories(${XAMARIN_NET_ANDROID_STATIC_LIB})
endif()

lib_target_options(${XAMARIN_NET_ANDROID_NATIVEAOT_LIB})
xa_add_compile_definitions(${XAMARIN_NET_ANDROID_NATIVEAOT_LIB})
xa_add_include_directories(${XAMARIN_NET_ANDROID_NATIVEAOT_LIB})
10 changes: 9 additions & 1 deletion src/native/native.targets
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,6 @@
AndroidRID="%(AndroidSupportedTargetJitAbi.AndroidRID)"
AndroidRuntime="$(CMakeRuntimeFlavor)"
RuntimePackName="$(_RuntimePackName)" />
<!-- NOTE: not building native libraries for NativeAOT yet -->
</ItemGroup>

<ItemGroup Condition=" '$(CMakeRuntimeFlavor)' == 'CoreCLR' ">
Expand All @@ -318,8 +317,17 @@
AndroidRID="%(AndroidSupportedTargetJitAbi.AndroidRID)"
AndroidRuntime="$(CMakeRuntimeFlavor)"
RuntimePackName="$(_RuntimePackName)" />
<_RuntimePackFiles Include="$(NativeRuntimeOutputRootDir)$(_RuntimeRedistDirName)\%(AndroidSupportedTargetJitAbi.AndroidRID)\*.o"
AndroidRID="%(AndroidSupportedTargetJitAbi.AndroidRID)"
AndroidRuntime="$(CMakeRuntimeFlavor)"
RuntimePackName="NativeAOT" />
<_RuntimePackFiles Include="$(NativeRuntimeOutputRootDir)$(_RuntimeRedistDirName)\%(AndroidSupportedTargetJitAbi.AndroidRID)\*.a"
AndroidRID="%(AndroidSupportedTargetJitAbi.AndroidRID)"
AndroidRuntime="$(CMakeRuntimeFlavor)"
RuntimePackName="NativeAOT" />
</ItemGroup>


<Copy
SourceFiles="%(_RuntimePackFiles.Identity)"
DestinationFolder="$(MicrosoftAndroidPacksRootDir)Microsoft.Android.Runtime.%(_RuntimePackFiles.RuntimePackName).$(AndroidApiLevel).%(_RuntimePackFiles.AndroidRID)\$(AndroidPackVersion)\runtimes\%(_RuntimePackFiles.AndroidRID)\native"
Expand Down
Loading