Created
April 3, 2023 21:52
-
-
Save mdh1418/941d79c155203fdd9b1b7447bac091a2 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
commit f7a541e3301fff5c08e281fea2345dfe5abe6fa0 | |
Author: mdh1418 <mitchhwang1418@gmail.com> | |
Date: Fri Mar 31 16:40:49 2023 -0400 | |
Setup end-to-end test on Android | |
diff --git a/src/mono/msbuild/android/build/AndroidBuild.targets b/src/mono/msbuild/android/build/AndroidBuild.targets | |
index 26cc272768a..54d2ab13edc 100644 | |
--- a/src/mono/msbuild/android/build/AndroidBuild.targets | |
+++ b/src/mono/msbuild/android/build/AndroidBuild.targets | |
@@ -3,7 +3,7 @@ | |
<AndroidGenerateAppBundle Condition="'$(AndroidGenerateAppBundle)' == '' and '$(GenerateAppBundle)' != ''">$(GenerateAppBundle)</AndroidGenerateAppBundle> | |
<AndroidGenerateAppBundle Condition="'$(AndroidGenerateAppBundle)' == ''">true</AndroidGenerateAppBundle> | |
<!-- Unable to properly integrate nativelib into app build, so not supported for now. --> | |
- <AndroidGenerateAppBundle Condition="'$(_IsLibraryMode)' == 'true'">false</AndroidGenerateAppBundle> | |
+ <AndroidGenerateAppBundle Condition="'$(_IsLibraryMode)' == 'true' and '$(AndroidGenerateAppBundle)' == ''">false</AndroidGenerateAppBundle> | |
<EnableDefaultAssembliesToBundle Condition="'$(EnableDefaultAssembliesToBundle)' == ''">false</EnableDefaultAssembliesToBundle> | |
</PropertyGroup> | |
diff --git a/src/tasks/AndroidAppBuilder/ApkBuilder.cs b/src/tasks/AndroidAppBuilder/ApkBuilder.cs | |
index 650281be454..be051b4859c 100644 | |
--- a/src/tasks/AndroidAppBuilder/ApkBuilder.cs | |
+++ b/src/tasks/AndroidAppBuilder/ApkBuilder.cs | |
@@ -334,7 +334,7 @@ public ApkBuilder(TaskLoggingHelper logger) | |
nativeLibraries += assemblerFilesToLink.ToString(); | |
string aotSources = assemblerFiles.ToString(); | |
- string monodroidSource = (IsLibraryMode) ? "monodroid-librarymode.c" : "monodroid.c"; | |
+ string monodroidSource = "monodroid.c";//(IsLibraryMode) ? "monodroid-librarymode.c" : "monodroid.c"; | |
string cmakeLists = Utils.GetEmbeddedResource("CMakeLists-android.txt") | |
.Replace("%ProjectName%", ProjectName) | |
diff --git a/src/tasks/AndroidAppBuilder/Templates/MainActivity.java b/src/tasks/AndroidAppBuilder/Templates/MainActivity.java | |
index 360fda7973b..1551c2b3598 100644 | |
--- a/src/tasks/AndroidAppBuilder/Templates/MainActivity.java | |
+++ b/src/tasks/AndroidAppBuilder/Templates/MainActivity.java | |
@@ -45,8 +45,11 @@ public class MainActivity extends Activity | |
@Override | |
public void run() { | |
int retcode = MonoRunner.initialize(entryPointLibName, new String[0], ctx); | |
+ retcode = mdh(); | |
textView.setText("Mono Runtime returned: " + retcode); | |
} | |
}, 1000); | |
} | |
+ | |
+ public native int mdh(); | |
} | |
diff --git a/src/tasks/AndroidAppBuilder/Templates/monodroid.c b/src/tasks/AndroidAppBuilder/Templates/monodroid.c | |
index a016353a0b4..273ca36314b 100644 | |
--- a/src/tasks/AndroidAppBuilder/Templates/monodroid.c | |
+++ b/src/tasks/AndroidAppBuilder/Templates/monodroid.c | |
@@ -26,182 +26,6 @@ | |
static char *bundle_path; | |
static char *executable; | |
-#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__) | |
- | |
-#if defined(__arm__) | |
-#define ANDROID_RUNTIME_IDENTIFIER "android-arm" | |
-#elif defined(__aarch64__) | |
-#define ANDROID_RUNTIME_IDENTIFIER "android-arm64" | |
-#elif defined(__i386__) | |
-#define ANDROID_RUNTIME_IDENTIFIER "android-x86" | |
-#elif defined(__x86_64__) | |
-#define ANDROID_RUNTIME_IDENTIFIER "android-x64" | |
-#else | |
-#error Unknown architecture | |
-#endif | |
- | |
-#define RUNTIMECONFIG_BIN_FILE "runtimeconfig.bin" | |
- | |
-static MonoAssembly* | |
-mono_droid_load_assembly (const char *name, const char *culture) | |
-{ | |
- char filename [1024]; | |
- char path [1024]; | |
- int res; | |
- | |
- LOG_INFO ("assembly_preload_hook: %s %s %s\n", name, culture, bundle_path); | |
- | |
- int len = strlen (name); | |
- int has_extension = len > 3 && name [len - 4] == '.' && (!strcmp ("exe", name + (len - 3)) || !strcmp ("dll", name + (len - 3))); | |
- | |
- // add extensions if required. | |
- strlcpy (filename, name, sizeof (filename)); | |
- if (!has_extension) { | |
- strlcat (filename, ".dll", sizeof (filename)); | |
- } | |
- | |
- if (culture && strcmp (culture, "")) | |
- res = snprintf (path, sizeof (path) - 1, "%s/%s/%s", bundle_path, culture, filename); | |
- else | |
- res = snprintf (path, sizeof (path) - 1, "%s/%s", bundle_path, filename); | |
- assert (res > 0); | |
- | |
- struct stat buffer; | |
- if (stat (path, &buffer) == 0) { | |
- MonoAssembly *assembly = mono_assembly_open (path, NULL); | |
- assert (assembly); | |
- return assembly; | |
- } | |
- return NULL; | |
-} | |
- | |
-static MonoAssembly* | |
-mono_droid_assembly_preload_hook (MonoAssemblyName *aname, char **assemblies_path, void* user_data) | |
-{ | |
- const char *name = mono_assembly_name_get_name (aname); | |
- const char *culture = mono_assembly_name_get_culture (aname); | |
- 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, ...) | |
-{ | |
- va_list args; | |
- char *formatted = NULL; | |
- va_start (args, msg); | |
- vasprintf (&formatted, msg, args); | |
- va_end (args); | |
- return formatted; | |
-} | |
- | |
-static MonoObject * | |
-mono_droid_fetch_exception_property (MonoObject *obj, const char *name, bool is_virtual) | |
-{ | |
- MonoMethod *get = NULL; | |
- MonoMethod *get_virt = NULL; | |
- MonoObject *exc = NULL; | |
- | |
- get = mono_class_get_method_from_name (mono_get_exception_class (), name, 0); | |
- if (get) { | |
- if (is_virtual) { | |
- get_virt = mono_object_get_virtual_method (obj, get); | |
- if (get_virt) | |
- get = get_virt; | |
- } | |
- | |
- return (MonoObject *) mono_runtime_invoke (get, obj, NULL, &exc); | |
- } else { | |
- printf ("Could not find the property System.Exception.%s", name); | |
- } | |
- | |
- return NULL; | |
-} | |
- | |
-static char * | |
-mono_droid_fetch_exception_property_string (MonoObject *obj, const char *name, bool is_virtual) | |
-{ | |
- MonoString *str = (MonoString *) mono_droid_fetch_exception_property (obj, name, is_virtual); | |
- return str ? mono_string_to_utf8 (str) : NULL; | |
-} | |
- | |
-void | |
-unhandled_exception_handler (MonoObject *exc, void *user_data) | |
-{ | |
- MonoClass *type = mono_object_get_class (exc); | |
- char *type_name = strdup_printf ("%s.%s", mono_class_get_namespace (type), mono_class_get_name (type)); | |
- char *trace = mono_droid_fetch_exception_property_string (exc, "get_StackTrace", true); | |
- char *message = mono_droid_fetch_exception_property_string (exc, "get_Message", true); | |
- | |
- LOG_ERROR("UnhandledException: %s %s %s", type_name, message, trace); | |
- | |
- free (trace); | |
- free (message); | |
- free (type_name); | |
- exit (1); | |
-} | |
- | |
-void | |
-log_callback (const char *log_domain, const char *log_level, const char *message, mono_bool fatal, void *user_data) | |
-{ | |
- LOG_INFO ("(%s %s) %s", log_domain, log_level, message); | |
- if (fatal) { | |
- LOG_ERROR ("Exit code: %d.", 1); | |
- exit (1); | |
- } | |
-} | |
- | |
-#if defined(FORCE_AOT) && defined(STATIC_AOT) | |
-void register_aot_modules (void); | |
-#endif | |
- | |
-void | |
-cleanup_runtime_config (MonovmRuntimeConfigArguments *args, void *user_data) | |
-{ | |
- free (args); | |
- free (user_data); | |
-} | |
- | |
int | |
mono_droid_runtime_init (const char* executable, int managed_argc, char* managed_argv[], int local_date_time_offset) | |
{ | |
@@ -220,85 +44,7 @@ mono_droid_runtime_init (const char* executable, int managed_argc, char* managed | |
setenv ("DOTNET_DiagnosticPorts", DIAGNOSTIC_PORTS, true); | |
#endif | |
- bool wait_for_debugger = false; | |
- chdir (bundle_path); | |
- | |
- // TODO: set TRUSTED_PLATFORM_ASSEMBLIES, APP_PATHS and NATIVE_DLL_SEARCH_DIRECTORIES | |
- | |
- const char* appctx_keys[3]; | |
- appctx_keys[0] = "RUNTIME_IDENTIFIER"; | |
- appctx_keys[1] = "APP_CONTEXT_BASE_DIRECTORY"; | |
- appctx_keys[2] = "System.TimeZoneInfo.LocalDateTimeOffset"; | |
- | |
- const char* appctx_values[3]; | |
- appctx_values[0] = ANDROID_RUNTIME_IDENTIFIER; | |
- appctx_values[1] = bundle_path; | |
- char local_date_time_offset_buffer[32]; | |
- snprintf (local_date_time_offset_buffer, sizeof(local_date_time_offset_buffer), "%d", local_date_time_offset); | |
- appctx_values[2] = strdup (local_date_time_offset_buffer); | |
- | |
- char *file_name = RUNTIMECONFIG_BIN_FILE; | |
- int str_len = strlen (bundle_path) + strlen (file_name) + 1; // +1 is for the "/" | |
- char *file_path = (char *)malloc (sizeof (char) * (str_len +1)); // +1 is for the terminating null character | |
- int num_char = snprintf (file_path, (str_len + 1), "%s/%s", bundle_path, file_name); | |
- struct stat buffer; | |
- | |
- LOG_INFO ("file_path: %s\n", file_path); | |
- assert (num_char > 0 && num_char == str_len); | |
- | |
- if (stat (file_path, &buffer) == 0) { | |
- MonovmRuntimeConfigArguments *arg = (MonovmRuntimeConfigArguments *)malloc (sizeof (MonovmRuntimeConfigArguments)); | |
- arg->kind = 0; | |
- arg->runtimeconfig.name.path = file_path; | |
- monovm_runtimeconfig_initialize (arg, cleanup_runtime_config, file_path); | |
- } else { | |
- free (file_path); | |
- } | |
- | |
- monovm_initialize(3, appctx_keys, appctx_values); | |
- | |
- 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); | |
- mono_set_crash_chaining (true); | |
- | |
- if (wait_for_debugger) { | |
- char* options[] = { "--debugger-agent=transport=dt_socket,server=y,address=0.0.0.0:55555" }; | |
- mono_jit_parse_options (1, options); | |
- } | |
- | |
-#if FORCE_INTERPRETER | |
- LOG_INFO("Interp Enabled"); | |
- mono_jit_set_aot_mode(MONO_AOT_MODE_INTERP_ONLY); | |
-#elif FORCE_AOT | |
- LOG_INFO("AOT Enabled"); | |
-#if STATIC_AOT | |
- register_aot_modules(); | |
-#endif // STATIC_AOT | |
- | |
-#if FULL_AOT | |
- mono_jit_set_aot_mode(MONO_AOT_MODE_FULL); | |
-#else | |
- mono_jit_set_aot_mode(MONO_AOT_MODE_NORMAL); | |
-#endif // FULL_AOT | |
-#endif // FORCE_INTERPRETER | |
- | |
- MonoDomain *domain = mono_jit_init_version ("dotnet.android", "mobile"); | |
- assert (domain); | |
- | |
- MonoAssembly *assembly = mono_droid_load_assembly (executable, NULL); | |
- assert (assembly); | |
- | |
- LOG_INFO ("Executable: %s", executable); | |
- int res = mono_jit_exec (domain, assembly, managed_argc, managed_argv); | |
- LOG_INFO ("Exit code: %d.", res); | |
- | |
- mono_jit_cleanup (domain); | |
- | |
- return res; | |
+ return 1418; | |
} | |
static void | |
@@ -311,6 +57,11 @@ strncpy_str (JNIEnv *env, char *buff, jstring str, int nbuff) | |
(*env)->ReleaseStringUTFChars (env, str, copy_buff); | |
} | |
+int | |
+Java_net_dot_MainActivity_mdh (JNIEnv* env, jobject thiz) { | |
+ return mdh(); | |
+} | |
+ | |
void | |
Java_net_dot_MonoRunner_setEnv (JNIEnv* env, jobject thiz, jstring j_key, jstring j_value) | |
{ | |
@@ -362,11 +113,3 @@ Java_net_dot_MonoRunner_initRuntime (JNIEnv* env, jobject thiz, jstring j_files_ | |
free(managed_argv); | |
return res; | |
} | |
- | |
-// called from C# | |
-void | |
-invoke_external_native_api (void (*callback)(void)) | |
-{ | |
- if (callback) | |
- callback(); | |
-} | |
diff --git a/src/tests/FunctionalTests/Android/Device_Emulator/AOT_LLVM/Android.Device_Emulator.Aot_Llvm.Test.csproj b/src/tests/FunctionalTests/Android/Device_Emulator/AOT_LLVM/Android.Device_Emulator.Aot_Llvm.Test.csproj | |
index 49ddce32380..24bfbad7d41 100644 | |
--- a/src/tests/FunctionalTests/Android/Device_Emulator/AOT_LLVM/Android.Device_Emulator.Aot_Llvm.Test.csproj | |
+++ b/src/tests/FunctionalTests/Android/Device_Emulator/AOT_LLVM/Android.Device_Emulator.Aot_Llvm.Test.csproj | |
@@ -6,9 +6,12 @@ | |
<TestRuntime>true</TestRuntime> | |
<TargetFramework>$(NetCoreAppCurrent)</TargetFramework> | |
<MainLibraryFileName>Android.Device_Emulator.Aot_Llvm.Test.dll</MainLibraryFileName> | |
- <ExpectedExitCode>42</ExpectedExitCode> | |
+ <ExpectedExitCode>1418</ExpectedExitCode> | |
<EnableAggressiveTrimming>true</EnableAggressiveTrimming> | |
<MonoEnableLLVM>true</MonoEnableLLVM> | |
+ <NativeLib>shared</NativeLib> | |
+ <AndroidGenerateAppBundle>true</AndroidGenerateAppBundle> | |
+ <ForceFullAOT>true</ForceFullAOT> | |
</PropertyGroup> | |
<ItemGroup> | |
diff --git a/src/tests/FunctionalTests/Android/Device_Emulator/AOT_LLVM/ILLink.Descriptors.xml b/src/tests/FunctionalTests/Android/Device_Emulator/AOT_LLVM/ILLink.Descriptors.xml | |
index b1259ec37ac..2d249806b9a 100644 | |
--- a/src/tests/FunctionalTests/Android/Device_Emulator/AOT_LLVM/ILLink.Descriptors.xml | |
+++ b/src/tests/FunctionalTests/Android/Device_Emulator/AOT_LLVM/ILLink.Descriptors.xml | |
@@ -1,7 +1,7 @@ | |
<linker> | |
<assembly fullname="Android.Device_Emulator.Aot_Llvm.Test"> | |
<type fullname="Program"> | |
- <method name="SayHello" /> | |
+ <method name="mdh" /> | |
</type> | |
</assembly> | |
</linker> | |
\ No newline at end of file | |
diff --git a/src/tests/FunctionalTests/Android/Device_Emulator/AOT_LLVM/Program.cs b/src/tests/FunctionalTests/Android/Device_Emulator/AOT_LLVM/Program.cs | |
index 916d1f1aa03..e583f49528c 100644 | |
--- a/src/tests/FunctionalTests/Android/Device_Emulator/AOT_LLVM/Program.cs | |
+++ b/src/tests/FunctionalTests/Android/Device_Emulator/AOT_LLVM/Program.cs | |
@@ -6,15 +6,14 @@ | |
public static class Program | |
{ | |
- [UnmanagedCallersOnly(EntryPoint = nameof(SayHello))] | |
- public static void SayHello() | |
+ [UnmanagedCallersOnly(EntryPoint="mdh")] | |
+ public static int mdh() | |
{ | |
- Console.WriteLine("Called from native! Hello!"); | |
+ return 1418; | |
} | |
public static int Main() | |
{ | |
- Console.WriteLine("Hello, Android!"); // logcat | |
return 42; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment