diff options
Diffstat (limited to 'modules')
10 files changed, 133 insertions, 54 deletions
diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp index 134dd92078..f74c32ba04 100644 --- a/modules/mono/csharp_script.cpp +++ b/modules/mono/csharp_script.cpp @@ -2179,7 +2179,9 @@ bool CSharpScript::_update_exports(PlaceHolderScriptInstance *p_instance_to_upda  	if (exports_invalidated)  #endif  	{ +#ifdef TOOLS_ENABLED  		exports_invalidated = false; +#endif  		changed = true; @@ -2222,6 +2224,7 @@ bool CSharpScript::_update_exports(PlaceHolderScriptInstance *p_instance_to_upda  						}  					}); +#ifdef TOOLS_ENABLED  			GDMonoCache::managed_callbacks.ScriptManagerBridge_GetPropertyDefaultValues(this,  					[](CSharpScript *p_script, GDMonoCache::godotsharp_property_def_val_pair *p_def_vals, int32_t p_count) {  						for (int i = 0; i < p_count; i++) { @@ -2233,6 +2236,7 @@ bool CSharpScript::_update_exports(PlaceHolderScriptInstance *p_instance_to_upda  							p_script->exported_members_defval_cache[name] = value;  						}  					}); +#endif  		}  	} diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotPluginsInitializerGenerator.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotPluginsInitializerGenerator.cs index 497a1b908c..54da6218f3 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotPluginsInitializerGenerator.cs +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotPluginsInitializerGenerator.cs @@ -26,14 +26,16 @@ namespace GodotPlugins.Game  {      internal static partial class Main      { -        [UnmanagedCallersOnly] -        private static godot_bool InitializeFromGameProject(IntPtr outManagedCallbacks) +        [UnmanagedCallersOnly(EntryPoint = ""godotsharp_game_main_init"")] +        private static godot_bool InitializeFromGameProject(IntPtr godotDllHandle, IntPtr outManagedCallbacks)          {              try              { +                DllImportResolver dllImportResolver = new GodotDllImportResolver(godotDllHandle).OnResolveDllImport; +                  var coreApiAssembly = typeof(Godot.Object).Assembly; -                NativeLibrary.SetDllImportResolver(coreApiAssembly, GodotDllImportResolver.OnResolveDllImport); +                NativeLibrary.SetDllImportResolver(coreApiAssembly, dllImportResolver);                  ManagedCallbacks.Create(outManagedCallbacks); diff --git a/modules/mono/editor/GodotTools/GodotTools/Build/BuildSystem.cs b/modules/mono/editor/GodotTools/GodotTools/Build/BuildSystem.cs index 221deede2f..506c0ec067 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Build/BuildSystem.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Build/BuildSystem.cs @@ -197,10 +197,6 @@ namespace GodotTools.Build              // Logger              AddLoggerArgument(buildInfo, arguments); -            // Trimming is not supported for dynamically loaded assemblies, as is our case with self hosting: -            // https://github.com/dotnet/runtime/blob/main/docs/design/features/native-hosting.md#incompatible-with-trimming -            arguments.Add("-p:PublishTrimmed=false"); -              // Custom properties              foreach (string customProperty in buildInfo.CustomProperties)              { diff --git a/modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs b/modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs index edf3eeb7fa..8d88734ead 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs @@ -134,7 +134,16 @@ namespace GodotTools.Export                  throw new Exception("Failed to build project");              } -            if (!File.Exists(Path.Combine(publishOutputTempDir, $"{GodotSharpEditor.ProjectAssemblyName}.dll"))) +            string soExt = ridOS switch +            { +                OS.DotNetOS.Win or OS.DotNetOS.Win10 => "dll", +                OS.DotNetOS.OSX or OS.DotNetOS.iOS => "dylib", +                _ => "so" +            }; + +            if (!File.Exists(Path.Combine(publishOutputTempDir, $"{GodotSharpEditor.ProjectAssemblyName}.dll")) +                // NativeAOT shared library output +                && !File.Exists(Path.Combine(publishOutputTempDir, $"{GodotSharpEditor.ProjectAssemblyName}.{soExt}")))              {                  throw new NotSupportedException(                      "Publish succeeded but project assembly not found in the output directory"); diff --git a/modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs b/modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs index 50c5dc96a7..62140d41bc 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs @@ -44,7 +44,7 @@ namespace GodotTools.Utils              public const string HTML5 = "javascript";          } -        private static class DotNetOS +        public static class DotNetOS          {              public const string Win = "win";              public const string OSX = "osx"; diff --git a/modules/mono/glue/GodotSharp/GodotPlugins/Main.cs b/modules/mono/glue/GodotSharp/GodotPlugins/Main.cs index 0cb9e57530..2a2e147eaa 100644 --- a/modules/mono/glue/GodotSharp/GodotPlugins/Main.cs +++ b/modules/mono/glue/GodotSharp/GodotPlugins/Main.cs @@ -20,22 +20,26 @@ namespace GodotPlugins              AssemblyLoadContext.GetLoadContext(Assembly.GetExecutingAssembly()) ??              AssemblyLoadContext.Default; +        private static DllImportResolver? _dllImportResolver; +          // Right now we do it this way for simplicity as hot-reload is disabled. It will need to be changed later.          [UnmanagedCallersOnly]          // ReSharper disable once UnusedMember.Local -        private static unsafe godot_bool InitializeFromEngine(godot_bool editorHint, +        private static unsafe godot_bool InitializeFromEngine(IntPtr godotDllHandle, godot_bool editorHint,              PluginsCallbacks* pluginsCallbacks, ManagedCallbacks* managedCallbacks)          {              try              { +                _dllImportResolver = new GodotDllImportResolver(godotDllHandle).OnResolveDllImport; +                  SharedAssemblies.Add(CoreApiAssembly.GetName()); -                NativeLibrary.SetDllImportResolver(CoreApiAssembly, GodotDllImportResolver.OnResolveDllImport); +                NativeLibrary.SetDllImportResolver(CoreApiAssembly, _dllImportResolver);                  if (editorHint.ToBool())                  {                      _editorApiAssembly = Assembly.Load("GodotSharpEditor");                      SharedAssemblies.Add(_editorApiAssembly.GetName()); -                    NativeLibrary.SetDllImportResolver(_editorApiAssembly, GodotDllImportResolver.OnResolveDllImport); +                    NativeLibrary.SetDllImportResolver(_editorApiAssembly, _dllImportResolver);                  }                  *pluginsCallbacks = new() @@ -97,7 +101,7 @@ namespace GodotPlugins                  var assembly = LoadPlugin(assemblyPath); -                NativeLibrary.SetDllImportResolver(assembly, GodotDllImportResolver.OnResolveDllImport); +                NativeLibrary.SetDllImportResolver(assembly, _dllImportResolver!);                  var method = assembly.GetType("GodotTools.GodotSharpEditor")?                      .GetMethod("InternalCreateInstance", diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.cs index 71736a65c7..61987c6466 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.cs @@ -39,7 +39,12 @@ namespace Godot.Bridge              try              { -                Type nativeType = TypeGetProxyClass(nativeTypeName); +                using var stringName = StringName.CreateTakingOwnershipOfDisposableValue( +                    NativeFuncs.godotsharp_string_name_new_copy(CustomUnsafe.AsRef(nativeTypeName))); +                string nativeTypeNameStr = stringName.ToString(); + +                Type nativeType = TypeGetProxyClass(nativeTypeNameStr) ?? throw new InvalidOperationException( +                    "Wrapper class not found for type: " + nativeTypeNameStr);                  var obj = (Object)FormatterServices.GetUninitializedObject(nativeType);                  var ctor = nativeType.GetConstructor( @@ -171,12 +176,9 @@ namespace Godot.Bridge              }          } -        private static unsafe Type TypeGetProxyClass(godot_string_name* nativeTypeName) +        private static Type TypeGetProxyClass(string nativeTypeNameStr)          {              // Performance is not critical here as this will be replaced with a generated dictionary. -            using var stringName = StringName.CreateTakingOwnershipOfDisposableValue( -                NativeFuncs.godotsharp_string_name_new_copy(CustomUnsafe.AsRef(nativeTypeName))); -            string nativeTypeNameStr = stringName.ToString();              if (nativeTypeNameStr[0] == '_')                  nativeTypeNameStr = nativeTypeNameStr.Substring(1); @@ -186,7 +188,7 @@ namespace Godot.Bridge              if (wrapperType == null)              {                  wrapperType = AppDomain.CurrentDomain.GetAssemblies() -                    .First(a => a.GetName().Name == "GodotSharpEditor") +                    .FirstOrDefault(a => a.GetName().Name == "GodotSharpEditor")?                      .GetType("Godot." + nativeTypeNameStr);              } diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/GodotDllImportResolver.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/GodotDllImportResolver.cs index c4a90625c3..5579992d2b 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/GodotDllImportResolver.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/GodotDllImportResolver.cs @@ -6,9 +6,16 @@ using System.Runtime.InteropServices;  namespace Godot.NativeInterop  { -    public static class GodotDllImportResolver +    public class GodotDllImportResolver      { -        public static IntPtr OnResolveDllImport(string libraryName, Assembly assembly, DllImportSearchPath? searchPath) +        private IntPtr _internalHandle; + +        public GodotDllImportResolver(IntPtr internalHandle) +        { +            _internalHandle = internalHandle; +        } + +        public IntPtr OnResolveDllImport(string libraryName, Assembly assembly, DllImportSearchPath? searchPath)          {              if (libraryName == "__Internal")              { @@ -18,7 +25,7 @@ namespace Godot.NativeInterop                  }                  else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))                  { -                    return Linux.dlopen(IntPtr.Zero, Linux.RTLD_LAZY); +                    return _internalHandle;                  }                  else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))                  { @@ -40,18 +47,6 @@ namespace Godot.NativeInterop              public static extern IntPtr dlopen(IntPtr path, int mode);          } -        private static class Linux -        { -            // libdl.so was resulting in DllNotFoundException, for some reason... -            // libcoreclr.so should work with both CoreCLR and the .NET Core version of Mono. -            private const string SystemLibrary = "libcoreclr.so"; - -            public const int RTLD_LAZY = 1; - -            [DllImport(SystemLibrary)] -            public static extern IntPtr dlopen(IntPtr path, int mode); -        } -          private static class Win32          {              private const string SystemLibrary = "Kernel32.dll"; diff --git a/modules/mono/mono_gd/gd_mono.cpp b/modules/mono/mono_gd/gd_mono.cpp index 8499d30ba4..d57ad2831a 100644 --- a/modules/mono/mono_gd/gd_mono.cpp +++ b/modules/mono/mono_gd/gd_mono.cpp @@ -48,6 +48,9 @@  #include <coreclr_delegates.h>  #include <hostfxr.h> +#ifdef UNIX_ENABLED +#include <dlfcn.h> +#endif  // TODO mobile  #if 0 @@ -168,18 +171,24 @@ String find_hostfxr() {  #else  #if defined(WINDOWS_ENABLED) -	return GodotSharpDirs::get_api_assemblies_dir() -			.plus_file("hostfxr.dll"); +	String probe_path = GodotSharpDirs::get_api_assemblies_dir() +								.plus_file("hostfxr.dll");  #elif defined(MACOS_ENABLED) -	return GodotSharpDirs::get_api_assemblies_dir() -			.plus_file("libhostfxr.dylib"); +	String probe_path = GodotSharpDirs::get_api_assemblies_dir() +								.plus_file("libhostfxr.dylib");  #elif defined(UNIX_ENABLED) -	return GodotSharpDirs::get_api_assemblies_dir() -			.plus_file("libhostfxr.so"); +	String probe_path = GodotSharpDirs::get_api_assemblies_dir() +								.plus_file("libhostfxr.so");  #else  #error "Platform not supported (yet?)"  #endif +	if (FileAccess::exists(probe_path)) { +		return probe_path; +	} + +	return String(); +  #endif  } @@ -285,11 +294,21 @@ load_assembly_and_get_function_pointer_fn initialize_hostfxr_self_contained(  #endif  #ifdef TOOLS_ENABLED -using godot_plugins_initialize_fn = bool (*)(bool, gdmono::PluginCallbacks *, GDMonoCache::ManagedCallbacks *); +using godot_plugins_initialize_fn = bool (*)(void *, bool, gdmono::PluginCallbacks *, GDMonoCache::ManagedCallbacks *);  #else -using godot_plugins_initialize_fn = bool (*)(GDMonoCache::ManagedCallbacks *); +using godot_plugins_initialize_fn = bool (*)(void *, GDMonoCache::ManagedCallbacks *);  #endif +static String get_assembly_name() { +	String appname = ProjectSettings::get_singleton()->get("application/config/name"); +	String appname_safe = OS::get_singleton()->get_safe_dir_name(appname); +	if (appname_safe.is_empty()) { +		appname_safe = "UnnamedProject"; +	} + +	return appname_safe; +} +  #ifdef TOOLS_ENABLED  godot_plugins_initialize_fn initialize_hostfxr_and_godot_plugins(bool &r_runtime_initialized) {  	godot_plugins_initialize_fn godot_plugins_initialize = nullptr; @@ -320,15 +339,9 @@ godot_plugins_initialize_fn initialize_hostfxr_and_godot_plugins(bool &r_runtime  }  #else  godot_plugins_initialize_fn initialize_hostfxr_and_godot_plugins(bool &r_runtime_initialized) { -	String appname = ProjectSettings::get_singleton()->get("application/config/name"); -	String appname_safe = OS::get_singleton()->get_safe_dir_name(appname); -	if (appname_safe.is_empty()) { -		appname_safe = "UnnamedProject"; -	} -  	godot_plugins_initialize_fn godot_plugins_initialize = nullptr; -	String assembly_name = appname_safe; +	String assembly_name = get_assembly_name();  	HostFxrCharString assembly_path = str_to_hostfxr(GodotSharpDirs::get_api_assemblies_dir()  															 .plus_file(assembly_name + ".dll")); @@ -351,6 +364,38 @@ godot_plugins_initialize_fn initialize_hostfxr_and_godot_plugins(bool &r_runtime  	return godot_plugins_initialize;  } + +godot_plugins_initialize_fn try_load_native_aot_library(void *&r_aot_dll_handle) { +	String assembly_name = get_assembly_name(); + +#if defined(WINDOWS_ENABLED) +	String native_aot_so_path = GodotSharpDirs::get_api_assemblies_dir().plus_file(assembly_name + ".dll"); +#elif defined(MACOS_ENABLED) +	String native_aot_so_path = GodotSharpDirs::get_api_assemblies_dir().plus_file(assembly_name + ".dylib"); +#elif defined(UNIX_ENABLED) +	String native_aot_so_path = GodotSharpDirs::get_api_assemblies_dir().plus_file(assembly_name + ".so"); +#else +#error "Platform not supported (yet?)" +#endif + +	if (FileAccess::exists(native_aot_so_path)) { +		Error err = OS::get_singleton()->open_dynamic_library(native_aot_so_path, r_aot_dll_handle); + +		if (err != OK) { +			return nullptr; +		} + +		void *lib = r_aot_dll_handle; + +		void *symbol = nullptr; + +		err = OS::get_singleton()->get_dynamic_library_symbol_handle(lib, "godotsharp_game_main_init", symbol); +		ERR_FAIL_COND_V(err != OK, nullptr); +		return (godot_plugins_initialize_fn)symbol; +	} + +	return nullptr; +}  #endif  } // namespace @@ -377,25 +422,46 @@ void GDMono::initialize() {  	_init_godot_api_hashes(); +	godot_plugins_initialize_fn godot_plugins_initialize = nullptr; +  	if (!load_hostfxr(hostfxr_dll_handle)) { +#if !defined(TOOLS_ENABLED) +		godot_plugins_initialize = try_load_native_aot_library(hostfxr_dll_handle); + +		if (godot_plugins_initialize != nullptr) { +			is_native_aot = true; +		} else { +			ERR_FAIL_MSG(".NET: Failed to load hostfxr"); +		} +#else  		ERR_FAIL_MSG(".NET: Failed to load hostfxr"); +#endif  	} -	godot_plugins_initialize_fn godot_plugins_initialize = -			initialize_hostfxr_and_godot_plugins(runtime_initialized); -	ERR_FAIL_NULL(godot_plugins_initialize); +	if (!is_native_aot) { +		godot_plugins_initialize = initialize_hostfxr_and_godot_plugins(runtime_initialized); +		ERR_FAIL_NULL(godot_plugins_initialize); +	}  	GDMonoCache::ManagedCallbacks managed_callbacks; +	void *godot_dll_handle = nullptr; + +#if defined(UNIX_ENABLED) && !defined(MACOS_ENABLED) && !defined(IOS_ENABLED) +	// Managed code can access it on its own on other platforms +	godot_dll_handle = dlopen(nullptr, RTLD_NOW); +#endif +  #ifdef TOOLS_ENABLED  	gdmono::PluginCallbacks plugin_callbacks_res; -	bool init_ok = godot_plugins_initialize(Engine::get_singleton()->is_editor_hint(), +	bool init_ok = godot_plugins_initialize(godot_dll_handle, +			Engine::get_singleton()->is_editor_hint(),  			&plugin_callbacks_res, &managed_callbacks);  	ERR_FAIL_COND_MSG(!init_ok, ".NET: GodotPlugins initialization failed");  	plugin_callbacks = plugin_callbacks_res;  #else -	bool init_ok = godot_plugins_initialize(&managed_callbacks); +	bool init_ok = godot_plugins_initialize(godot_dll_handle, &managed_callbacks);  	ERR_FAIL_COND_MSG(!init_ok, ".NET: GodotPlugins initialization failed");  #endif diff --git a/modules/mono/mono_gd/gd_mono.h b/modules/mono/mono_gd/gd_mono.h index 66ed331b67..301782575c 100644 --- a/modules/mono/mono_gd/gd_mono.h +++ b/modules/mono/mono_gd/gd_mono.h @@ -61,6 +61,7 @@ class GDMono {  	bool finalizing_scripts_domain;  	void *hostfxr_dll_handle = nullptr; +	bool is_native_aot = false;  #ifdef TOOLS_ENABLED  	bool _load_project_assembly();  |