diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/MakeBundleNativeCodeExternal.cs b/src/Xamarin.Android.Build.Tasks/Tasks/MakeBundleNativeCodeExternal.cs index 916fc7f4ac6..698aeaab84c 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/MakeBundleNativeCodeExternal.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/MakeBundleNativeCodeExternal.cs @@ -39,6 +39,9 @@ public class MakeBundleNativeCodeExternal : Task public bool EmbedDebugSymbols { get; set; } public bool KeepTemp { get; set; } + [Required] + public string BundleApiPath { get; set; } + [Output] public ITaskItem [] OutputNativeLibraries { get; set; } @@ -113,6 +116,8 @@ bool DoExecute () clb.AppendSwitch ("--nomain"); clb.AppendSwitch ("--i18n none"); clb.AppendSwitch ("--bundled-header"); + clb.AppendSwitch ("--mono-api-struct-path"); + clb.AppendFileNameIfNotNull (BundleApiPath); clb.AppendSwitch ("--style"); clb.AppendSwitch ("linux"); clb.AppendSwitch ("-c"); @@ -157,22 +162,6 @@ bool DoExecute () return false; } - Log.LogDebugMessage ("[mkbundle] modifying mono_mkbundle_init"); - // make some changes in the mkbundle output so that it does not require libmonodroid.so - var mkbundleOutput = new StringBuilder (File.ReadAllText (Path.Combine (outpath, "temp.c"))); - - mkbundleOutput.Replace ("mono_jit_set_aot_mode", "mono_jit_set_aot_mode_ptr") - .Replace ("void mono_mkbundle_init ()", "void mono_mkbundle_init (void (register_bundled_assemblies_func)(const MonoBundledAssembly **), void (register_config_for_assembly_func)(const char *, const char *), void (mono_jit_set_aot_mode_func) (int mode))") - .Replace ("mono_register_config_for_assembly (\"", "register_config_for_assembly_func (\"") - .Replace ("install_dll_config_files (void)", "install_dll_config_files (void (register_config_for_assembly_func)(const char *, const char *))") - .Replace ("install_dll_config_files ()", "install_dll_config_files (register_config_for_assembly_func)") - .Replace ("mono_register_bundled_assemblies(", "register_bundled_assemblies_func(") - .Replace ("int nbundles;", "int nbundles;\n\n\tmono_jit_set_aot_mode_ptr = mono_jit_set_aot_mode_func;"); - - mkbundleOutput.Insert (0, "void (*mono_jit_set_aot_mode_ptr) (int mode);\n"); - - File.WriteAllText (Path.Combine (outpath, "temp.c"), mkbundleOutput.ToString ()); - // then compile temp.c into temp.o and ... clb = new CommandLineBuilder (); @@ -182,6 +171,10 @@ bool DoExecute () // defined even if we don't use them clb.AppendSwitch ($"-D__ANDROID_API__={level}"); + // This is necessary because of the injected code, which is reused between libmonodroid + // and the bundle + clb.AppendSwitch ("-DANDROID"); + clb.AppendSwitch ("-o"); clb.AppendFileNameIfNotNull (Path.Combine (outpath, "temp.o")); if (!string.IsNullOrWhiteSpace (IncludePath)) { diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.csproj b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.csproj index 89133632461..cfa2b5b5215 100644 --- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.csproj +++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.csproj @@ -574,6 +574,10 @@ LayoutBinding.cs PreserveNewest + + mkbundle-api.h + PreserveNewest + diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets index 80084f0bde8..9d93cbdbf64 100755 --- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets +++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets @@ -303,9 +303,8 @@ Copyright (C) 2011-2012 Xamarin. All rights reserved. <_AndroidSequencePointsMode Condition=" '$(_AndroidSequencePointsMode)' == ''">None <_InstantRunEnabled Condition=" '$(_InstantRunEnabled)' == '' ">False <_AndroidBuildPropertiesCache>$(IntermediateOutputPath)build.props - False - + False @@ -2688,12 +2687,14 @@ because xbuild doesn't support framework reference assemblies. + ToolPath="$(_MonoAndroidToolsDirectory)" + BundleApiPath="$(MSBuildThisFileDirectory)\mkbundle-api.h"> diff --git a/src/monodroid/jni/dylib-mono.c b/src/monodroid/jni/dylib-mono.c index 8e1675a7042..67dd46b566d 100644 --- a/src/monodroid/jni/dylib-mono.c +++ b/src/monodroid/jni/dylib-mono.c @@ -139,7 +139,7 @@ int monodroid_dylib_mono_init (struct DylibMono *mono_imports, const char *libmo LOAD_SYMBOL(mono_thread_create) LOAD_SYMBOL(mono_thread_current) LOAD_SYMBOL(mono_use_llvm) - + LOAD_SYMBOL(mono_aot_register_module) if (symbols_missing) { log_fatal (LOG_DEFAULT, "Failed to load some Mono symbols, aborting..."); diff --git a/src/monodroid/jni/dylib-mono.h b/src/monodroid/jni/dylib-mono.h index 25cb828adfd..9d95e4fb7a3 100644 --- a/src/monodroid/jni/dylib-mono.h +++ b/src/monodroid/jni/dylib-mono.h @@ -254,6 +254,7 @@ typedef MonoThread* (*monodroid_mono_thread_current_fptr) (void); typedef void (*monodroid_mono_gc_disable_fptr) (void); typedef void* (*monodroid_mono_install_assembly_refonly_preload_hook_fptr) (MonoAssemblyPreLoadFunc func, void *user_data); typedef int (*monodroid_mono_runtime_set_main_args_fptr) (int argc, char* argv[]); +typedef void (*mono_aot_register_module_fptr) (void* aot_info); /* NOTE: structure members MUST NOT CHANGE ORDER. */ struct DylibMono { @@ -342,6 +343,7 @@ struct DylibMono { monodroid_mono_class_get_property_from_name_fptr mono_class_get_property_from_name; monodroid_mono_domain_from_appdomain_fptr mono_domain_from_appdomain; monodroid_mono_thread_current_fptr mono_thread_current; + mono_aot_register_module_fptr mono_aot_register_module; }; MONO_API struct DylibMono* monodroid_dylib_mono_new (const char *libmono_path); diff --git a/src/monodroid/jni/mkbundle-api.h b/src/monodroid/jni/mkbundle-api.h new file mode 100644 index 00000000000..aa833a70b00 --- /dev/null +++ b/src/monodroid/jni/mkbundle-api.h @@ -0,0 +1,27 @@ +#ifndef __MKBUNDLE_API_H +#define __MKBUNDLE_API_H +typedef struct BundleMonoAPI +{ + void (*mono_register_bundled_assemblies) (const MonoBundledAssembly **assemblies); + void (*mono_register_config_for_assembly) (const char* assembly_name, const char* config_xml); + void (*mono_jit_set_aot_mode) (int mode); + void (*mono_aot_register_module) (void* aot_info); + void (*mono_config_parse_memory) (const char *buffer); + void (*mono_register_machine_config) (const char *config_xml); +} BundleMonoAPI; + +#if ANDROID +#include +#include + +static void +mkbundle_log_error (const char *format, ...) +{ + va_list ap; + + va_start (ap, format); + __android_log_vprint (ANDROID_LOG_ERROR, "mkbundle", format, ap); + va_end (ap); +} +#endif // ANDROID +#endif // __MKBUNDLE_API_H diff --git a/src/monodroid/jni/monodroid-glue.c b/src/monodroid/jni/monodroid-glue.c index 61c7d23a3a2..31ba3d6af67 100644 --- a/src/monodroid/jni/monodroid-glue.c +++ b/src/monodroid/jni/monodroid-glue.c @@ -71,6 +71,7 @@ #include "unzip.h" #include "ioapi.h" #include "monodroid-glue.h" +#include "mkbundle-api.h" #ifndef WINDOWS #include "xamarin_getifaddrs.h" @@ -693,6 +694,7 @@ get_libmonosgen_path () typedef void* (*mono_mkbundle_init_ptr) (void (*)(const MonoBundledAssembly **), void (*)(const char* assembly_name, const char* config_xml),void (*) (int mode)); mono_mkbundle_init_ptr mono_mkbundle_init; +void (*mono_mkbundle_initialize_mono_api) (const BundleMonoAPI *info); static void setup_bundled_app (const char *libappso) @@ -705,7 +707,11 @@ setup_bundled_app (const char *libappso) log_fatal (LOG_BUNDLE, "bundled app initialization error: %s", dlerror ()); exit (FATAL_EXIT_CANNOT_LOAD_BUNDLE); } - + + mono_mkbundle_initialize_mono_api = dlsym (libapp, "initialize_mono_api"); + if (!mono_mkbundle_initialize_mono_api) + log_error (LOG_BUNDLE, "Missing initialize_mono_api in the application"); + mono_mkbundle_init = dlsym (libapp, "mono_mkbundle_init"); if (!mono_mkbundle_init) log_error (LOG_BUNDLE, "Missing mono_mkbundle_init in the application"); @@ -2647,6 +2653,20 @@ mono_runtime_init (char *runtime_args) register_gc_hooks (); + if (mono_mkbundle_initialize_mono_api) { + BundleMonoAPI bundle_mono_api = { + .mono_register_bundled_assemblies = mono.mono_register_bundled_assemblies, + .mono_register_config_for_assembly = mono.mono_register_config_for_assembly, + .mono_jit_set_aot_mode = mono.mono_jit_set_aot_mode, + .mono_aot_register_module = mono.mono_aot_register_module, + .mono_config_parse_memory = mono.mono_config_parse_memory, + .mono_register_machine_config = mono.mono_register_machine_config, + }; + + /* The initialization function copies the struct */ + mono_mkbundle_initialize_mono_api (&bundle_mono_api); + } + if (mono_mkbundle_init) mono_mkbundle_init (mono.mono_register_bundled_assemblies, mono.mono_register_config_for_assembly, mono.mono_jit_set_aot_mode);