From f2285a8f14db3c5c3a03b53b18e5fef4280d491e Mon Sep 17 00:00:00 2001 From: Maxim Lipnin Date: Tue, 19 Jan 2021 18:33:41 +0300 Subject: [PATCH 01/18] Add android AOT functional test --- eng/testing/tests.mobile.targets | 24 +++++++++++++++---- .../AOT/Android.Emulator.Aot.Test.csproj | 16 +++++++++++++ .../Android/Emulator/AOT/Program.cs | 13 ++++++++++ .../Android/Emulator/AOT/README.md | 1 - 4 files changed, 49 insertions(+), 5 deletions(-) create mode 100644 src/tests/FunctionalTests/Android/Emulator/AOT/Android.Emulator.Aot.Test.csproj create mode 100644 src/tests/FunctionalTests/Android/Emulator/AOT/Program.cs delete mode 100644 src/tests/FunctionalTests/Android/Emulator/AOT/README.md diff --git a/eng/testing/tests.mobile.targets b/eng/testing/tests.mobile.targets index b4e7fb22dfa962..132e79501cdc9b 100644 --- a/eng/testing/tests.mobile.targets +++ b/eng/testing/tests.mobile.targets @@ -25,6 +25,9 @@ true + + + AndroidTestRunner.dll + + + @(MonoAOTCompilerDefaultAotArguments, ';') + @(MonoAOTCompilerDefaultProcessArguments, ';') + + + + + + + - - - - diff --git a/src/tests/FunctionalTests/Android/Emulator/AOT/Android.Emulator.Aot.Test.csproj b/src/tests/FunctionalTests/Android/Emulator/AOT/Android.Emulator.Aot.Test.csproj new file mode 100644 index 00000000000000..48e4324d195b11 --- /dev/null +++ b/src/tests/FunctionalTests/Android/Emulator/AOT/Android.Emulator.Aot.Test.csproj @@ -0,0 +1,16 @@ + + + Exe + false + true + true + $(NetCoreAppCurrent) + Android.Emulator.Aot.Test.dll + 42 + true + + + + + + diff --git a/src/tests/FunctionalTests/Android/Emulator/AOT/Program.cs b/src/tests/FunctionalTests/Android/Emulator/AOT/Program.cs new file mode 100644 index 00000000000000..7dcc0f375db878 --- /dev/null +++ b/src/tests/FunctionalTests/Android/Emulator/AOT/Program.cs @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; + +public static class Program +{ + public static int Main(string[] args) + { + Console.WriteLine("Hello, Android!"); // logcat + return 42; + } +} diff --git a/src/tests/FunctionalTests/Android/Emulator/AOT/README.md b/src/tests/FunctionalTests/Android/Emulator/AOT/README.md deleted file mode 100644 index 55f50108e401f3..00000000000000 --- a/src/tests/FunctionalTests/Android/Emulator/AOT/README.md +++ /dev/null @@ -1 +0,0 @@ -TO-DO: add the test case for AOT mode when https://github.com/dotnet/runtime/pull/43535 has been completed. \ No newline at end of file From 8942a40dfa038216bd0c4421eeae71e9ba483eb7 Mon Sep 17 00:00:00 2001 From: Maxim Lipnin Date: Mon, 25 Jan 2021 12:21:38 +0300 Subject: [PATCH 02/18] Update Android app builder --- eng/testing/tests.mobile.targets | 4 +- .../AndroidAppBuilder/AndroidAppBuilder.cs | 24 ++++++- src/tasks/AndroidAppBuilder/ApkBuilder.cs | 64 +++++++++++-------- 3 files changed, 62 insertions(+), 30 deletions(-) diff --git a/eng/testing/tests.mobile.targets b/eng/testing/tests.mobile.targets index 132e79501cdc9b..a8da6a3f0ae168 100644 --- a/eng/testing/tests.mobile.targets +++ b/eng/testing/tests.mobile.targets @@ -77,11 +77,13 @@ RuntimeIdentifier="$(RuntimeIdentifier)" ProjectName="$(AssemblyName)" MonoRuntimeHeaders="$(MicrosoftNetCoreAppRuntimePackNativeDir)include\mono-2.0" + Assemblies="@(BundleAssemblies)" MainLibraryFileName="$(MainLibraryFileName)" + ForceAOT="$(RunAOTCompilation)" ForceInterpreter="$(MonoForceInterpreter)" StripDebugSymbols="False" OutputDir="$(BundleDir)" - SourceDir="$(PublishDir)"> + AppDir="$(PublishDir)"> diff --git a/src/tasks/AndroidAppBuilder/AndroidAppBuilder.cs b/src/tasks/AndroidAppBuilder/AndroidAppBuilder.cs index f9c88cb5a1d957..86cb7f1fe374a9 100644 --- a/src/tasks/AndroidAppBuilder/AndroidAppBuilder.cs +++ b/src/tasks/AndroidAppBuilder/AndroidAppBuilder.cs @@ -10,22 +10,38 @@ public class AndroidAppBuilderTask : Task { [Required] - public string SourceDir { get; set; } = ""!; + public string MonoRuntimeHeaders { get; set; } = ""!; + /// + /// Target directory with *dll and other content to be AOT'd and/or bundled + /// [Required] - public string MonoRuntimeHeaders { get; set; } = ""!; + public string AppDir { get; set; } = ""!; /// /// This library will be used as an entry-point (e.g. TestRunner.dll) /// + [Required] public string MainLibraryFileName { get; set; } = ""!; + /// + /// List of paths to assemblies to be included in the app. For AOT builds the 'ObjectFile' metadata key needs to point to the object file. + /// + [Required] + public ITaskItem[] Assemblies { get; set; } = Array.Empty(); + + /// + /// Prefer FullAOT mode for Emulator over JIT + /// + public bool ForceAOT { get; set; } + [Required] public string RuntimeIdentifier { get; set; } = ""!; [Required] public string OutputDir { get; set; } = ""!; + [Required] public string? ProjectName { get; set; } public string? AndroidSdk { get; set; } @@ -64,6 +80,7 @@ public override bool Execute() var apkBuilder = new ApkBuilder(); apkBuilder.ProjectName = ProjectName; + apkBuilder.AppDir = AppDir; apkBuilder.OutputDir = OutputDir; apkBuilder.AndroidSdk = AndroidSdk; apkBuilder.AndroidNdk = AndroidNdk; @@ -74,7 +91,8 @@ public override bool Execute() apkBuilder.NativeMainSource = NativeMainSource; apkBuilder.KeyStorePath = KeyStorePath; apkBuilder.ForceInterpreter = ForceInterpreter; - (ApkBundlePath, ApkPackageId) = apkBuilder.BuildApk(SourceDir, abi, MainLibraryFileName, MonoRuntimeHeaders); + apkBuilder.ForceAOT = ForceAOT; + (ApkBundlePath, ApkPackageId) = apkBuilder.BuildApk(Assemblies, abi, MainLibraryFileName, MonoRuntimeHeaders); return true; } diff --git a/src/tasks/AndroidAppBuilder/ApkBuilder.cs b/src/tasks/AndroidAppBuilder/ApkBuilder.cs index 71a83cf2a65b59..6b6acfa1e2d3dd 100644 --- a/src/tasks/AndroidAppBuilder/ApkBuilder.cs +++ b/src/tasks/AndroidAppBuilder/ApkBuilder.cs @@ -5,12 +5,14 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using Microsoft.Build.Framework; public class ApkBuilder { private const string DefaultMinApiLevel = "21"; public string? ProjectName { get; set; } + public string? AppDir { get; set; } public string? AndroidNdk { get; set; } public string? AndroidSdk { get; set; } public string? MinApiLevel { get; set; } @@ -21,49 +23,57 @@ public class ApkBuilder public string? NativeMainSource { get; set; } public string? KeyStorePath { get; set; } public bool ForceInterpreter { get; set; } + public bool ForceAOT { get; set; } public (string apk, string packageId) BuildApk( - string sourceDir, + ITaskItem[] assemblies, string abi, - string entryPointLib, + string mainLibraryFileName, string monoRuntimeHeaders) { - if (!Directory.Exists(sourceDir)) - throw new ArgumentException($"sourceDir='{sourceDir}' is empty or doesn't exist"); - - if (string.IsNullOrEmpty(abi)) - throw new ArgumentException("abi shoudln't be empty (e.g. x86, x86_64, armeabi-v7a or arm64-v8a"); + if (string.IsNullOrEmpty(AppDir) || !Directory.Exists(AppDir)) + { + throw new ArgumentException($"AppDir='{AppDir}' is empty or doesn't exist"); + } - string entryPointLibPath = ""; - if (!string.IsNullOrEmpty(entryPointLib)) + if (!File.Exists(Path.Combine(AppDir, mainLibraryFileName))) { - entryPointLibPath = Path.Combine(sourceDir, entryPointLib); - if (!File.Exists(entryPointLibPath)) - throw new ArgumentException($"{entryPointLib} was not found in sourceDir='{sourceDir}'"); + throw new ArgumentException($"MainLibraryFileName='{mainLibraryFileName}' was not found in AppDir='{AppDir}'"); } - if (string.IsNullOrEmpty(ProjectName)) + if (string.IsNullOrEmpty(abi)) { - if (string.IsNullOrEmpty(entryPointLib)) - throw new ArgumentException("ProjectName needs to be set if entryPointLib is empty."); - else - ProjectName = Path.GetFileNameWithoutExtension(entryPointLib); + throw new ArgumentException("abi should not be empty (e.g. x86, x86_64, armeabi-v7a or arm64-v8a"); } - if (ProjectName.Contains(' ')) - throw new ArgumentException($"ProjectName='{ProjectName}' shouldn't not contain spaces."); + if (!string.IsNullOrEmpty(ProjectName) && ProjectName.Contains(' ')) + { + throw new ArgumentException($"ProjectName='{ProjectName}' should not not contain spaces."); + } - if (string.IsNullOrEmpty(AndroidSdk)) + if (string.IsNullOrEmpty(AndroidSdk)){ AndroidSdk = Environment.GetEnvironmentVariable("ANDROID_SDK_ROOT"); + } if (string.IsNullOrEmpty(AndroidNdk)) + { AndroidNdk = Environment.GetEnvironmentVariable("ANDROID_NDK_ROOT"); + } if (string.IsNullOrEmpty(AndroidSdk) || !Directory.Exists(AndroidSdk)) + { throw new ArgumentException($"Android SDK='{AndroidSdk}' was not found or empty (can be set via ANDROID_SDK_ROOT envvar)."); + } if (string.IsNullOrEmpty(AndroidNdk) || !Directory.Exists(AndroidNdk)) + { throw new ArgumentException($"Android NDK='{AndroidNdk}' was not found or empty (can be set via ANDROID_NDK_ROOT envvar)."); + } + + if (ForceInterpreter && ForceAOT) + { + throw new InvalidOperationException("Interpreter and AOT cannot be enabled at the same time"); + } // Try to get the latest build-tools version if not specified if (string.IsNullOrEmpty(BuildToolsVersion)) @@ -88,7 +98,9 @@ public class ApkBuilder string buildToolsFolder = Path.Combine(AndroidSdk, "build-tools", BuildToolsVersion); if (!Directory.Exists(buildToolsFolder)) + { throw new ArgumentException($"{buildToolsFolder} was not found."); + } Directory.CreateDirectory(OutputDir); Directory.CreateDirectory(Path.Combine(OutputDir, "bin")); @@ -105,7 +117,7 @@ public class ApkBuilder // Copy sourceDir to OutputDir/assets-tozip (ignore native files) // these files then will be zipped and copied to apk/assets/assets.zip - Utils.DirectoryCopy(sourceDir, Path.Combine(OutputDir, "assets-tozip"), file => + Utils.DirectoryCopy(AppDir, Path.Combine(OutputDir, "assets-tozip"), file => { string fileName = Path.GetFileName(file); string extension = Path.GetExtension(file); @@ -143,9 +155,9 @@ public class ApkBuilder // 1. Build libmonodroid.so` via cmake - string monoRuntimeLib = Path.Combine(sourceDir, "libmonosgen-2.0.a"); + string monoRuntimeLib = Path.Combine(AppDir, "libmonosgen-2.0.a"); if (!File.Exists(monoRuntimeLib)) - throw new ArgumentException($"libmonosgen-2.0.a was not found in {sourceDir}"); + throw new ArgumentException($"libmonosgen-2.0.a was not found in {AppDir}"); string cmakeLists = Utils.GetEmbeddedResource("CMakeLists-android.txt") .Replace("%MonoInclude%", monoRuntimeHeaders) @@ -186,12 +198,12 @@ public class ApkBuilder File.WriteAllText(javaActivityPath, Utils.GetEmbeddedResource("MainActivity.java") - .Replace("%EntryPointLibName%", Path.GetFileName(entryPointLib))); + .Replace("%EntryPointLibName%", Path.GetFileName(mainLibraryFileName))); if (!string.IsNullOrEmpty(NativeMainSource)) File.Copy(NativeMainSource, javaActivityPath, true); string monoRunner = Utils.GetEmbeddedResource("MonoRunner.java") - .Replace("%EntryPointLibName%", Path.GetFileName(entryPointLib)) + .Replace("%EntryPointLibName%", Path.GetFileName(mainLibraryFileName)) .Replace("%ForceInterpreter%", ForceInterpreter.ToString().ToLower()); File.WriteAllText(monoRunnerPath, monoRunner); @@ -213,7 +225,7 @@ public class ApkBuilder var dynamicLibs = new List(); dynamicLibs.Add(Path.Combine(OutputDir, "monodroid", "libmonodroid.so")); - dynamicLibs.AddRange(Directory.GetFiles(sourceDir, "*.so").Where(file => Path.GetFileName(file) != "libmonodroid.so")); + dynamicLibs.AddRange(Directory.GetFiles(AppDir, "*.so").Where(file => Path.GetFileName(file) != "libmonodroid.so")); // add all *.so files to lib/%abi%/ Directory.CreateDirectory(Path.Combine(OutputDir, "lib", abi)); From 8b01816fe9d6299b0e52c834c16e95a87338cf17 Mon Sep 17 00:00:00 2001 From: Maxim Lipnin Date: Thu, 28 Jan 2021 15:57:46 +0300 Subject: [PATCH 03/18] output dir --- eng/testing/tests.mobile.targets | 9 ++++++++- src/mono/sample/Android/AndroidSampleApp.csproj | 12 ++++++++++-- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/eng/testing/tests.mobile.targets b/eng/testing/tests.mobile.targets index a8da6a3f0ae168..39e6af341f41d6 100644 --- a/eng/testing/tests.mobile.targets +++ b/eng/testing/tests.mobile.targets @@ -28,6 +28,10 @@ + + <_MobileIntermediateOutputPath>$(IntermediateOutputPath)mobile + + - + + + + + <_MobileIntermediateOutputPath>$(IntermediateOutputPath)mobile + @@ -39,6 +43,8 @@ + @@ -62,6 +68,7 @@ + OutputDir="$(ApkDir)" + AppDir="$(PublishDir)"> From 356f071514ba47af0a33bc9bc440b5f0abfdcf80 Mon Sep 17 00:00:00 2001 From: Maxim Lipnin Date: Mon, 1 Feb 2021 17:03:06 +0300 Subject: [PATCH 04/18] Update template --- src/tasks/AndroidAppBuilder/ApkBuilder.cs | 3 ++- src/tasks/AndroidAppBuilder/Templates/MonoRunner.java | 5 +++-- src/tasks/AndroidAppBuilder/Templates/monodroid.c | 10 +++++++++- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/tasks/AndroidAppBuilder/ApkBuilder.cs b/src/tasks/AndroidAppBuilder/ApkBuilder.cs index 6b6acfa1e2d3dd..e3f4630fc9d044 100644 --- a/src/tasks/AndroidAppBuilder/ApkBuilder.cs +++ b/src/tasks/AndroidAppBuilder/ApkBuilder.cs @@ -204,7 +204,8 @@ public class ApkBuilder string monoRunner = Utils.GetEmbeddedResource("MonoRunner.java") .Replace("%EntryPointLibName%", Path.GetFileName(mainLibraryFileName)) - .Replace("%ForceInterpreter%", ForceInterpreter.ToString().ToLower()); + .Replace("%ForceInterpreter%", ForceInterpreter.ToString().ToLower()) + .Replace("%ForceAOT%", ForceAOT.ToString().ToLower()); File.WriteAllText(monoRunnerPath, monoRunner); File.WriteAllText(Path.Combine(OutputDir, "AndroidManifest.xml"), diff --git a/src/tasks/AndroidAppBuilder/Templates/MonoRunner.java b/src/tasks/AndroidAppBuilder/Templates/MonoRunner.java index 5618fdd61504c9..b395031c3423da 100644 --- a/src/tasks/AndroidAppBuilder/Templates/MonoRunner.java +++ b/src/tasks/AndroidAppBuilder/Templates/MonoRunner.java @@ -44,6 +44,7 @@ public class MonoRunner extends Instrumentation static String entryPointLibName = "%EntryPointLibName%"; static Bundle result = new Bundle(); static boolean forceInterpreter = %ForceInterpreter%; + static boolean forceAOT = %ForceAOT%; @Override public void onCreate(Bundle arguments) { @@ -84,7 +85,7 @@ public static int initialize(String entryPointLibName, Context context) { unzipAssets(context, filesDir, "assets.zip"); Log.i("DOTNET", "MonoRunner initialize,, entryPointLibName=" + entryPointLibName); - return initRuntime(filesDir, cacheDir, docsDir, entryPointLibName, forceInterpreter); + return initRuntime(filesDir, cacheDir, docsDir, entryPointLibName, forceInterpreter, forceAOT); } @Override @@ -145,7 +146,7 @@ static void unzipAssets(Context context, String toPath, String zipName) { } } - static native int initRuntime(String libsDir, String cacheDir, String docsDir, String entryPointLibName, boolean forceInterpreter); + static native int initRuntime(String libsDir, String cacheDir, String docsDir, String entryPointLibName, boolean forceInterpreter, boolean forceAOT); static native int setEnv(String key, String value); } diff --git a/src/tasks/AndroidAppBuilder/Templates/monodroid.c b/src/tasks/AndroidAppBuilder/Templates/monodroid.c index 8d4ae5a5ac8d8b..d6888fca7d326c 100644 --- a/src/tasks/AndroidAppBuilder/Templates/monodroid.c +++ b/src/tasks/AndroidAppBuilder/Templates/monodroid.c @@ -23,6 +23,7 @@ static char *bundle_path; static char *executable; static bool force_interpreter; +static bool force_AOT; #define LOG_INFO(fmt, ...) __android_log_print(ANDROID_LOG_DEBUG, "DOTNET", fmt, ##__VA_ARGS__) #define LOG_ERROR(fmt, ...) __android_log_print(ANDROID_LOG_ERROR, "DOTNET", fmt, ##__VA_ARGS__) @@ -147,6 +148,9 @@ log_callback (const char *log_domain, const char *log_level, const char *message } } +void +register_aot_modules (void); + int mono_droid_runtime_init (void) { @@ -187,6 +191,9 @@ mono_droid_runtime_init (void) if (force_interpreter) { LOG_INFO("Interp Enabled"); mono_jit_set_aot_mode(MONO_AOT_MODE_INTERP_ONLY); + } else if (force_AOT) { + register_aot_modules(); + mono_jit_set_aot_mode(MONO_AOT_MODE_FULL); } mono_jit_init_version ("dotnet.android", "mobile"); @@ -224,7 +231,7 @@ Java_net_dot_MonoRunner_setEnv (JNIEnv* env, jobject thiz, jstring j_key, jstrin } int -Java_net_dot_MonoRunner_initRuntime (JNIEnv* env, jobject thiz, jstring j_files_dir, jstring j_cache_dir, jstring j_docs_dir, jstring j_entryPointLibName, jboolean j_forceInterpreter) +Java_net_dot_MonoRunner_initRuntime (JNIEnv* env, jobject thiz, jstring j_files_dir, jstring j_cache_dir, jstring j_docs_dir, jstring j_entryPointLibName, jboolean j_forceInterpreter, jboolean j_forceAOT) { char file_dir[2048]; char cache_dir[2048]; @@ -238,6 +245,7 @@ Java_net_dot_MonoRunner_initRuntime (JNIEnv* env, jobject thiz, jstring j_files_ bundle_path = file_dir; executable = entryPointLibName; force_interpreter = (bool)j_forceInterpreter; + force_AOT = (bool)j_forceAOT; setenv ("HOME", bundle_path, true); setenv ("TMPDIR", cache_dir, true); From cb982b994c416e0d6efe671e78edcb2f378161c4 Mon Sep 17 00:00:00 2001 From: Maxim Lipnin Date: Mon, 1 Feb 2021 18:12:34 +0300 Subject: [PATCH 05/18] Update builder --- eng/testing/tests.mobile.targets | 1 + src/tasks/AndroidAppBuilder/ApkBuilder.cs | 36 ++++++++++++++++++- .../Templates/CMakeLists-android.txt | 5 ++- 3 files changed, 40 insertions(+), 2 deletions(-) diff --git a/eng/testing/tests.mobile.targets b/eng/testing/tests.mobile.targets index 39e6af341f41d6..d89c3e3703eeb7 100644 --- a/eng/testing/tests.mobile.targets +++ b/eng/testing/tests.mobile.targets @@ -75,6 +75,7 @@ Mode="Full" OutputType="AsmOnly" Assemblies="@(AotInputAssemblies)" + AotModulesTablePath="$(BundleDir)\modules.c" UseLLVM="$(MonoEnableLLVM)" LLVMPath="$(MicrosoftNetCoreAppRuntimePackNativeDir)cross\$(PackageRID)"> diff --git a/src/tasks/AndroidAppBuilder/ApkBuilder.cs b/src/tasks/AndroidAppBuilder/ApkBuilder.cs index e3f4630fc9d044..fd0d2c7fafe304 100644 --- a/src/tasks/AndroidAppBuilder/ApkBuilder.cs +++ b/src/tasks/AndroidAppBuilder/ApkBuilder.cs @@ -102,6 +102,22 @@ public class ApkBuilder throw new ArgumentException($"{buildToolsFolder} was not found."); } + var assemblerFiles = new List(); + foreach (ITaskItem file in assemblies) + { + // use AOT files if available + var obj = file.GetMetadata("AssemblerFile"); + if (!string.IsNullOrEmpty(obj)) + { + assemblerFiles.Add(obj); + } + } + + if (ForceAOT && !assemblerFiles.Any()) + { + throw new InvalidOperationException("Need list of AOT files."); + } + Directory.CreateDirectory(OutputDir); Directory.CreateDirectory(Path.Combine(OutputDir, "bin")); Directory.CreateDirectory(Path.Combine(OutputDir, "obj")); @@ -157,11 +173,29 @@ public class ApkBuilder string monoRuntimeLib = Path.Combine(AppDir, "libmonosgen-2.0.a"); if (!File.Exists(monoRuntimeLib)) + { throw new ArgumentException($"libmonosgen-2.0.a was not found in {AppDir}"); + } + else + { + monoRuntimeLib = $" {monoRuntimeLib}{Environment.NewLine}"; + } + + string aotSources = ""; + foreach (string asm in assemblerFiles) + { + // these libraries are linked via modules.c + var name = Path.GetFileNameWithoutExtension(asm); + aotSources += $"add_library({name} OBJECT {asm}){Environment.NewLine}"; + monoRuntimeLib += $" {name}{Environment.NewLine}"; + } string cmakeLists = Utils.GetEmbeddedResource("CMakeLists-android.txt") .Replace("%MonoInclude%", monoRuntimeHeaders) - .Replace("%NativeLibrariesToLink%", monoRuntimeLib); + .Replace("%NativeLibrariesToLink%", monoRuntimeLib) + .Replace("%AotSources%", aotSources) + .Replace("%AotModulesSource%", string.IsNullOrEmpty(aotSources) ? "" : "modules.c"); + File.WriteAllText(Path.Combine(OutputDir, "CMakeLists.txt"), cmakeLists); File.WriteAllText(Path.Combine(OutputDir, "monodroid.c"), Utils.GetEmbeddedResource("monodroid.c")); diff --git a/src/tasks/AndroidAppBuilder/Templates/CMakeLists-android.txt b/src/tasks/AndroidAppBuilder/Templates/CMakeLists-android.txt index 48e1d080fcd5d3..4c054635be8baf 100644 --- a/src/tasks/AndroidAppBuilder/Templates/CMakeLists-android.txt +++ b/src/tasks/AndroidAppBuilder/Templates/CMakeLists-android.txt @@ -5,7 +5,10 @@ project(monodroid) add_library( monodroid SHARED - monodroid.c) + monodroid.c + %AotModulesSource%) + +%AotSources% include_directories("%MonoInclude%") From a47201030caa9fbcb276509636b597a08fc79f0f Mon Sep 17 00:00:00 2001 From: Maxim Lipnin Date: Wed, 3 Feb 2021 12:40:31 +0300 Subject: [PATCH 06/18] Add defines --- src/tasks/AndroidAppBuilder/ApkBuilder.cs | 12 ++++++++++++ .../Templates/CMakeLists-android.txt | 2 ++ src/tasks/AndroidAppBuilder/Templates/monodroid.c | 10 +++++++--- 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/src/tasks/AndroidAppBuilder/ApkBuilder.cs b/src/tasks/AndroidAppBuilder/ApkBuilder.cs index fd0d2c7fafe304..d28fabf07ed5ab 100644 --- a/src/tasks/AndroidAppBuilder/ApkBuilder.cs +++ b/src/tasks/AndroidAppBuilder/ApkBuilder.cs @@ -196,6 +196,18 @@ public class ApkBuilder .Replace("%AotSources%", aotSources) .Replace("%AotModulesSource%", string.IsNullOrEmpty(aotSources) ? "" : "modules.c"); + string defines = ""; + if (ForceInterpreter) + { + defines = "add_definitions(-DFORCE_INTERPRETER=1)"; + } + else if (ForceAOT) + { + defines = "add_definitions(-DFORCE_AOT=1)"; + } + + cmakeLists = cmakeLists.Replace("%Defines%", defines); + File.WriteAllText(Path.Combine(OutputDir, "CMakeLists.txt"), cmakeLists); File.WriteAllText(Path.Combine(OutputDir, "monodroid.c"), Utils.GetEmbeddedResource("monodroid.c")); diff --git a/src/tasks/AndroidAppBuilder/Templates/CMakeLists-android.txt b/src/tasks/AndroidAppBuilder/Templates/CMakeLists-android.txt index 4c054635be8baf..77f6b090e579b6 100644 --- a/src/tasks/AndroidAppBuilder/Templates/CMakeLists-android.txt +++ b/src/tasks/AndroidAppBuilder/Templates/CMakeLists-android.txt @@ -10,6 +10,8 @@ add_library( %AotSources% +%Defines% + include_directories("%MonoInclude%") target_link_libraries( diff --git a/src/tasks/AndroidAppBuilder/Templates/monodroid.c b/src/tasks/AndroidAppBuilder/Templates/monodroid.c index d6888fca7d326c..e8f1ddd1f08265 100644 --- a/src/tasks/AndroidAppBuilder/Templates/monodroid.c +++ b/src/tasks/AndroidAppBuilder/Templates/monodroid.c @@ -148,8 +148,9 @@ log_callback (const char *log_domain, const char *log_level, const char *message } } -void -register_aot_modules (void); +#if FORCE_AOT +void register_aot_modules (void); +#endif int mono_droid_runtime_init (void) @@ -191,10 +192,13 @@ mono_droid_runtime_init (void) if (force_interpreter) { LOG_INFO("Interp Enabled"); mono_jit_set_aot_mode(MONO_AOT_MODE_INTERP_ONLY); - } else if (force_AOT) { + } +#if FORCE_AOT + else if (force_AOT) { register_aot_modules(); mono_jit_set_aot_mode(MONO_AOT_MODE_FULL); } +#endif mono_jit_init_version ("dotnet.android", "mobile"); From 1848d6ee01be48aae48b1fa298b6be8b2a6bb83c Mon Sep 17 00:00:00 2001 From: Maxim Lipnin Date: Wed, 3 Feb 2021 12:40:53 +0300 Subject: [PATCH 07/18] Update the sample --- src/mono/sample/Android/AndroidSampleApp.csproj | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/mono/sample/Android/AndroidSampleApp.csproj b/src/mono/sample/Android/AndroidSampleApp.csproj index 6adb558c09b4b0..0853fd97915bb4 100644 --- a/src/mono/sample/Android/AndroidSampleApp.csproj +++ b/src/mono/sample/Android/AndroidSampleApp.csproj @@ -8,6 +8,7 @@ true Link $(ArtifactsBinDir)microsoft.netcore.app.runtime.$(RuntimeIdentifier)\$(Configuration)\runtimes\android-$(TargetArchitecture)\ + false @@ -44,7 +45,7 @@ + Condition="'$(ForceAOT)' == 'true'"/> @@ -65,13 +66,13 @@ - @@ -81,6 +82,7 @@ RuntimeIdentifier="$(RuntimeIdentifier)" ProjectName="HelloAndroid" ForceInterpreter="$(MonoForceInterpreter)" + ForceAOT="$(ForceAOT)" MonoRuntimeHeaders="$(MicrosoftNetCoreAppRuntimePackDir)\native\include\mono-2.0" Assemblies="@(BundleAssemblies)" MainLibraryFileName="$(AssemblyName).dll" From a0e4c142d3a86f69c416fc8e1f56c7be91bc682d Mon Sep 17 00:00:00 2001 From: Maxim Lipnin Date: Thu, 4 Feb 2021 10:20:20 +0300 Subject: [PATCH 08/18] Update defines usage --- src/tasks/AndroidAppBuilder/Templates/monodroid.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/src/tasks/AndroidAppBuilder/Templates/monodroid.c b/src/tasks/AndroidAppBuilder/Templates/monodroid.c index e8f1ddd1f08265..8f80b0db4f8828 100644 --- a/src/tasks/AndroidAppBuilder/Templates/monodroid.c +++ b/src/tasks/AndroidAppBuilder/Templates/monodroid.c @@ -189,15 +189,12 @@ mono_droid_runtime_init (void) mono_jit_parse_options (1, options); } - if (force_interpreter) { - LOG_INFO("Interp Enabled"); - mono_jit_set_aot_mode(MONO_AOT_MODE_INTERP_ONLY); - } -#if FORCE_AOT - else if (force_AOT) { - register_aot_modules(); - mono_jit_set_aot_mode(MONO_AOT_MODE_FULL); - } +#if FORCE_INTERPRETER + LOG_INFO("Interp Enabled"); + mono_jit_set_aot_mode(MONO_AOT_MODE_INTERP_ONLY); +#elif FORCE_AOT + register_aot_modules(); + mono_jit_set_aot_mode(MONO_AOT_MODE_FULL); #endif mono_jit_init_version ("dotnet.android", "mobile"); From e4f27067bb83b39913d4b051e64ead25044eb6c9 Mon Sep 17 00:00:00 2001 From: Maxim Lipnin Date: Fri, 5 Feb 2021 15:40:30 +0300 Subject: [PATCH 09/18] Remove unnecessary parameters --- src/tasks/AndroidAppBuilder/Templates/MonoRunner.java | 6 ++---- src/tasks/AndroidAppBuilder/Templates/monodroid.c | 6 +----- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/src/tasks/AndroidAppBuilder/Templates/MonoRunner.java b/src/tasks/AndroidAppBuilder/Templates/MonoRunner.java index b395031c3423da..ad5fa5348a4144 100644 --- a/src/tasks/AndroidAppBuilder/Templates/MonoRunner.java +++ b/src/tasks/AndroidAppBuilder/Templates/MonoRunner.java @@ -43,8 +43,6 @@ public class MonoRunner extends Instrumentation static String entryPointLibName = "%EntryPointLibName%"; static Bundle result = new Bundle(); - static boolean forceInterpreter = %ForceInterpreter%; - static boolean forceAOT = %ForceAOT%; @Override public void onCreate(Bundle arguments) { @@ -85,7 +83,7 @@ public static int initialize(String entryPointLibName, Context context) { unzipAssets(context, filesDir, "assets.zip"); Log.i("DOTNET", "MonoRunner initialize,, entryPointLibName=" + entryPointLibName); - return initRuntime(filesDir, cacheDir, docsDir, entryPointLibName, forceInterpreter, forceAOT); + return initRuntime(filesDir, cacheDir, docsDir, entryPointLibName); } @Override @@ -146,7 +144,7 @@ static void unzipAssets(Context context, String toPath, String zipName) { } } - static native int initRuntime(String libsDir, String cacheDir, String docsDir, String entryPointLibName, boolean forceInterpreter, boolean forceAOT); + static native int initRuntime(String libsDir, String cacheDir, String docsDir, String entryPointLibName); static native int setEnv(String key, String value); } diff --git a/src/tasks/AndroidAppBuilder/Templates/monodroid.c b/src/tasks/AndroidAppBuilder/Templates/monodroid.c index 8f80b0db4f8828..105be3c8c14767 100644 --- a/src/tasks/AndroidAppBuilder/Templates/monodroid.c +++ b/src/tasks/AndroidAppBuilder/Templates/monodroid.c @@ -22,8 +22,6 @@ static char *bundle_path; static char *executable; -static bool force_interpreter; -static bool force_AOT; #define LOG_INFO(fmt, ...) __android_log_print(ANDROID_LOG_DEBUG, "DOTNET", fmt, ##__VA_ARGS__) #define LOG_ERROR(fmt, ...) __android_log_print(ANDROID_LOG_ERROR, "DOTNET", fmt, ##__VA_ARGS__) @@ -232,7 +230,7 @@ Java_net_dot_MonoRunner_setEnv (JNIEnv* env, jobject thiz, jstring j_key, jstrin } int -Java_net_dot_MonoRunner_initRuntime (JNIEnv* env, jobject thiz, jstring j_files_dir, jstring j_cache_dir, jstring j_docs_dir, jstring j_entryPointLibName, jboolean j_forceInterpreter, jboolean j_forceAOT) +Java_net_dot_MonoRunner_initRuntime (JNIEnv* env, jobject thiz, jstring j_files_dir, jstring j_cache_dir, jstring j_docs_dir, jstring j_entryPointLibName) { char file_dir[2048]; char cache_dir[2048]; @@ -245,8 +243,6 @@ Java_net_dot_MonoRunner_initRuntime (JNIEnv* env, jobject thiz, jstring j_files_ bundle_path = file_dir; executable = entryPointLibName; - force_interpreter = (bool)j_forceInterpreter; - force_AOT = (bool)j_forceAOT; setenv ("HOME", bundle_path, true); setenv ("TMPDIR", cache_dir, true); From 1914ca080f0d850361fd7fcf59a4f757074fb032 Mon Sep 17 00:00:00 2001 From: Maxim Lipnin Date: Fri, 5 Feb 2021 16:09:02 +0300 Subject: [PATCH 10/18] Remove unused replacements --- src/tasks/AndroidAppBuilder/ApkBuilder.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/tasks/AndroidAppBuilder/ApkBuilder.cs b/src/tasks/AndroidAppBuilder/ApkBuilder.cs index d28fabf07ed5ab..e0be96c5a5f414 100644 --- a/src/tasks/AndroidAppBuilder/ApkBuilder.cs +++ b/src/tasks/AndroidAppBuilder/ApkBuilder.cs @@ -250,8 +250,7 @@ public class ApkBuilder string monoRunner = Utils.GetEmbeddedResource("MonoRunner.java") .Replace("%EntryPointLibName%", Path.GetFileName(mainLibraryFileName)) - .Replace("%ForceInterpreter%", ForceInterpreter.ToString().ToLower()) - .Replace("%ForceAOT%", ForceAOT.ToString().ToLower()); + File.WriteAllText(monoRunnerPath, monoRunner); File.WriteAllText(Path.Combine(OutputDir, "AndroidManifest.xml"), From ffada16869e0c88213b1d479f01b1a308f69455f Mon Sep 17 00:00:00 2001 From: Maxim Lipnin Date: Mon, 8 Feb 2021 09:27:25 +0300 Subject: [PATCH 11/18] Semicolon --- src/tasks/AndroidAppBuilder/ApkBuilder.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tasks/AndroidAppBuilder/ApkBuilder.cs b/src/tasks/AndroidAppBuilder/ApkBuilder.cs index e0be96c5a5f414..bd09d5bdf0008c 100644 --- a/src/tasks/AndroidAppBuilder/ApkBuilder.cs +++ b/src/tasks/AndroidAppBuilder/ApkBuilder.cs @@ -249,7 +249,7 @@ public class ApkBuilder File.Copy(NativeMainSource, javaActivityPath, true); string monoRunner = Utils.GetEmbeddedResource("MonoRunner.java") - .Replace("%EntryPointLibName%", Path.GetFileName(mainLibraryFileName)) + .Replace("%EntryPointLibName%", Path.GetFileName(mainLibraryFileName)); File.WriteAllText(monoRunnerPath, monoRunner); From b0e33172cd26220b5f9942718251187e74add712 Mon Sep 17 00:00:00 2001 From: Maxim Lipnin Date: Mon, 8 Feb 2021 09:37:42 +0300 Subject: [PATCH 12/18] Try updating C-case of modules table generating --- src/tasks/AotCompilerTask/MonoAOTCompiler.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/tasks/AotCompilerTask/MonoAOTCompiler.cs b/src/tasks/AotCompilerTask/MonoAOTCompiler.cs index 7e5baee6f81dd7..d4cd019dce52e9 100644 --- a/src/tasks/AotCompilerTask/MonoAOTCompiler.cs +++ b/src/tasks/AotCompilerTask/MonoAOTCompiler.cs @@ -390,11 +390,13 @@ private void GenerateAotModulesTable(ITaskItem[] assemblies, string[]? profilers _fileWrites.Add(AotModulesTablePath!); if (parsedAotModulesTableLanguage == MonoAotModulesTableLanguage.C) { + writer.WriteLine("#include "); + foreach (var symbol in symbols) { writer.WriteLine($"extern void *{symbol};"); } - writer.WriteLine("static void register_aot_modules ()"); + writer.WriteLine("void register_aot_modules ()"); writer.WriteLine("{"); foreach (var symbol in symbols) { From bc71b6f0e2b0c492832b74747e03e997c8f9e45a Mon Sep 17 00:00:00 2001 From: Maxim Lipnin Date: Mon, 8 Feb 2021 14:07:58 +0300 Subject: [PATCH 13/18] Fix parameter name --- src/tests/run.proj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tests/run.proj b/src/tests/run.proj index 73450c6344bbe8..83d512e561e769 100644 --- a/src/tests/run.proj +++ b/src/tests/run.proj @@ -473,7 +473,7 @@ namespace $([System.String]::Copy($(Category)).Replace(".","_").Replace("\",""). ProjectName="$(Category)" MonoRuntimeHeaders="$(MicrosoftNetCoreAppRuntimePackDir)/native/include/mono-2.0" StripDebugSymbols="$(StripDebugSymbols)" - SourceDir="$(BuildDir)" + AppDir="$(BuildDir)" OutputDir="$(AppDir)"> From a7b7980e8dd7636f2bc58bde844b86a163dd99b1 Mon Sep 17 00:00:00 2001 From: Maxim Lipnin Date: Mon, 8 Feb 2021 15:34:26 +0300 Subject: [PATCH 14/18] MainLibraryFileName is not always required --- src/tasks/AndroidAppBuilder/AndroidAppBuilder.cs | 1 - src/tasks/AndroidAppBuilder/ApkBuilder.cs | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/tasks/AndroidAppBuilder/AndroidAppBuilder.cs b/src/tasks/AndroidAppBuilder/AndroidAppBuilder.cs index 86cb7f1fe374a9..ab21becdc7cfdb 100644 --- a/src/tasks/AndroidAppBuilder/AndroidAppBuilder.cs +++ b/src/tasks/AndroidAppBuilder/AndroidAppBuilder.cs @@ -21,7 +21,6 @@ public class AndroidAppBuilderTask : Task /// /// This library will be used as an entry-point (e.g. TestRunner.dll) /// - [Required] public string MainLibraryFileName { get; set; } = ""!; /// diff --git a/src/tasks/AndroidAppBuilder/ApkBuilder.cs b/src/tasks/AndroidAppBuilder/ApkBuilder.cs index bd09d5bdf0008c..58b1565e489424 100644 --- a/src/tasks/AndroidAppBuilder/ApkBuilder.cs +++ b/src/tasks/AndroidAppBuilder/ApkBuilder.cs @@ -36,7 +36,7 @@ public class ApkBuilder throw new ArgumentException($"AppDir='{AppDir}' is empty or doesn't exist"); } - if (!File.Exists(Path.Combine(AppDir, mainLibraryFileName))) + if (!string.IsNullOrEmpty(mainLibraryFileName) && !File.Exists(Path.Combine(AppDir, mainLibraryFileName))) { throw new ArgumentException($"MainLibraryFileName='{mainLibraryFileName}' was not found in AppDir='{AppDir}'"); } From f54087365fa3d69064df986ea37740604e608872 Mon Sep 17 00:00:00 2001 From: Maxim Lipnin Date: Mon, 8 Feb 2021 16:39:36 +0300 Subject: [PATCH 15/18] Assemblies parameter is not always required --- src/tasks/AndroidAppBuilder/AndroidAppBuilder.cs | 4 ++-- src/tasks/AndroidAppBuilder/ApkBuilder.cs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/tasks/AndroidAppBuilder/AndroidAppBuilder.cs b/src/tasks/AndroidAppBuilder/AndroidAppBuilder.cs index ab21becdc7cfdb..af036e41e27375 100644 --- a/src/tasks/AndroidAppBuilder/AndroidAppBuilder.cs +++ b/src/tasks/AndroidAppBuilder/AndroidAppBuilder.cs @@ -26,7 +26,6 @@ public class AndroidAppBuilderTask : Task /// /// List of paths to assemblies to be included in the app. For AOT builds the 'ObjectFile' metadata key needs to point to the object file. /// - [Required] public ITaskItem[] Assemblies { get; set; } = Array.Empty(); /// @@ -91,7 +90,8 @@ public override bool Execute() apkBuilder.KeyStorePath = KeyStorePath; apkBuilder.ForceInterpreter = ForceInterpreter; apkBuilder.ForceAOT = ForceAOT; - (ApkBundlePath, ApkPackageId) = apkBuilder.BuildApk(Assemblies, abi, MainLibraryFileName, MonoRuntimeHeaders); + apkBuilder.Assemblies = Assemblies; + (ApkBundlePath, ApkPackageId) = apkBuilder.BuildApk(abi, MainLibraryFileName, MonoRuntimeHeaders); return true; } diff --git a/src/tasks/AndroidAppBuilder/ApkBuilder.cs b/src/tasks/AndroidAppBuilder/ApkBuilder.cs index 58b1565e489424..47c24375d03a79 100644 --- a/src/tasks/AndroidAppBuilder/ApkBuilder.cs +++ b/src/tasks/AndroidAppBuilder/ApkBuilder.cs @@ -24,9 +24,9 @@ public class ApkBuilder public string? KeyStorePath { get; set; } public bool ForceInterpreter { get; set; } public bool ForceAOT { get; set; } + public ITaskItem[] Assemblies { get; set; } = Array.Empty(); public (string apk, string packageId) BuildApk( - ITaskItem[] assemblies, string abi, string mainLibraryFileName, string monoRuntimeHeaders) @@ -103,7 +103,7 @@ public class ApkBuilder } var assemblerFiles = new List(); - foreach (ITaskItem file in assemblies) + foreach (ITaskItem file in Assemblies) { // use AOT files if available var obj = file.GetMetadata("AssemblerFile"); From 1eeb9d84d3b13e33e973c3dec037b92d100d1698 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20K=C3=B6plinger?= Date: Thu, 11 Feb 2021 12:54:22 +0100 Subject: [PATCH 16/18] Fix AOT build --- src/tasks/AndroidAppBuilder/ApkBuilder.cs | 4 +- .../Templates/CMakeLists-android.txt | 12 +++-- .../AndroidAppBuilder/Templates/monodroid.c | 44 +++++++++++++++++++ .../AotCompilerTask/MonoAOTCompiler.props | 3 ++ 4 files changed, 57 insertions(+), 6 deletions(-) diff --git a/src/tasks/AndroidAppBuilder/ApkBuilder.cs b/src/tasks/AndroidAppBuilder/ApkBuilder.cs index 47c24375d03a79..0ce54fd15c1d6d 100644 --- a/src/tasks/AndroidAppBuilder/ApkBuilder.cs +++ b/src/tasks/AndroidAppBuilder/ApkBuilder.cs @@ -185,9 +185,7 @@ public class ApkBuilder foreach (string asm in assemblerFiles) { // these libraries are linked via modules.c - var name = Path.GetFileNameWithoutExtension(asm); - aotSources += $"add_library({name} OBJECT {asm}){Environment.NewLine}"; - monoRuntimeLib += $" {name}{Environment.NewLine}"; + aotSources += $" {asm}{Environment.NewLine}"; } string cmakeLists = Utils.GetEmbeddedResource("CMakeLists-android.txt") diff --git a/src/tasks/AndroidAppBuilder/Templates/CMakeLists-android.txt b/src/tasks/AndroidAppBuilder/Templates/CMakeLists-android.txt index 77f6b090e579b6..c74d4625af0fa0 100644 --- a/src/tasks/AndroidAppBuilder/Templates/CMakeLists-android.txt +++ b/src/tasks/AndroidAppBuilder/Templates/CMakeLists-android.txt @@ -2,13 +2,19 @@ cmake_minimum_required(VERSION 3.10) project(monodroid) +enable_language(C ASM) + +if(NOT USE_LLVM) + # the assembler code we generate is GNU which isn't understood by llvm + add_compile_options(-no-integrated-as) +endif() + add_library( monodroid SHARED monodroid.c - %AotModulesSource%) - -%AotSources% + %AotModulesSource% + %AotSources%) %Defines% diff --git a/src/tasks/AndroidAppBuilder/Templates/monodroid.c b/src/tasks/AndroidAppBuilder/Templates/monodroid.c index 105be3c8c14767..cbcb2503eadaf2 100644 --- a/src/tasks/AndroidAppBuilder/Templates/monodroid.c +++ b/src/tasks/AndroidAppBuilder/Templates/monodroid.c @@ -13,10 +13,13 @@ #include #include #include +#include +#include #include #include #include #include +#include #include #include @@ -79,6 +82,46 @@ mono_droid_assembly_preload_hook (MonoAssemblyName *aname, char **assemblies_pat return mono_droid_load_assembly (name, culture); } +static unsigned char * +load_aot_data (MonoAssembly *assembly, int size, void *user_data, void **out_handle) +{ + *out_handle = NULL; + + char path [1024]; + int res; + + MonoAssemblyName *assembly_name = mono_assembly_get_name (assembly); + const char *aname = mono_assembly_name_get_name (assembly_name); + + LOG_INFO ("Looking for aot data for assembly '%s'.", aname); + res = snprintf (path, sizeof (path) - 1, "%s/%s.aotdata", bundle_path, aname); + assert (res > 0); + + int fd = open (path, O_RDONLY); + if (fd < 0) { + LOG_INFO ("Could not load the aot data for %s from %s: %s\n", aname, path, strerror (errno)); + return NULL; + } + + void *ptr = mmap (NULL, size, PROT_READ, MAP_FILE | MAP_PRIVATE, fd, 0); + if (ptr == MAP_FAILED) { + LOG_INFO ("Could not map the aot file for %s: %s\n", aname, strerror (errno)); + close (fd); + return NULL; + } + + close (fd); + LOG_INFO ("Loaded aot data for %s.\n", aname); + *out_handle = ptr; + return (unsigned char *) ptr; +} + +static void +free_aot_data (MonoAssembly *assembly, int size, void *user_data, void *handle) +{ + munmap (handle, size); +} + char * strdup_printf (const char *msg, ...) { @@ -177,6 +220,7 @@ mono_droid_runtime_init (void) mono_debug_init (MONO_DEBUG_FORMAT_MONO); mono_install_assembly_preload_hook (mono_droid_assembly_preload_hook, NULL); + mono_install_load_aot_data_hook (load_aot_data, free_aot_data, NULL); mono_install_unhandled_exception_hook (unhandled_exception_handler, NULL); mono_trace_set_log_handler (log_callback, NULL); mono_set_signal_chaining (true); diff --git a/src/tasks/AotCompilerTask/MonoAOTCompiler.props b/src/tasks/AotCompilerTask/MonoAOTCompiler.props index db518b2e8455da..852a5330a0e733 100644 --- a/src/tasks/AotCompilerTask/MonoAOTCompiler.props +++ b/src/tasks/AotCompilerTask/MonoAOTCompiler.props @@ -14,6 +14,9 @@ + + + From c3687a16a074f6f210605be0c06e24e481f94003 Mon Sep 17 00:00:00 2001 From: Maxim Lipnin Date: Sat, 20 Feb 2021 14:15:06 +0300 Subject: [PATCH 17/18] Adjust android func test directory structure --- .../AOT/Android.Device_Emulator.Aot.Test.csproj} | 2 +- .../Android/{Emulator => Device_Emulator}/AOT/Program.cs | 0 .../Android.Device_Emulator.Interpreter.Test.csproj} | 2 +- .../{Emulator => Device_Emulator}/Interpreter/Program.cs | 0 .../JIT/Android.Device_Emulator.JIT.Test.csproj} | 2 +- .../Android/{Emulator => Device_Emulator}/JIT/Program.cs | 0 6 files changed, 3 insertions(+), 3 deletions(-) rename src/tests/FunctionalTests/Android/{Emulator/AOT/Android.Emulator.Aot.Test.csproj => Device_Emulator/AOT/Android.Device_Emulator.Aot.Test.csproj} (85%) rename src/tests/FunctionalTests/Android/{Emulator => Device_Emulator}/AOT/Program.cs (100%) rename src/tests/FunctionalTests/Android/{Emulator/Interpreter/Android.Emulator.Interpreter.Test.csproj => Device_Emulator/Interpreter/Android.Device_Emulator.Interpreter.Test.csproj} (82%) rename src/tests/FunctionalTests/Android/{Emulator => Device_Emulator}/Interpreter/Program.cs (100%) rename src/tests/FunctionalTests/Android/{Emulator/JIT/Android.Emulator.JIT.Test.csproj => Device_Emulator/JIT/Android.Device_Emulator.JIT.Test.csproj} (81%) rename src/tests/FunctionalTests/Android/{Emulator => Device_Emulator}/JIT/Program.cs (100%) diff --git a/src/tests/FunctionalTests/Android/Emulator/AOT/Android.Emulator.Aot.Test.csproj b/src/tests/FunctionalTests/Android/Device_Emulator/AOT/Android.Device_Emulator.Aot.Test.csproj similarity index 85% rename from src/tests/FunctionalTests/Android/Emulator/AOT/Android.Emulator.Aot.Test.csproj rename to src/tests/FunctionalTests/Android/Device_Emulator/AOT/Android.Device_Emulator.Aot.Test.csproj index 48e4324d195b11..49fd6653dde851 100644 --- a/src/tests/FunctionalTests/Android/Emulator/AOT/Android.Emulator.Aot.Test.csproj +++ b/src/tests/FunctionalTests/Android/Device_Emulator/AOT/Android.Device_Emulator.Aot.Test.csproj @@ -5,7 +5,7 @@ true true $(NetCoreAppCurrent) - Android.Emulator.Aot.Test.dll + Android.Device_Emulator.Aot.Test.dll 42 true diff --git a/src/tests/FunctionalTests/Android/Emulator/AOT/Program.cs b/src/tests/FunctionalTests/Android/Device_Emulator/AOT/Program.cs similarity index 100% rename from src/tests/FunctionalTests/Android/Emulator/AOT/Program.cs rename to src/tests/FunctionalTests/Android/Device_Emulator/AOT/Program.cs diff --git a/src/tests/FunctionalTests/Android/Emulator/Interpreter/Android.Emulator.Interpreter.Test.csproj b/src/tests/FunctionalTests/Android/Device_Emulator/Interpreter/Android.Device_Emulator.Interpreter.Test.csproj similarity index 82% rename from src/tests/FunctionalTests/Android/Emulator/Interpreter/Android.Emulator.Interpreter.Test.csproj rename to src/tests/FunctionalTests/Android/Device_Emulator/Interpreter/Android.Device_Emulator.Interpreter.Test.csproj index f20f4348a2637f..cd209e1ddd3a53 100644 --- a/src/tests/FunctionalTests/Android/Emulator/Interpreter/Android.Emulator.Interpreter.Test.csproj +++ b/src/tests/FunctionalTests/Android/Device_Emulator/Interpreter/Android.Device_Emulator.Interpreter.Test.csproj @@ -5,7 +5,7 @@ false true $(NetCoreAppCurrent) - Android.Emulator.Interpreter.Test.dll + Android.Device_Emulator.Interpreter.Test.dll 42 diff --git a/src/tests/FunctionalTests/Android/Emulator/Interpreter/Program.cs b/src/tests/FunctionalTests/Android/Device_Emulator/Interpreter/Program.cs similarity index 100% rename from src/tests/FunctionalTests/Android/Emulator/Interpreter/Program.cs rename to src/tests/FunctionalTests/Android/Device_Emulator/Interpreter/Program.cs diff --git a/src/tests/FunctionalTests/Android/Emulator/JIT/Android.Emulator.JIT.Test.csproj b/src/tests/FunctionalTests/Android/Device_Emulator/JIT/Android.Device_Emulator.JIT.Test.csproj similarity index 81% rename from src/tests/FunctionalTests/Android/Emulator/JIT/Android.Emulator.JIT.Test.csproj rename to src/tests/FunctionalTests/Android/Device_Emulator/JIT/Android.Device_Emulator.JIT.Test.csproj index 109a6cc549ca7b..3503f290ce73ea 100644 --- a/src/tests/FunctionalTests/Android/Emulator/JIT/Android.Emulator.JIT.Test.csproj +++ b/src/tests/FunctionalTests/Android/Device_Emulator/JIT/Android.Device_Emulator.JIT.Test.csproj @@ -4,7 +4,7 @@ false true $(NetCoreAppCurrent) - Android.Emulator.JIT.Test.dll + Android.Device_Emulator.JIT.Test.dll 42 diff --git a/src/tests/FunctionalTests/Android/Emulator/JIT/Program.cs b/src/tests/FunctionalTests/Android/Device_Emulator/JIT/Program.cs similarity index 100% rename from src/tests/FunctionalTests/Android/Emulator/JIT/Program.cs rename to src/tests/FunctionalTests/Android/Device_Emulator/JIT/Program.cs From 6f1f7b0cbc7c8edc7cb092ac68440e761431254a Mon Sep 17 00:00:00 2001 From: Maxim Lipnin Date: Wed, 24 Feb 2021 15:25:34 +0300 Subject: [PATCH 18/18] Add pinvoke test --- .../AndroidAppBuilder/Templates/monodroid.c | 8 +++++ ...ndroid.Device_Emulator.PInvoke.Test.csproj | 16 ++++++++++ .../Device_Emulator/PInvoke/Program.cs | 31 +++++++++++++++++++ 3 files changed, 55 insertions(+) create mode 100644 src/tests/FunctionalTests/Android/Device_Emulator/PInvoke/Android.Device_Emulator.PInvoke.Test.csproj create mode 100644 src/tests/FunctionalTests/Android/Device_Emulator/PInvoke/Program.cs diff --git a/src/tasks/AndroidAppBuilder/Templates/monodroid.c b/src/tasks/AndroidAppBuilder/Templates/monodroid.c index cbcb2503eadaf2..56cd77a65e3947 100644 --- a/src/tasks/AndroidAppBuilder/Templates/monodroid.c +++ b/src/tasks/AndroidAppBuilder/Templates/monodroid.c @@ -294,3 +294,11 @@ Java_net_dot_MonoRunner_initRuntime (JNIEnv* env, jobject thiz, jstring j_files_ return mono_droid_runtime_init (); } + +// called from C# +void +invoke_external_native_api (void (*callback)(void)) +{ + if (callback) + callback(); +} diff --git a/src/tests/FunctionalTests/Android/Device_Emulator/PInvoke/Android.Device_Emulator.PInvoke.Test.csproj b/src/tests/FunctionalTests/Android/Device_Emulator/PInvoke/Android.Device_Emulator.PInvoke.Test.csproj new file mode 100644 index 00000000000000..3e8c96b95a705c --- /dev/null +++ b/src/tests/FunctionalTests/Android/Device_Emulator/PInvoke/Android.Device_Emulator.PInvoke.Test.csproj @@ -0,0 +1,16 @@ + + + Exe + true + false + true + $(NetCoreAppCurrent) + Android.Device_Emulator.PInvoke.Test.dll + false + 42 + + + + + + diff --git a/src/tests/FunctionalTests/Android/Device_Emulator/PInvoke/Program.cs b/src/tests/FunctionalTests/Android/Device_Emulator/PInvoke/Program.cs new file mode 100644 index 00000000000000..750e83dc4785ad --- /dev/null +++ b/src/tests/FunctionalTests/Android/Device_Emulator/PInvoke/Program.cs @@ -0,0 +1,31 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Threading; +using System.Threading.Tasks; +using System.Runtime.InteropServices; + +public static class Program +{ + [DllImport("__Internal")] + unsafe private static extern void invoke_external_native_api(delegate* unmanaged callback); + + private static int counter = 1; + + [UnmanagedCallersOnly] + private static void Callback() + { + counter = 42; + } + + public static int Main(string[] args) + { + unsafe { + delegate* unmanaged unmanagedPtr = &Callback; + invoke_external_native_api(unmanagedPtr); + } + + return counter; + } +}