From 5c461069b39150244d4d8f309bffbe6de6c60308 Mon Sep 17 00:00:00 2001 From: Relintai Date: Tue, 23 May 2023 17:54:30 +0200 Subject: [PATCH] Added godot's mono module. --- .editorconfig | 14 + .gitignore | 2 + LICENSE.txt | 21 + SCsub | 64 + __init__.py | 0 build_scripts/__init__.py | 0 build_scripts/api_solution_build.py | 80 + build_scripts/gen_cs_glue_version.py | 20 + build_scripts/godot_tools_build.py | 38 + build_scripts/make_android_mono_config.py | 55 + build_scripts/mono_android_config.xml | 28 + build_scripts/mono_configure.py | 585 +++ build_scripts/mono_reg_utils.py | 119 + build_scripts/solution_builder.py | 148 + build_scripts/tls_configure.py | 37 + class_db_api_json.cpp | 247 ++ class_db_api_json.h | 46 + config.py | 77 + csharp_script.cpp | 3482 +++++++++++++++++ csharp_script.h | 496 +++ doc_classes/CSharpScript.xml | 24 + doc_classes/GodotSharp.xml | 76 + editor/Godot.NET.Sdk/Godot.NET.Sdk.sln | 16 + .../Godot.NET.Sdk/Godot.NET.Sdk.csproj | 35 + .../Godot.NET.Sdk/Godot.NET.Sdk.nuspec | 22 + .../Godot.NET.Sdk/Godot.NET.Sdk/Sdk/Sdk.props | 117 + .../Godot.NET.Sdk/Sdk/Sdk.targets | 29 + .../Godot.NET.Sdk.AssemblyInfo.cs | 24 + .../Godot.NET.Sdk.AssemblyInfoInputs.cache | 1 + ....GeneratedMSBuildEditorConfig.editorconfig | 3 + editor/GodotTools/.gitignore | 355 ++ .../GodotBuildLogger.cs | 175 + .../GodotTools.BuildLogger.csproj | 13 + .../GodotTools/GodotTools.Core/FileUtils.cs | 30 + .../GodotTools.Core/GodotTools.Core.csproj | 7 + .../GodotTools.Core/ProcessExtensions.cs | 38 + .../GodotTools.Core/StringExtensions.cs | 83 + .../ForwarderMessageHandler.cs | 57 + .../GodotTools.IdeMessaging.CLI.csproj | 17 + .../GodotTools.IdeMessaging.CLI/Program.cs | 217 + .../GodotTools.IdeMessaging/Client.cs | 332 ++ .../ClientHandshake.cs | 44 + .../ClientMessageHandler.cs | 52 + .../GodotIdeMetadata.cs | 47 + .../GodotTools.IdeMessaging.csproj | 24 + .../GodotTools.IdeMessaging/IHandshake.cs | 8 + .../GodotTools.IdeMessaging/ILogger.cs | 13 + .../IMessageHandler.cs | 9 + .../GodotTools.IdeMessaging/Message.cs | 52 + .../GodotTools.IdeMessaging/MessageDecoder.cs | 100 + .../GodotTools.IdeMessaging/Peer.cs | 302 ++ .../Requests/Requests.cs | 116 + .../ResponseAwaiter.cs | 23 + .../Utils/NotifyAwaiter.cs | 64 + .../Utils/SemaphoreExtensions.cs | 32 + .../GodotTools.OpenVisualStudio.csproj | 12 + .../GodotTools.OpenVisualStudio/Program.cs | 289 ++ .../ApiAssembliesInfo.cs | 15 + .../DotNetSolution.cs | 165 + .../GodotTools.ProjectEditor.csproj | 34 + .../IdentifierUtils.cs | 205 + .../GodotTools.ProjectEditor/MSBuild.exe | 0 .../ProjectExtensions.cs | 133 + .../ProjectGenerator.cs | 50 + .../GodotTools.ProjectEditor/ProjectUtils.cs | 471 +++ editor/GodotTools/GodotTools.sln | 41 + .../GodotTools/GodotTools/Build/BuildInfo.cs | 58 + .../GodotTools/Build/BuildManager.cs | 294 ++ .../GodotTools/Build/BuildOutputView.cs | 418 ++ .../GodotTools/Build/BuildResult.cs | 8 + .../GodotTools/Build/BuildSystem.cs | 156 + .../GodotTools/GodotTools/Build/BuildTool.cs | 10 + .../GodotTools/Build/MSBuildPanel.cs | 181 + .../GodotTools/Build/MsBuildFinder.cs | 233 ++ .../GodotTools/GodotTools/CsProjOperations.cs | 108 + .../GodotTools/Export/AotBuilder.cs | 834 ++++ .../GodotTools/GodotTools/Export/AotCache.cs | 144 + .../GodotTools/Export/ExportPlugin.cs | 485 +++ .../GodotTools/Export/XcodeHelper.cs | 93 + .../GodotTools/GodotTools/ExternalEditorId.cs | 12 + .../GodotTools/GodotTools/GodotSharpEditor.cs | 548 +++ .../GodotTools/GodotTools/GodotTools.csproj | 41 + .../GodotTools/HotReloadAssemblyWatcher.cs | 48 + .../GodotTools/Ides/GodotIdeManager.cs | 229 ++ .../GodotTools/Ides/MessagingServer.cs | 395 ++ .../GodotTools/Ides/MonoDevelop/EditorId.cs | 8 + .../GodotTools/Ides/MonoDevelop/Instance.cs | 141 + .../GodotTools/Ides/Rider/RiderPathLocator.cs | 470 +++ .../GodotTools/Ides/Rider/RiderPathManager.cs | 124 + .../GodotTools/Internals/EditorProgress.cs | 50 + .../GodotTools/Internals/Globals.cs | 39 + .../GodotTools/Internals/GodotSharpDirs.cs | 107 + .../GodotTools/Internals/Internal.cs | 123 + .../GodotTools/Internals/ScriptClassParser.cs | 61 + editor/GodotTools/GodotTools/PlaySettings.cs | 19 + .../GodotTools/Utils/CollectionExtensions.cs | 29 + .../GodotTools/GodotTools/Utils/Directory.cs | 40 + editor/GodotTools/GodotTools/Utils/File.cs | 43 + .../GodotTools/Utils/FsPathUtils.cs | 48 + editor/GodotTools/GodotTools/Utils/OS.cs | 221 ++ .../GodotTools/GodotTools/Utils/User32Dll.cs | 10 + editor/bindings_generator.cpp | 3257 +++++++++++++++ editor/bindings_generator.h | 669 ++++ editor/code_completion.cpp | 249 ++ editor/code_completion.h | 56 + editor/csharp_project.cpp | 68 + editor/csharp_project.h | 42 + editor/editor_internal_calls.cpp | 451 +++ editor/editor_internal_calls.h | 36 + editor/godotsharp_export.cpp | 143 + editor/godotsharp_export.h | 49 + editor/script_class_parser.cpp | 738 ++++ editor/script_class_parser.h | 109 + glue/GodotSharp/.gitignore | 3 + glue/GodotSharp/GodotSharp.sln | 22 + glue/GodotSharp/GodotSharp/Core/AABB.cs | 769 ++++ glue/GodotSharp/GodotSharp/Core/Array.cs | 619 +++ .../Core/Attributes/ExportAttribute.cs | 17 + .../Core/Attributes/GodotMethodAttribute.cs | 17 + .../Core/Attributes/RPCAttributes.cs | 59 + .../Core/Attributes/SignalAttribute.cs | 7 + .../Core/Attributes/ToolAttribute.cs | 7 + glue/GodotSharp/GodotSharp/Core/Basis.cs | 1314 +++++++ glue/GodotSharp/GodotSharp/Core/Color.cs | 1168 ++++++ glue/GodotSharp/GodotSharp/Core/Colors.cs | 310 ++ .../GodotSharp/Core/DebuggingUtils.cs | 89 + glue/GodotSharp/GodotSharp/Core/Dictionary.cs | 626 +++ glue/GodotSharp/GodotSharp/Core/Dispatcher.cs | 13 + .../GodotSharp/Core/DynamicObject.cs | 220 ++ .../Core/Extensions/NodeExtensions.cs | 195 + .../Core/Extensions/ObjectExtensions.cs | 41 + .../Core/Extensions/PackedSceneExtensions.cs | 36 + .../Extensions/ResourceLoaderExtensions.cs | 30 + glue/GodotSharp/GodotSharp/Core/GD.cs | 621 +++ .../Core/GodotSynchronizationContext.cs | 25 + .../GodotSharp/Core/GodotTaskScheduler.cs | 91 + .../GodotSharp/Core/GodotTraceListener.cs | 36 + .../Core/GodotUnhandledExceptionEvent.cs | 17 + .../GodotSharp/Core/Interfaces/IAwaitable.cs | 12 + .../GodotSharp/Core/Interfaces/IAwaiter.cs | 18 + .../Core/Interfaces/ISerializationListener.cs | 8 + .../GodotSharp/Core/MarshalUtils.cs | 154 + glue/GodotSharp/GodotSharp/Core/Mathf.cs | 742 ++++ glue/GodotSharp/GodotSharp/Core/MathfEx.cs | 111 + glue/GodotSharp/GodotSharp/Core/NodePath.cs | 306 ++ .../GodotSharp/GodotSharp/Core/Object.base.cs | 150 + glue/GodotSharp/GodotSharp/Core/Plane.cs | 436 +++ glue/GodotSharp/GodotSharp/Core/Quat.cs | 692 ++++ glue/GodotSharp/GodotSharp/Core/RID.cs | 107 + glue/GodotSharp/GodotSharp/Core/Rect2.cs | 495 +++ .../GodotSharp/Core/SignalAwaiter.cs | 56 + .../GodotSharp/Core/StringExtensions.cs | 1626 ++++++++ glue/GodotSharp/GodotSharp/Core/Transform.cs | 470 +++ .../GodotSharp/GodotSharp/Core/Transform2D.cs | 655 ++++ .../GodotSharp/Core/UnhandledExceptionArgs.cs | 20 + glue/GodotSharp/GodotSharp/Core/Vector2.cs | 1001 +++++ glue/GodotSharp/GodotSharp/Core/Vector3.cs | 1066 +++++ glue/GodotSharp/GodotSharp/GodotSharp.csproj | 66 + .../GodotSharp/Properties/AssemblyInfo.cs | 3 + .../GodotSharpEditor/GodotSharpEditor.csproj | 26 + glue/arguments_vector.h | 67 + glue/base_object_glue.cpp | 252 ++ glue/base_object_glue.h | 71 + glue/collections_glue.cpp | 373 ++ glue/collections_glue.h | 126 + glue/gd_glue.cpp | 311 ++ glue/gd_glue.h | 86 + glue/glue_header.h | 84 + glue/nodepath_glue.cpp | 96 + glue/nodepath_glue.h | 68 + glue/rid_glue.cpp | 61 + glue/rid_glue.h | 53 + glue/string_glue.cpp | 85 + glue/string_glue.h | 56 + godotsharp_defs.h | 48 + godotsharp_dirs.cpp | 350 ++ godotsharp_dirs.h | 73 + icons/icon_c_sharp_script.svg | 5 + mono_gc_handle.cpp | 78 + mono_gc_handle.h | 75 + mono_gd/android_mono_config.h | 43 + mono_gd/gd_mono.cpp | 1405 +++++++ mono_gd/gd_mono.h | 339 ++ mono_gd/gd_mono_assembly.cpp | 496 +++ mono_gd/gd_mono_assembly.h | 131 + mono_gd/gd_mono_cache.cpp | 308 ++ mono_gd/gd_mono_cache.h | 195 + mono_gd/gd_mono_class.cpp | 557 +++ mono_gd/gd_mono_class.h | 161 + mono_gd/gd_mono_field.cpp | 457 +++ mono_gd/gd_mono_field.h | 77 + mono_gd/gd_mono_header.h | 52 + mono_gd/gd_mono_internals.cpp | 142 + mono_gd/gd_mono_internals.h | 52 + mono_gd/gd_mono_log.cpp | 217 + mono_gd/gd_mono_log.h | 71 + mono_gd/gd_mono_marshal.cpp | 1497 +++++++ mono_gd/gd_mono_marshal.h | 468 +++ mono_gd/gd_mono_method.cpp | 291 ++ mono_gd/gd_mono_method.h | 97 + mono_gd/gd_mono_method_thunk.h | 328 ++ mono_gd/gd_mono_property.cpp | 196 + mono_gd/gd_mono_property.h | 80 + mono_gd/gd_mono_utils.cpp | 649 +++ mono_gd/gd_mono_utils.h | 196 + mono_gd/gd_mono_wasm_m2n.cpp | 79 + mono_gd/gd_mono_wasm_m2n.h | 283 ++ mono_gd/i_mono_class_member.h | 70 + mono_gd/managed_type.cpp | 58 + mono_gd/managed_type.h | 58 + mono_gd/support/android_support.cpp | 730 ++++ mono_gd/support/android_support.h | 55 + mono_gd/support/ios_support.h | 51 + mono_gd/support/ios_support.mm | 150 + register_types.cpp | 76 + register_types.h | 32 + signal_awaiter_utils.cpp | 142 + signal_awaiter_utils.h | 70 + utils/macros.h | 105 + utils/mono_reg_utils.cpp | 230 ++ utils/mono_reg_utils.h | 54 + utils/osx_utils.cpp | 58 + utils/osx_utils.h | 42 + utils/path_utils.cpp | 211 + utils/path_utils.h | 64 + utils/string_utils.cpp | 252 ++ utils/string_utils.h | 62 + utils/thread_local.cpp | 107 + utils/thread_local.h | 174 + 229 files changed, 49934 insertions(+) create mode 100644 .editorconfig create mode 100644 .gitignore create mode 100644 LICENSE.txt create mode 100644 SCsub create mode 100644 __init__.py create mode 100644 build_scripts/__init__.py create mode 100644 build_scripts/api_solution_build.py create mode 100644 build_scripts/gen_cs_glue_version.py create mode 100644 build_scripts/godot_tools_build.py create mode 100644 build_scripts/make_android_mono_config.py create mode 100644 build_scripts/mono_android_config.xml create mode 100644 build_scripts/mono_configure.py create mode 100644 build_scripts/mono_reg_utils.py create mode 100644 build_scripts/solution_builder.py create mode 100644 build_scripts/tls_configure.py create mode 100644 class_db_api_json.cpp create mode 100644 class_db_api_json.h create mode 100644 config.py create mode 100644 csharp_script.cpp create mode 100644 csharp_script.h create mode 100644 doc_classes/CSharpScript.xml create mode 100644 doc_classes/GodotSharp.xml create mode 100644 editor/Godot.NET.Sdk/Godot.NET.Sdk.sln create mode 100644 editor/Godot.NET.Sdk/Godot.NET.Sdk/Godot.NET.Sdk.csproj create mode 100644 editor/Godot.NET.Sdk/Godot.NET.Sdk/Godot.NET.Sdk.nuspec create mode 100644 editor/Godot.NET.Sdk/Godot.NET.Sdk/Sdk/Sdk.props create mode 100644 editor/Godot.NET.Sdk/Godot.NET.Sdk/Sdk/Sdk.targets create mode 100644 editor/Godot.NET.Sdk/Godot.NET.Sdk/obj/Debug/netstandard2.0/Godot.NET.Sdk.AssemblyInfo.cs create mode 100644 editor/Godot.NET.Sdk/Godot.NET.Sdk/obj/Debug/netstandard2.0/Godot.NET.Sdk.AssemblyInfoInputs.cache create mode 100644 editor/Godot.NET.Sdk/Godot.NET.Sdk/obj/Debug/netstandard2.0/Godot.NET.Sdk.GeneratedMSBuildEditorConfig.editorconfig create mode 100644 editor/GodotTools/.gitignore create mode 100644 editor/GodotTools/GodotTools.BuildLogger/GodotBuildLogger.cs create mode 100644 editor/GodotTools/GodotTools.BuildLogger/GodotTools.BuildLogger.csproj create mode 100644 editor/GodotTools/GodotTools.Core/FileUtils.cs create mode 100644 editor/GodotTools/GodotTools.Core/GodotTools.Core.csproj create mode 100644 editor/GodotTools/GodotTools.Core/ProcessExtensions.cs create mode 100644 editor/GodotTools/GodotTools.Core/StringExtensions.cs create mode 100644 editor/GodotTools/GodotTools.IdeMessaging.CLI/ForwarderMessageHandler.cs create mode 100644 editor/GodotTools/GodotTools.IdeMessaging.CLI/GodotTools.IdeMessaging.CLI.csproj create mode 100644 editor/GodotTools/GodotTools.IdeMessaging.CLI/Program.cs create mode 100644 editor/GodotTools/GodotTools.IdeMessaging/Client.cs create mode 100644 editor/GodotTools/GodotTools.IdeMessaging/ClientHandshake.cs create mode 100644 editor/GodotTools/GodotTools.IdeMessaging/ClientMessageHandler.cs create mode 100644 editor/GodotTools/GodotTools.IdeMessaging/GodotIdeMetadata.cs create mode 100644 editor/GodotTools/GodotTools.IdeMessaging/GodotTools.IdeMessaging.csproj create mode 100644 editor/GodotTools/GodotTools.IdeMessaging/IHandshake.cs create mode 100644 editor/GodotTools/GodotTools.IdeMessaging/ILogger.cs create mode 100644 editor/GodotTools/GodotTools.IdeMessaging/IMessageHandler.cs create mode 100644 editor/GodotTools/GodotTools.IdeMessaging/Message.cs create mode 100644 editor/GodotTools/GodotTools.IdeMessaging/MessageDecoder.cs create mode 100644 editor/GodotTools/GodotTools.IdeMessaging/Peer.cs create mode 100644 editor/GodotTools/GodotTools.IdeMessaging/Requests/Requests.cs create mode 100644 editor/GodotTools/GodotTools.IdeMessaging/ResponseAwaiter.cs create mode 100644 editor/GodotTools/GodotTools.IdeMessaging/Utils/NotifyAwaiter.cs create mode 100644 editor/GodotTools/GodotTools.IdeMessaging/Utils/SemaphoreExtensions.cs create mode 100644 editor/GodotTools/GodotTools.OpenVisualStudio/GodotTools.OpenVisualStudio.csproj create mode 100644 editor/GodotTools/GodotTools.OpenVisualStudio/Program.cs create mode 100644 editor/GodotTools/GodotTools.ProjectEditor/ApiAssembliesInfo.cs create mode 100644 editor/GodotTools/GodotTools.ProjectEditor/DotNetSolution.cs create mode 100644 editor/GodotTools/GodotTools.ProjectEditor/GodotTools.ProjectEditor.csproj create mode 100644 editor/GodotTools/GodotTools.ProjectEditor/IdentifierUtils.cs create mode 100644 editor/GodotTools/GodotTools.ProjectEditor/MSBuild.exe create mode 100644 editor/GodotTools/GodotTools.ProjectEditor/ProjectExtensions.cs create mode 100644 editor/GodotTools/GodotTools.ProjectEditor/ProjectGenerator.cs create mode 100644 editor/GodotTools/GodotTools.ProjectEditor/ProjectUtils.cs create mode 100644 editor/GodotTools/GodotTools.sln create mode 100644 editor/GodotTools/GodotTools/Build/BuildInfo.cs create mode 100644 editor/GodotTools/GodotTools/Build/BuildManager.cs create mode 100644 editor/GodotTools/GodotTools/Build/BuildOutputView.cs create mode 100644 editor/GodotTools/GodotTools/Build/BuildResult.cs create mode 100644 editor/GodotTools/GodotTools/Build/BuildSystem.cs create mode 100644 editor/GodotTools/GodotTools/Build/BuildTool.cs create mode 100644 editor/GodotTools/GodotTools/Build/MSBuildPanel.cs create mode 100644 editor/GodotTools/GodotTools/Build/MsBuildFinder.cs create mode 100644 editor/GodotTools/GodotTools/CsProjOperations.cs create mode 100644 editor/GodotTools/GodotTools/Export/AotBuilder.cs create mode 100644 editor/GodotTools/GodotTools/Export/AotCache.cs create mode 100644 editor/GodotTools/GodotTools/Export/ExportPlugin.cs create mode 100644 editor/GodotTools/GodotTools/Export/XcodeHelper.cs create mode 100644 editor/GodotTools/GodotTools/ExternalEditorId.cs create mode 100644 editor/GodotTools/GodotTools/GodotSharpEditor.cs create mode 100644 editor/GodotTools/GodotTools/GodotTools.csproj create mode 100644 editor/GodotTools/GodotTools/HotReloadAssemblyWatcher.cs create mode 100644 editor/GodotTools/GodotTools/Ides/GodotIdeManager.cs create mode 100644 editor/GodotTools/GodotTools/Ides/MessagingServer.cs create mode 100644 editor/GodotTools/GodotTools/Ides/MonoDevelop/EditorId.cs create mode 100644 editor/GodotTools/GodotTools/Ides/MonoDevelop/Instance.cs create mode 100644 editor/GodotTools/GodotTools/Ides/Rider/RiderPathLocator.cs create mode 100644 editor/GodotTools/GodotTools/Ides/Rider/RiderPathManager.cs create mode 100644 editor/GodotTools/GodotTools/Internals/EditorProgress.cs create mode 100644 editor/GodotTools/GodotTools/Internals/Globals.cs create mode 100644 editor/GodotTools/GodotTools/Internals/GodotSharpDirs.cs create mode 100644 editor/GodotTools/GodotTools/Internals/Internal.cs create mode 100644 editor/GodotTools/GodotTools/Internals/ScriptClassParser.cs create mode 100644 editor/GodotTools/GodotTools/PlaySettings.cs create mode 100644 editor/GodotTools/GodotTools/Utils/CollectionExtensions.cs create mode 100644 editor/GodotTools/GodotTools/Utils/Directory.cs create mode 100644 editor/GodotTools/GodotTools/Utils/File.cs create mode 100644 editor/GodotTools/GodotTools/Utils/FsPathUtils.cs create mode 100644 editor/GodotTools/GodotTools/Utils/OS.cs create mode 100644 editor/GodotTools/GodotTools/Utils/User32Dll.cs create mode 100644 editor/bindings_generator.cpp create mode 100644 editor/bindings_generator.h create mode 100644 editor/code_completion.cpp create mode 100644 editor/code_completion.h create mode 100644 editor/csharp_project.cpp create mode 100644 editor/csharp_project.h create mode 100644 editor/editor_internal_calls.cpp create mode 100644 editor/editor_internal_calls.h create mode 100644 editor/godotsharp_export.cpp create mode 100644 editor/godotsharp_export.h create mode 100644 editor/script_class_parser.cpp create mode 100644 editor/script_class_parser.h create mode 100644 glue/GodotSharp/.gitignore create mode 100644 glue/GodotSharp/GodotSharp.sln create mode 100644 glue/GodotSharp/GodotSharp/Core/AABB.cs create mode 100644 glue/GodotSharp/GodotSharp/Core/Array.cs create mode 100644 glue/GodotSharp/GodotSharp/Core/Attributes/ExportAttribute.cs create mode 100644 glue/GodotSharp/GodotSharp/Core/Attributes/GodotMethodAttribute.cs create mode 100644 glue/GodotSharp/GodotSharp/Core/Attributes/RPCAttributes.cs create mode 100644 glue/GodotSharp/GodotSharp/Core/Attributes/SignalAttribute.cs create mode 100644 glue/GodotSharp/GodotSharp/Core/Attributes/ToolAttribute.cs create mode 100644 glue/GodotSharp/GodotSharp/Core/Basis.cs create mode 100644 glue/GodotSharp/GodotSharp/Core/Color.cs create mode 100644 glue/GodotSharp/GodotSharp/Core/Colors.cs create mode 100644 glue/GodotSharp/GodotSharp/Core/DebuggingUtils.cs create mode 100644 glue/GodotSharp/GodotSharp/Core/Dictionary.cs create mode 100644 glue/GodotSharp/GodotSharp/Core/Dispatcher.cs create mode 100644 glue/GodotSharp/GodotSharp/Core/DynamicObject.cs create mode 100644 glue/GodotSharp/GodotSharp/Core/Extensions/NodeExtensions.cs create mode 100644 glue/GodotSharp/GodotSharp/Core/Extensions/ObjectExtensions.cs create mode 100644 glue/GodotSharp/GodotSharp/Core/Extensions/PackedSceneExtensions.cs create mode 100644 glue/GodotSharp/GodotSharp/Core/Extensions/ResourceLoaderExtensions.cs create mode 100644 glue/GodotSharp/GodotSharp/Core/GD.cs create mode 100644 glue/GodotSharp/GodotSharp/Core/GodotSynchronizationContext.cs create mode 100644 glue/GodotSharp/GodotSharp/Core/GodotTaskScheduler.cs create mode 100644 glue/GodotSharp/GodotSharp/Core/GodotTraceListener.cs create mode 100644 glue/GodotSharp/GodotSharp/Core/GodotUnhandledExceptionEvent.cs create mode 100644 glue/GodotSharp/GodotSharp/Core/Interfaces/IAwaitable.cs create mode 100644 glue/GodotSharp/GodotSharp/Core/Interfaces/IAwaiter.cs create mode 100644 glue/GodotSharp/GodotSharp/Core/Interfaces/ISerializationListener.cs create mode 100644 glue/GodotSharp/GodotSharp/Core/MarshalUtils.cs create mode 100644 glue/GodotSharp/GodotSharp/Core/Mathf.cs create mode 100644 glue/GodotSharp/GodotSharp/Core/MathfEx.cs create mode 100644 glue/GodotSharp/GodotSharp/Core/NodePath.cs create mode 100644 glue/GodotSharp/GodotSharp/Core/Object.base.cs create mode 100644 glue/GodotSharp/GodotSharp/Core/Plane.cs create mode 100644 glue/GodotSharp/GodotSharp/Core/Quat.cs create mode 100644 glue/GodotSharp/GodotSharp/Core/RID.cs create mode 100644 glue/GodotSharp/GodotSharp/Core/Rect2.cs create mode 100644 glue/GodotSharp/GodotSharp/Core/SignalAwaiter.cs create mode 100644 glue/GodotSharp/GodotSharp/Core/StringExtensions.cs create mode 100644 glue/GodotSharp/GodotSharp/Core/Transform.cs create mode 100644 glue/GodotSharp/GodotSharp/Core/Transform2D.cs create mode 100644 glue/GodotSharp/GodotSharp/Core/UnhandledExceptionArgs.cs create mode 100644 glue/GodotSharp/GodotSharp/Core/Vector2.cs create mode 100644 glue/GodotSharp/GodotSharp/Core/Vector3.cs create mode 100644 glue/GodotSharp/GodotSharp/GodotSharp.csproj create mode 100644 glue/GodotSharp/GodotSharp/Properties/AssemblyInfo.cs create mode 100644 glue/GodotSharp/GodotSharpEditor/GodotSharpEditor.csproj create mode 100644 glue/arguments_vector.h create mode 100644 glue/base_object_glue.cpp create mode 100644 glue/base_object_glue.h create mode 100644 glue/collections_glue.cpp create mode 100644 glue/collections_glue.h create mode 100644 glue/gd_glue.cpp create mode 100644 glue/gd_glue.h create mode 100644 glue/glue_header.h create mode 100644 glue/nodepath_glue.cpp create mode 100644 glue/nodepath_glue.h create mode 100644 glue/rid_glue.cpp create mode 100644 glue/rid_glue.h create mode 100644 glue/string_glue.cpp create mode 100644 glue/string_glue.h create mode 100644 godotsharp_defs.h create mode 100644 godotsharp_dirs.cpp create mode 100644 godotsharp_dirs.h create mode 100644 icons/icon_c_sharp_script.svg create mode 100644 mono_gc_handle.cpp create mode 100644 mono_gc_handle.h create mode 100644 mono_gd/android_mono_config.h create mode 100644 mono_gd/gd_mono.cpp create mode 100644 mono_gd/gd_mono.h create mode 100644 mono_gd/gd_mono_assembly.cpp create mode 100644 mono_gd/gd_mono_assembly.h create mode 100644 mono_gd/gd_mono_cache.cpp create mode 100644 mono_gd/gd_mono_cache.h create mode 100644 mono_gd/gd_mono_class.cpp create mode 100644 mono_gd/gd_mono_class.h create mode 100644 mono_gd/gd_mono_field.cpp create mode 100644 mono_gd/gd_mono_field.h create mode 100644 mono_gd/gd_mono_header.h create mode 100644 mono_gd/gd_mono_internals.cpp create mode 100644 mono_gd/gd_mono_internals.h create mode 100644 mono_gd/gd_mono_log.cpp create mode 100644 mono_gd/gd_mono_log.h create mode 100644 mono_gd/gd_mono_marshal.cpp create mode 100644 mono_gd/gd_mono_marshal.h create mode 100644 mono_gd/gd_mono_method.cpp create mode 100644 mono_gd/gd_mono_method.h create mode 100644 mono_gd/gd_mono_method_thunk.h create mode 100644 mono_gd/gd_mono_property.cpp create mode 100644 mono_gd/gd_mono_property.h create mode 100644 mono_gd/gd_mono_utils.cpp create mode 100644 mono_gd/gd_mono_utils.h create mode 100644 mono_gd/gd_mono_wasm_m2n.cpp create mode 100644 mono_gd/gd_mono_wasm_m2n.h create mode 100644 mono_gd/i_mono_class_member.h create mode 100644 mono_gd/managed_type.cpp create mode 100644 mono_gd/managed_type.h create mode 100644 mono_gd/support/android_support.cpp create mode 100644 mono_gd/support/android_support.h create mode 100644 mono_gd/support/ios_support.h create mode 100644 mono_gd/support/ios_support.mm create mode 100644 register_types.cpp create mode 100644 register_types.h create mode 100644 signal_awaiter_utils.cpp create mode 100644 signal_awaiter_utils.h create mode 100644 utils/macros.h create mode 100644 utils/mono_reg_utils.cpp create mode 100644 utils/mono_reg_utils.h create mode 100644 utils/osx_utils.cpp create mode 100644 utils/osx_utils.h create mode 100644 utils/path_utils.cpp create mode 100644 utils/path_utils.h create mode 100644 utils/string_utils.cpp create mode 100644 utils/string_utils.h create mode 100644 utils/thread_local.cpp create mode 100644 utils/thread_local.h diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..c9dcd77 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,14 @@ +[*.sln] +indent_style = tab + +[*.{csproj,props,targets,nuspec,resx}] +indent_style = space +indent_size = 2 + +[*.cs] +indent_style = space +indent_size = 4 +insert_final_newline = true +trim_trailing_whitespace = true +max_line_length = 120 +csharp_indent_case_contents_when_block = false diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..fa6d00c --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +# Do not ignore solution files inside the mono module. Overrides Godot's global gitignore. +!*.sln diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..c73b002 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,21 @@ +Copyright (c) 2023-present Péter Magyar. +Copyright (c) 2014-2023 Godot Engine contributors (cf. AUTHORS.md). +Copyright (c) 2007-2023 Juan Linietsky, Ariel Manzur. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/SCsub b/SCsub new file mode 100644 index 0000000..93f0f98 --- /dev/null +++ b/SCsub @@ -0,0 +1,64 @@ +#!/usr/bin/env python + +import build_scripts.tls_configure as tls_configure +import build_scripts.mono_configure as mono_configure + +Import("env") +Import("env_modules") + +env_mono = env_modules.Clone() + +if env_mono["tools"]: + # NOTE: It is safe to generate this file here, since this is still executed serially + import build_scripts.gen_cs_glue_version as gen_cs_glue_version + + gen_cs_glue_version.generate_header("glue/GodotSharp", "glue/cs_glue_version.gen.h") + +# Glue sources +if env_mono["mono_glue"]: + env_mono.Append(CPPDEFINES=["MONO_GLUE_ENABLED"]) + + import os.path + + if not os.path.isfile("glue/mono_glue.gen.cpp"): + raise RuntimeError("Mono glue sources not found. Did you forget to run '--generate-mono-glue'?") + +# Configure Thread Local Storage + +conf = Configure(env_mono) +tls_configure.configure(conf) +env_mono = conf.Finish() + +# Configure Mono + +mono_configure.configure(env, env_mono) + +if env_mono["tools"] and env_mono["mono_glue"] and env_mono["build_cil"]: + # Build Godot API solution + import build_scripts.api_solution_build as api_solution_build + + api_sln_cmd = api_solution_build.build(env_mono) + + # Build GodotTools + import build_scripts.godot_tools_build as godot_tools_build + + godot_tools_build.build(env_mono, api_sln_cmd) + +# Add sources + +env_mono.add_source_files(env.modules_sources, "*.cpp") +env_mono.add_source_files(env.modules_sources, "glue/*.cpp") +env_mono.add_source_files(env.modules_sources, "glue/mono_glue.gen.cpp") +env_mono.add_source_files(env.modules_sources, "mono_gd/*.cpp") +env_mono.add_source_files(env.modules_sources, "utils/*.cpp") + +env_mono.add_source_files(env.modules_sources, "mono_gd/support/*.cpp") + +if env["platform"] in ["osx", "iphone"]: + env_mono.add_source_files(env.modules_sources, "mono_gd/support/*.mm") + env_mono.add_source_files(env.modules_sources, "mono_gd/support/*.m") +elif env["platform"] == "android": + env_mono.add_source_files(env.modules_sources, "mono_gd/android_mono_config.gen.cpp") + +if env["tools"]: + env_mono.add_source_files(env.modules_sources, "editor/*.cpp") diff --git a/__init__.py b/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/build_scripts/__init__.py b/build_scripts/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/build_scripts/api_solution_build.py b/build_scripts/api_solution_build.py new file mode 100644 index 0000000..9abac22 --- /dev/null +++ b/build_scripts/api_solution_build.py @@ -0,0 +1,80 @@ +# Build the Godot API solution + +import os + +from SCons.Script import Dir + + +def build_api_solution(source, target, env): + # source and target elements are of type SCons.Node.FS.File, hence why we convert them to str + + module_dir = env["module_dir"] + + solution_path = os.path.join(module_dir, "glue/GodotSharp/GodotSharp.sln") + + build_config = env["solution_build_config"] + + extra_msbuild_args = ["/p:NoWarn=1591"] # Ignore missing documentation warnings + + from .solution_builder import build_solution + + build_solution(env, solution_path, build_config, extra_msbuild_args=extra_msbuild_args) + + # Copy targets + + core_src_dir = os.path.abspath(os.path.join(solution_path, os.pardir, "GodotSharp", "bin", build_config)) + editor_src_dir = os.path.abspath(os.path.join(solution_path, os.pardir, "GodotSharpEditor", "bin", build_config)) + + dst_dir = os.path.abspath(os.path.join(str(target[0]), os.pardir)) + + if not os.path.isdir(dst_dir): + assert not os.path.isfile(dst_dir) + os.makedirs(dst_dir) + + def copy_target(target_path): + from shutil import copy + + filename = os.path.basename(target_path) + + src_path = os.path.join(core_src_dir, filename) + if not os.path.isfile(src_path): + src_path = os.path.join(editor_src_dir, filename) + + copy(src_path, target_path) + + for scons_target in target: + copy_target(str(scons_target)) + + +def build(env_mono): + assert env_mono["tools"] + + target_filenames = [ + "GodotSharp.dll", + "GodotSharp.pdb", + "GodotSharp.xml", + "GodotSharpEditor.dll", + "GodotSharpEditor.pdb", + "GodotSharpEditor.xml", + ] + + depend_cmd = [] + + for build_config in ["Debug", "Release"]: + output_dir = Dir("#bin").abspath + editor_api_dir = os.path.join(output_dir, "GodotSharp", "Api", build_config) + + targets = [os.path.join(editor_api_dir, filename) for filename in target_filenames] + + cmd = env_mono.CommandNoCache( + targets, depend_cmd, build_api_solution, module_dir=os.getcwd(), solution_build_config=build_config + ) + env_mono.AlwaysBuild(cmd) + + # Make the Release build of the API solution depend on the Debug build. + # We do this in order to prevent SCons from building them in parallel, + # which can freak out MSBuild. In many cases, one of the builds would + # hang indefinitely requiring a key to be pressed for it to continue. + depend_cmd = cmd + + return depend_cmd diff --git a/build_scripts/gen_cs_glue_version.py b/build_scripts/gen_cs_glue_version.py new file mode 100644 index 0000000..98bbb4d --- /dev/null +++ b/build_scripts/gen_cs_glue_version.py @@ -0,0 +1,20 @@ +def generate_header(solution_dir, version_header_dst): + import os + + latest_mtime = 0 + for root, dirs, files in os.walk(solution_dir, topdown=True): + dirs[:] = [d for d in dirs if d not in ["Generated"]] # Ignored generated files + files = [f for f in files if f.endswith(".cs")] + for file in files: + filepath = os.path.join(root, file) + mtime = os.path.getmtime(filepath) + latest_mtime = mtime if mtime > latest_mtime else latest_mtime + + glue_version = int(latest_mtime) # The latest modified time will do for now + + with open(version_header_dst, "w") as version_header: + version_header.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n") + version_header.write("#ifndef CS_GLUE_VERSION_H\n") + version_header.write("#define CS_GLUE_VERSION_H\n\n") + version_header.write("#define CS_GLUE_VERSION UINT32_C(" + str(glue_version) + ")\n") + version_header.write("\n#endif // CS_GLUE_VERSION_H\n") diff --git a/build_scripts/godot_tools_build.py b/build_scripts/godot_tools_build.py new file mode 100644 index 0000000..3bbbf29 --- /dev/null +++ b/build_scripts/godot_tools_build.py @@ -0,0 +1,38 @@ +# Build GodotTools solution + +import os + +from SCons.Script import Dir + + +def build_godot_tools(source, target, env): + # source and target elements are of type SCons.Node.FS.File, hence why we convert them to str + + module_dir = env["module_dir"] + + solution_path = os.path.join(module_dir, "editor/GodotTools/GodotTools.sln") + build_config = "Debug" if env["target"] == "debug" else "Release" + + from .solution_builder import build_solution + + extra_msbuild_args = ["/p:GodotPlatform=" + env["platform"]] + + build_solution(env, solution_path, build_config, extra_msbuild_args) + # No need to copy targets. The GodotTools csproj takes care of copying them. + + +def build(env_mono, api_sln_cmd): + assert env_mono["tools"] + + output_dir = Dir("#bin").abspath + editor_tools_dir = os.path.join(output_dir, "GodotSharp", "Tools") + + target_filenames = ["GodotTools.dll"] + + if env_mono["target"] == "debug": + target_filenames += ["GodotTools.pdb"] + + targets = [os.path.join(editor_tools_dir, filename) for filename in target_filenames] + + cmd = env_mono.CommandNoCache(targets, api_sln_cmd, build_godot_tools, module_dir=os.getcwd()) + env_mono.AlwaysBuild(cmd) diff --git a/build_scripts/make_android_mono_config.py b/build_scripts/make_android_mono_config.py new file mode 100644 index 0000000..ef41f92 --- /dev/null +++ b/build_scripts/make_android_mono_config.py @@ -0,0 +1,55 @@ +def generate_compressed_config(config_src, output_dir): + import os.path + from compat import byte_to_str + + # Source file + with open(os.path.join(output_dir, "android_mono_config.gen.cpp"), "w") as cpp: + with open(config_src, "rb") as f: + buf = f.read() + decompr_size = len(buf) + import zlib + + buf = zlib.compress(buf) + compr_size = len(buf) + + bytes_seq_str = "" + for i, buf_idx in enumerate(range(compr_size)): + if i > 0: + bytes_seq_str += ", " + bytes_seq_str += byte_to_str(buf[buf_idx]) + + cpp.write( + """/* THIS FILE IS GENERATED DO NOT EDIT */ +#include "android_mono_config.h" + +#ifdef ANDROID_ENABLED + +#include "core/io/compression.h" +#include "core/pool_vector.h" + +namespace { + +// config +static const int config_compressed_size = %d; +static const int config_uncompressed_size = %d; +static const unsigned char config_compressed_data[] = { %s }; + +} // namespace + +String get_godot_android_mono_config() { + PoolVector data; + data.resize(config_uncompressed_size); + PoolVector::Write w = data.write(); + Compression::decompress(w.ptr(), config_uncompressed_size, config_compressed_data, + config_compressed_size, Compression::MODE_DEFLATE); + String s; + if (s.parse_utf8((const char *)w.ptr(), data.size())) { + ERR_FAIL_V(String()); + } + return s; +} + +#endif // ANDROID_ENABLED +""" + % (compr_size, decompr_size, bytes_seq_str) + ) diff --git a/build_scripts/mono_android_config.xml b/build_scripts/mono_android_config.xml new file mode 100644 index 0000000..e79670a --- /dev/null +++ b/build_scripts/mono_android_config.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/build_scripts/mono_configure.py b/build_scripts/mono_configure.py new file mode 100644 index 0000000..de29e75 --- /dev/null +++ b/build_scripts/mono_configure.py @@ -0,0 +1,585 @@ +import os +import os.path +import sys +import subprocess + +from SCons.Script import Dir, Environment + +if os.name == "nt": + from . import mono_reg_utils as monoreg + + +android_arch_dirs = {"armv7": "armeabi-v7a", "arm64v8": "arm64-v8a", "x86": "x86", "x86_64": "x86_64"} + + +def get_android_out_dir(env): + return os.path.join( + Dir("#platform/android/java/lib/libs").abspath, + "release" if env["target"] == "release" else "debug", + android_arch_dirs[env["android_arch"]], + ) + + +def find_name_in_dir_files(directory, names, prefixes=[""], extensions=[""]): + for extension in extensions: + if extension and not extension.startswith("."): + extension = "." + extension + for prefix in prefixes: + for curname in names: + if os.path.isfile(os.path.join(directory, prefix + curname + extension)): + return curname + return "" + + +def find_file_in_dir(directory, names, prefixes=[""], extensions=[""]): + for extension in extensions: + if extension and not extension.startswith("."): + extension = "." + extension + for prefix in prefixes: + for curname in names: + filename = prefix + curname + extension + if os.path.isfile(os.path.join(directory, filename)): + return filename + return "" + + +def copy_file(src_dir, dst_dir, src_name, dst_name=""): + from shutil import copy + + src_path = os.path.join(Dir(src_dir).abspath, src_name) + dst_dir = Dir(dst_dir).abspath + + if not os.path.isdir(dst_dir): + os.makedirs(dst_dir) + + if dst_name: + copy(src_path, os.path.join(dst_dir, dst_name)) + else: + copy(src_path, dst_dir) + + +def is_desktop(platform): + return platform in ["windows", "osx", "x11", "server", "uwp", "haiku"] + + +def is_unix_like(platform): + return platform in ["osx", "x11", "server", "android", "haiku", "iphone"] + + +def module_supports_tools_on(platform): + return platform not in ["android", "javascript", "iphone"] + + +def find_wasm_src_dir(mono_root): + hint_dirs = [ + os.path.join(mono_root, "src"), + os.path.join(mono_root, "../src"), + ] + for hint_dir in hint_dirs: + if os.path.isfile(os.path.join(hint_dir, "driver.c")): + return hint_dir + return "" + + +def configure(env, env_mono): + bits = env["bits"] + is_android = env["platform"] == "android" + is_javascript = env["platform"] == "javascript" + is_ios = env["platform"] == "iphone" + is_ios_sim = is_ios and env["ios_simulator"] + + tools_enabled = env["tools"] + mono_static = env["mono_static"] + copy_mono_root = env["copy_mono_root"] + + mono_prefix = env["mono_prefix"] + mono_bcl = env["mono_bcl"] + + mono_lib_names = ["mono-2.0-sgen", "monosgen-2.0"] + + if is_android and not env["android_arch"] in android_arch_dirs: + raise RuntimeError("This module does not support the specified 'android_arch': " + env["android_arch"]) + + if tools_enabled and not module_supports_tools_on(env["platform"]): + # TODO: + # Android: We have to add the data directory to the apk, concretely the Api and Tools folders. + raise RuntimeError("This module does not currently support building for this platform with tools enabled") + + if is_android and mono_static: + # FIXME: When static linking and doing something that requires libmono-native, we get a dlopen error as 'libmono-native' + # seems to depend on 'libmonosgen-2.0'. Could be fixed by re-directing to '__Internal' with a dllmap or in the dlopen hook. + raise RuntimeError("Statically linking Mono is not currently supported for this platform") + + if not mono_static and (is_javascript or is_ios): + raise RuntimeError("Dynamically linking Mono is not currently supported for this platform") + + if not mono_prefix and (os.getenv("MONO32_PREFIX") or os.getenv("MONO64_PREFIX")): + print( + "WARNING: The environment variables 'MONO32_PREFIX' and 'MONO64_PREFIX' are deprecated; use the 'mono_prefix' SCons parameter instead" + ) + + # Although we don't support building with tools for any platform where we currently use static AOT, + # if these are supported in the future, we won't be using static AOT for them as that would be + # too restrictive for the editor. These builds would probably be made to only use the interpreter. + mono_aot_static = (is_ios and not is_ios_sim) and not env["tools"] + + # Static AOT is only supported on the root domain + mono_single_appdomain = mono_aot_static + + if mono_single_appdomain: + env_mono.Append(CPPDEFINES=["GD_MONO_SINGLE_APPDOMAIN"]) + + if (env["tools"] or env["target"] != "release") and not mono_single_appdomain: + env_mono.Append(CPPDEFINES=["GD_MONO_HOT_RELOAD"]) + + if env["platform"] == "windows": + mono_root = mono_prefix + + if not mono_root and os.name == "nt": + mono_root = monoreg.find_mono_root_dir(bits) + + if not mono_root: + raise RuntimeError( + "Mono installation directory not found; specify one manually with the 'mono_prefix' SCons parameter" + ) + + print("Found Mono root directory: " + mono_root) + + mono_lib_path = os.path.join(mono_root, "lib") + + env.Append(LIBPATH=mono_lib_path) + env_mono.Prepend(CPPPATH=os.path.join(mono_root, "include", "mono-2.0")) + + lib_suffixes = [".lib"] + + if not env.msvc: + # MingW supports both '.a' and '.lib' + lib_suffixes.insert(0, ".a") + + if mono_static: + if env.msvc: + mono_static_lib_name = "libmono-static-sgen" + else: + mono_static_lib_name = "libmonosgen-2.0" + + mono_static_lib_file = find_file_in_dir(mono_lib_path, [mono_static_lib_name], extensions=lib_suffixes) + + if not mono_static_lib_file: + raise RuntimeError("Could not find static mono library in: " + mono_lib_path) + + if env.msvc: + env.Append(LINKFLAGS=mono_static_lib_file) + + env.Append(LINKFLAGS="Mincore.lib") + env.Append(LINKFLAGS="msvcrt.lib") + env.Append(LINKFLAGS="LIBCMT.lib") + env.Append(LINKFLAGS="Psapi.lib") + else: + mono_static_lib_file_path = os.path.join(mono_lib_path, mono_static_lib_file) + env.Append(LINKFLAGS=["-Wl,-whole-archive", mono_static_lib_file_path, "-Wl,-no-whole-archive"]) + + env.Append(LIBS=["psapi"]) + env.Append(LIBS=["version"]) + else: + mono_lib_name = find_name_in_dir_files( + mono_lib_path, mono_lib_names, prefixes=["", "lib"], extensions=lib_suffixes + ) + + if not mono_lib_name: + raise RuntimeError("Could not find mono library in: " + mono_lib_path) + + if env.msvc: + env.Append(LINKFLAGS=mono_lib_name + ".lib") + else: + env.Append(LIBS=[mono_lib_name]) + + mono_bin_path = os.path.join(mono_root, "bin") + + mono_dll_file = find_file_in_dir(mono_bin_path, mono_lib_names, prefixes=["", "lib"], extensions=[".dll"]) + + if not mono_dll_file: + raise RuntimeError("Could not find mono shared library in: " + mono_bin_path) + + copy_file(mono_bin_path, "#bin", mono_dll_file) + else: + is_apple = env["platform"] in ["osx", "iphone"] + is_macos = is_apple and not is_ios + + sharedlib_ext = ".dylib" if is_apple else ".so" + + mono_root = mono_prefix + mono_lib_path = "" + mono_so_file = "" + + if not mono_root and (is_android or is_javascript or is_ios): + raise RuntimeError( + "Mono installation directory not found; specify one manually with the 'mono_prefix' SCons parameter" + ) + + if not mono_root and is_macos: + # Try with some known directories under OSX + hint_dirs = ["/Library/Frameworks/Mono.framework/Versions/Current", "/usr/local/var/homebrew/linked/mono"] + for hint_dir in hint_dirs: + if os.path.isdir(hint_dir): + mono_root = hint_dir + break + + # We can't use pkg-config to link mono statically, + # but we can still use it to find the mono root directory + if not mono_root and mono_static: + mono_root = pkgconfig_try_find_mono_root(mono_lib_names, sharedlib_ext) + if not mono_root: + raise RuntimeError( + "Building with mono_static=yes, but failed to find the mono prefix with pkg-config; " + + "specify one manually with the 'mono_prefix' SCons parameter" + ) + + if is_ios and not is_ios_sim: + env_mono.Append(CPPDEFINES=["IOS_DEVICE"]) + + if mono_root: + print("Found Mono root directory: " + mono_root) + + mono_lib_path = os.path.join(mono_root, "lib") + + env.Append(LIBPATH=[mono_lib_path]) + env_mono.Prepend(CPPPATH=os.path.join(mono_root, "include", "mono-2.0")) + + mono_lib = find_name_in_dir_files(mono_lib_path, mono_lib_names, prefixes=["lib"], extensions=[".a"]) + + if not mono_lib: + raise RuntimeError("Could not find mono library in: " + mono_lib_path) + + env_mono.Append(CPPDEFINES=["_REENTRANT"]) + + if mono_static: + if not is_javascript: + env.Append(LINKFLAGS=["-rdynamic"]) + + mono_lib_file = os.path.join(mono_lib_path, "lib" + mono_lib + ".a") + + if is_apple: + if is_macos: + env.Append(LINKFLAGS=["-Wl,-force_load," + mono_lib_file]) + else: + arch = env["arch"] + + def copy_mono_lib(libname_wo_ext): + if is_ios_sim: + copy_file( + mono_lib_path, + "#bin", + libname_wo_ext + ".a", + "%s.iphone.%s.simulator.a" % (libname_wo_ext, arch), + ) + else: + copy_file( + mono_lib_path, + "#bin", + libname_wo_ext + ".a", + "%s.iphone.%s.a" % (libname_wo_ext, arch), + ) + + # Copy Mono libraries to the output folder. These are meant to be bundled with + # the export templates and added to the Xcode project when exporting a game. + copy_mono_lib("lib" + mono_lib) + copy_mono_lib("libmono-native") + copy_mono_lib("libmono-profiler-log") + + if not is_ios_sim: + copy_mono_lib("libmono-ee-interp") + copy_mono_lib("libmono-icall-table") + copy_mono_lib("libmono-ilgen") + else: + assert is_desktop(env["platform"]) or is_android or is_javascript + env.Append(LINKFLAGS=["-Wl,-whole-archive", mono_lib_file, "-Wl,-no-whole-archive"]) + + if is_javascript: + env.Append(LIBS=["mono-icall-table", "mono-native", "mono-ilgen", "mono-ee-interp"]) + + wasm_src_dir = os.path.join(mono_root, "src") + if not os.path.isdir(wasm_src_dir): + raise RuntimeError("Could not find mono wasm src directory") + + # Ideally this should be defined only for 'driver.c', but I can't fight scons for another 2 hours + env_mono.Append(CPPDEFINES=["CORE_BINDINGS"]) + + env_mono.add_source_files( + env.modules_sources, + [ + os.path.join(wasm_src_dir, "driver.c"), + os.path.join(wasm_src_dir, "zlib-helper.c"), + os.path.join(wasm_src_dir, "corebindings.c"), + ], + ) + + env.Append( + LINKFLAGS=[ + "--js-library", + os.path.join(wasm_src_dir, "library_mono.js"), + "--js-library", + os.path.join(wasm_src_dir, "binding_support.js"), + "--js-library", + os.path.join(wasm_src_dir, "dotnet_support.js"), + ] + ) + else: + env.Append(LIBS=[mono_lib]) + + if is_macos: + env.Append(LIBS=["iconv", "pthread"]) + elif is_android: + pass # Nothing + elif is_ios: + pass # Nothing, linking is delegated to the exported Xcode project + elif is_javascript: + env.Append(LIBS=["m", "rt", "dl", "pthread"]) + else: + env.Append(LIBS=["m", "rt", "dl", "pthread"]) + + if not mono_static: + mono_so_file = find_file_in_dir( + mono_lib_path, mono_lib_names, prefixes=["lib"], extensions=[sharedlib_ext] + ) + + if not mono_so_file: + raise RuntimeError("Could not find mono shared library in: " + mono_lib_path) + else: + assert not mono_static + + # TODO: Add option to force using pkg-config + print("Mono root directory not found. Using pkg-config instead") + + env.ParseConfig("pkg-config monosgen-2 --libs") + env_mono.ParseConfig("pkg-config monosgen-2 --cflags") + + tmpenv = Environment() + tmpenv.AppendENVPath("PKG_CONFIG_PATH", os.getenv("PKG_CONFIG_PATH")) + tmpenv.ParseConfig("pkg-config monosgen-2 --libs-only-L") + + for hint_dir in tmpenv["LIBPATH"]: + file_found = find_file_in_dir(hint_dir, mono_lib_names, prefixes=["lib"], extensions=[sharedlib_ext]) + if file_found: + mono_lib_path = hint_dir + mono_so_file = file_found + break + + if not mono_so_file: + raise RuntimeError("Could not find mono shared library in: " + str(tmpenv["LIBPATH"])) + + if not mono_static: + libs_output_dir = get_android_out_dir(env) if is_android else "#bin" + copy_file(mono_lib_path, libs_output_dir, mono_so_file) + + if not tools_enabled: + if is_desktop(env["platform"]): + if not mono_root: + mono_root = ( + subprocess.check_output(["pkg-config", "mono-2", "--variable=prefix"]).decode("utf8").strip() + ) + + make_template_dir(env, mono_root) + elif is_android: + # Compress Android Mono Config + from . import make_android_mono_config + + module_dir = os.getcwd() + config_file_path = os.path.join(module_dir, "build_scripts", "mono_android_config.xml") + make_android_mono_config.generate_compressed_config(config_file_path, "mono_gd/") + + # Copy the required shared libraries + copy_mono_shared_libs(env, mono_root, None) + elif is_javascript: + pass # No data directory for this platform + elif is_ios: + pass # No data directory for this platform + + if copy_mono_root: + if not mono_root: + mono_root = subprocess.check_output(["pkg-config", "mono-2", "--variable=prefix"]).decode("utf8").strip() + + if tools_enabled: + # Only supported for editor builds. + copy_mono_root_files(env, mono_root, mono_bcl) + + +def make_template_dir(env, mono_root): + from shutil import rmtree + + platform = env["platform"] + target = env["target"] + + template_dir_name = "" + + assert is_desktop(platform) + + template_dir_name = "data.mono.%s.%s.%s" % (platform, env["bits"], target) + + output_dir = Dir("#bin").abspath + template_dir = os.path.join(output_dir, template_dir_name) + + template_mono_root_dir = os.path.join(template_dir, "Mono") + + if os.path.isdir(template_mono_root_dir): + rmtree(template_mono_root_dir) # Clean first + + # Copy etc/mono/ + + template_mono_config_dir = os.path.join(template_mono_root_dir, "etc", "mono") + copy_mono_etc_dir(mono_root, template_mono_config_dir, platform) + + # Copy the required shared libraries + + copy_mono_shared_libs(env, mono_root, template_mono_root_dir) + + +def copy_mono_root_files(env, mono_root, mono_bcl): + from glob import glob + from shutil import copy + from shutil import rmtree + + if not mono_root: + raise RuntimeError("Mono installation directory not found") + + output_dir = Dir("#bin").abspath + editor_mono_root_dir = os.path.join(output_dir, "GodotSharp", "Mono") + + if os.path.isdir(editor_mono_root_dir): + rmtree(editor_mono_root_dir) # Clean first + + # Copy etc/mono/ + + editor_mono_config_dir = os.path.join(editor_mono_root_dir, "etc", "mono") + copy_mono_etc_dir(mono_root, editor_mono_config_dir, env["platform"]) + + # Copy the required shared libraries + + copy_mono_shared_libs(env, mono_root, editor_mono_root_dir) + + # Copy framework assemblies + + mono_framework_dir = mono_bcl or os.path.join(mono_root, "lib", "mono", "4.5") + mono_framework_facades_dir = os.path.join(mono_framework_dir, "Facades") + + editor_mono_framework_dir = os.path.join(editor_mono_root_dir, "lib", "mono", "4.5") + editor_mono_framework_facades_dir = os.path.join(editor_mono_framework_dir, "Facades") + + if not os.path.isdir(editor_mono_framework_dir): + os.makedirs(editor_mono_framework_dir) + if not os.path.isdir(editor_mono_framework_facades_dir): + os.makedirs(editor_mono_framework_facades_dir) + + for assembly in glob(os.path.join(mono_framework_dir, "*.dll")): + copy(assembly, editor_mono_framework_dir) + for assembly in glob(os.path.join(mono_framework_facades_dir, "*.dll")): + copy(assembly, editor_mono_framework_facades_dir) + + +def copy_mono_etc_dir(mono_root, target_mono_config_dir, platform): + from distutils.dir_util import copy_tree + from glob import glob + from shutil import copy + + if not os.path.isdir(target_mono_config_dir): + os.makedirs(target_mono_config_dir) + + mono_etc_dir = os.path.join(mono_root, "etc", "mono") + if not os.path.isdir(mono_etc_dir): + mono_etc_dir = "" + etc_hint_dirs = [] + if platform != "windows": + etc_hint_dirs += ["/etc/mono", "/usr/local/etc/mono"] + if "MONO_CFG_DIR" in os.environ: + etc_hint_dirs += [os.path.join(os.environ["MONO_CFG_DIR"], "mono")] + for etc_hint_dir in etc_hint_dirs: + if os.path.isdir(etc_hint_dir): + mono_etc_dir = etc_hint_dir + break + if not mono_etc_dir: + raise RuntimeError("Mono installation etc directory not found") + + copy_tree(os.path.join(mono_etc_dir, "2.0"), os.path.join(target_mono_config_dir, "2.0")) + copy_tree(os.path.join(mono_etc_dir, "4.0"), os.path.join(target_mono_config_dir, "4.0")) + copy_tree(os.path.join(mono_etc_dir, "4.5"), os.path.join(target_mono_config_dir, "4.5")) + if os.path.isdir(os.path.join(mono_etc_dir, "mconfig")): + copy_tree(os.path.join(mono_etc_dir, "mconfig"), os.path.join(target_mono_config_dir, "mconfig")) + + for file in glob(os.path.join(mono_etc_dir, "*")): + if os.path.isfile(file): + copy(file, target_mono_config_dir) + + +def copy_mono_shared_libs(env, mono_root, target_mono_root_dir): + from shutil import copy + + def copy_if_exists(src, dst): + if os.path.isfile(src): + copy(src, dst) + + platform = env["platform"] + + if platform == "windows": + src_mono_bin_dir = os.path.join(mono_root, "bin") + target_mono_bin_dir = os.path.join(target_mono_root_dir, "bin") + + if not os.path.isdir(target_mono_bin_dir): + os.makedirs(target_mono_bin_dir) + + mono_posix_helper_file = find_file_in_dir( + src_mono_bin_dir, ["MonoPosixHelper"], prefixes=["", "lib"], extensions=[".dll"] + ) + copy( + os.path.join(src_mono_bin_dir, mono_posix_helper_file), + os.path.join(target_mono_bin_dir, "MonoPosixHelper.dll"), + ) + + # For newer versions + btls_dll_path = os.path.join(src_mono_bin_dir, "libmono-btls-shared.dll") + if os.path.isfile(btls_dll_path): + copy(btls_dll_path, target_mono_bin_dir) + else: + target_mono_lib_dir = ( + get_android_out_dir(env) if platform == "android" else os.path.join(target_mono_root_dir, "lib") + ) + + if not os.path.isdir(target_mono_lib_dir): + os.makedirs(target_mono_lib_dir) + + src_mono_lib_dir = os.path.join(mono_root, "lib") + + lib_file_names = [] + if platform == "osx": + lib_file_names = [lib_name + ".dylib" for lib_name in ["libmono-btls-shared", "libMonoPosixHelper"]] + + if os.path.isfile(os.path.join(src_mono_lib_dir, "libmono-native-compat.dylib")): + lib_file_names += ["libmono-native-compat.dylib"] + else: + lib_file_names += ["libmono-native.dylib"] + elif is_unix_like(platform): + lib_file_names = [ + lib_name + ".so" + for lib_name in [ + "libmono-btls-shared", + "libmono-ee-interp", + "libmono-native", + "libMonoPosixHelper", + "libmono-profiler-aot", + "libmono-profiler-coverage", + "libmono-profiler-log", + "libMonoSupportW", + ] + ] + + for lib_file_name in lib_file_names: + copy_if_exists(os.path.join(src_mono_lib_dir, lib_file_name), target_mono_lib_dir) + + +def pkgconfig_try_find_mono_root(mono_lib_names, sharedlib_ext): + tmpenv = Environment() + tmpenv.AppendENVPath("PKG_CONFIG_PATH", os.getenv("PKG_CONFIG_PATH")) + tmpenv.ParseConfig("pkg-config monosgen-2 --libs-only-L") + for hint_dir in tmpenv["LIBPATH"]: + name_found = find_name_in_dir_files(hint_dir, mono_lib_names, prefixes=["lib"], extensions=[sharedlib_ext]) + if name_found and os.path.isdir(os.path.join(hint_dir, "..", "include", "mono-2.0")): + return os.path.join(hint_dir, "..") + return "" diff --git a/build_scripts/mono_reg_utils.py b/build_scripts/mono_reg_utils.py new file mode 100644 index 0000000..596129c --- /dev/null +++ b/build_scripts/mono_reg_utils.py @@ -0,0 +1,119 @@ +import os +import platform + +from compat import decode_utf8 + +if os.name == "nt": + import sys + + if sys.version_info < (3,): + import _winreg as winreg + else: + import winreg + + +def _reg_open_key(key, subkey): + try: + return winreg.OpenKey(key, subkey) + except (WindowsError, OSError): + if platform.architecture()[0] == "32bit": + bitness_sam = winreg.KEY_WOW64_64KEY + else: + bitness_sam = winreg.KEY_WOW64_32KEY + return winreg.OpenKey(key, subkey, 0, winreg.KEY_READ | bitness_sam) + + +def _reg_open_key_bits(key, subkey, bits): + sam = winreg.KEY_READ + + if platform.architecture()[0] == "32bit": + if bits == "64": + # Force 32bit process to search in 64bit registry + sam |= winreg.KEY_WOW64_64KEY + else: + if bits == "32": + # Force 64bit process to search in 32bit registry + sam |= winreg.KEY_WOW64_32KEY + + return winreg.OpenKey(key, subkey, 0, sam) + + +def _find_mono_in_reg(subkey, bits): + try: + with _reg_open_key_bits(winreg.HKEY_LOCAL_MACHINE, subkey, bits) as hKey: + value = winreg.QueryValueEx(hKey, "SdkInstallRoot")[0] + return value + except (WindowsError, OSError): + return None + + +def _find_mono_in_reg_old(subkey, bits): + try: + with _reg_open_key_bits(winreg.HKEY_LOCAL_MACHINE, subkey, bits) as hKey: + default_clr = winreg.QueryValueEx(hKey, "DefaultCLR")[0] + if default_clr: + return _find_mono_in_reg(subkey + "\\" + default_clr, bits) + return None + except (WindowsError, EnvironmentError): + return None + + +def find_mono_root_dir(bits): + root_dir = _find_mono_in_reg(r"SOFTWARE\Mono", bits) + if root_dir is not None: + return str(root_dir) + root_dir = _find_mono_in_reg_old(r"SOFTWARE\Novell\Mono", bits) + if root_dir is not None: + return str(root_dir) + return "" + + +def find_msbuild_tools_path_reg(): + import subprocess + + vswhere = os.getenv("PROGRAMFILES(X86)") + if not vswhere: + vswhere = os.getenv("PROGRAMFILES") + vswhere += r"\Microsoft Visual Studio\Installer\vswhere.exe" + + vswhere_args = ["-latest", "-products", "*", "-requires", "Microsoft.Component.MSBuild"] + + try: + lines = subprocess.check_output([vswhere] + vswhere_args).splitlines() + + for line in lines: + parts = decode_utf8(line).split(":", 1) + + if len(parts) < 2 or parts[0] != "installationPath": + continue + + val = parts[1].strip() + + if not val: + raise ValueError("Value of `installationPath` entry is empty") + + # Since VS2019, the directory is simply named "Current" + msbuild_dir = os.path.join(val, "MSBuild\\Current\\Bin") + if os.path.isdir(msbuild_dir): + return msbuild_dir + + # Directory name "15.0" is used in VS 2017 + return os.path.join(val, "MSBuild\\15.0\\Bin") + + raise ValueError("Cannot find `installationPath` entry") + except ValueError as e: + print("Error reading output from vswhere: " + e.message) + except subprocess.CalledProcessError as e: + print(e.output) + except OSError as e: + print(e) + + # Try to find 14.0 in the Registry + + try: + subkey = r"SOFTWARE\Microsoft\MSBuild\ToolsVersions\14.0" + with _reg_open_key(winreg.HKEY_LOCAL_MACHINE, subkey) as hKey: + value = winreg.QueryValueEx(hKey, "MSBuildToolsPath")[0] + return value + except (WindowsError, OSError): + return "" diff --git a/build_scripts/solution_builder.py b/build_scripts/solution_builder.py new file mode 100644 index 0000000..03f4e57 --- /dev/null +++ b/build_scripts/solution_builder.py @@ -0,0 +1,148 @@ +import os + + +verbose = False + + +def find_dotnet_cli(): + import os.path + + if os.name == "nt": + windows_exts = os.environ["PATHEXT"] + windows_exts = windows_exts.split(os.pathsep) if windows_exts else [] + + for hint_dir in os.environ["PATH"].split(os.pathsep): + hint_dir = hint_dir.strip('"') + hint_path = os.path.join(hint_dir, "dotnet") + if os.path.isfile(hint_path) and os.access(hint_path, os.X_OK): + return hint_path + if os.path.isfile(hint_path + ".exe") and os.access(hint_path + ".exe", os.X_OK): + return hint_path + ".exe" + else: + for hint_dir in os.environ["PATH"].split(os.pathsep): + hint_dir = hint_dir.strip('"') + hint_path = os.path.join(hint_dir, "dotnet") + if os.path.isfile(hint_path) and os.access(hint_path, os.X_OK): + return hint_path + + +def find_msbuild_unix(): + import os.path + import sys + + hint_dirs = [] + if sys.platform == "darwin": + hint_dirs[:0] = [ + "/Library/Frameworks/Mono.framework/Versions/Current/bin", + "/usr/local/var/homebrew/linked/mono/bin", + ] + + for hint_dir in hint_dirs: + hint_path = os.path.join(hint_dir, "msbuild") + if os.path.isfile(hint_path): + return hint_path + elif os.path.isfile(hint_path + ".exe"): + return hint_path + ".exe" + + for hint_dir in os.environ["PATH"].split(os.pathsep): + hint_dir = hint_dir.strip('"') + hint_path = os.path.join(hint_dir, "msbuild") + if os.path.isfile(hint_path) and os.access(hint_path, os.X_OK): + return hint_path + if os.path.isfile(hint_path + ".exe") and os.access(hint_path + ".exe", os.X_OK): + return hint_path + ".exe" + + return None + + +def find_msbuild_windows(env): + from .mono_reg_utils import find_mono_root_dir, find_msbuild_tools_path_reg + + mono_root = env["mono_prefix"] or find_mono_root_dir(env["bits"]) + + if not mono_root: + raise RuntimeError("Cannot find mono root directory") + + mono_bin_dir = os.path.join(mono_root, "bin") + msbuild_mono = os.path.join(mono_bin_dir, "msbuild.bat") + + msbuild_tools_path = find_msbuild_tools_path_reg() + + if msbuild_tools_path: + return (os.path.join(msbuild_tools_path, "MSBuild.exe"), {}) + + if os.path.isfile(msbuild_mono): + # The (Csc/Vbc/Fsc)ToolExe environment variables are required when + # building with Mono's MSBuild. They must point to the batch files + # in Mono's bin directory to make sure they are executed with Mono. + mono_msbuild_env = { + "CscToolExe": os.path.join(mono_bin_dir, "csc.bat"), + "VbcToolExe": os.path.join(mono_bin_dir, "vbc.bat"), + "FscToolExe": os.path.join(mono_bin_dir, "fsharpc.bat"), + } + return (msbuild_mono, mono_msbuild_env) + + return None + + +def run_command(command, args, env_override=None, name=None): + def cmd_args_to_str(cmd_args): + return " ".join([arg if not " " in arg else '"%s"' % arg for arg in cmd_args]) + + args = [command] + args + + if name is None: + name = os.path.basename(command) + + if verbose: + print("Running '%s': %s" % (name, cmd_args_to_str(args))) + + import subprocess + + try: + if env_override is None: + subprocess.check_call(args) + else: + subprocess.check_call(args, env=env_override) + except subprocess.CalledProcessError as e: + raise RuntimeError("'%s' exited with error code: %s" % (name, e.returncode)) + + +def build_solution(env, solution_path, build_config, extra_msbuild_args=[]): + global verbose + verbose = env["verbose"] + + msbuild_env = os.environ.copy() + + # Needed when running from Developer Command Prompt for VS + if "PLATFORM" in msbuild_env: + del msbuild_env["PLATFORM"] + + msbuild_args = [] + + dotnet_cli = find_dotnet_cli() + + if dotnet_cli: + msbuild_path = dotnet_cli + msbuild_args += ["msbuild"] # `dotnet msbuild` command + else: + # Find MSBuild + if os.name == "nt": + msbuild_info = find_msbuild_windows(env) + if msbuild_info is None: + raise RuntimeError("Cannot find MSBuild executable") + msbuild_path = msbuild_info[0] + msbuild_env.update(msbuild_info[1]) + else: + msbuild_path = find_msbuild_unix() + if msbuild_path is None: + raise RuntimeError("Cannot find MSBuild executable") + + print("MSBuild path: " + msbuild_path) + + # Build solution + + msbuild_args += [solution_path, "/restore", "/t:Build", "/p:Configuration=" + build_config] + msbuild_args += extra_msbuild_args + + run_command(msbuild_path, msbuild_args, env_override=msbuild_env, name="msbuild") diff --git a/build_scripts/tls_configure.py b/build_scripts/tls_configure.py new file mode 100644 index 0000000..522be4b --- /dev/null +++ b/build_scripts/tls_configure.py @@ -0,0 +1,37 @@ +from __future__ import print_function + + +def supported(result): + return "supported" if result else "not supported" + + +def check_cxx11_thread_local(conf): + print("Checking for `thread_local` support...", end=" ") + result = conf.TryCompile("thread_local int foo = 0; int main() { return foo; }", ".cpp") + print(supported(result)) + return bool(result) + + +def check_declspec_thread(conf): + print("Checking for `__declspec(thread)` support...", end=" ") + result = conf.TryCompile("__declspec(thread) int foo = 0; int main() { return foo; }", ".cpp") + print(supported(result)) + return bool(result) + + +def check_gcc___thread(conf): + print("Checking for `__thread` support...", end=" ") + result = conf.TryCompile("__thread int foo = 0; int main() { return foo; }", ".cpp") + print(supported(result)) + return bool(result) + + +def configure(conf): + if check_cxx11_thread_local(conf): + conf.env.Append(CPPDEFINES=["HAVE_CXX11_THREAD_LOCAL"]) + else: + if conf.env.msvc: + if check_declspec_thread(conf): + conf.env.Append(CPPDEFINES=["HAVE_DECLSPEC_THREAD"]) + elif check_gcc___thread(conf): + conf.env.Append(CPPDEFINES=["HAVE_GCC___THREAD"]) diff --git a/class_db_api_json.cpp b/class_db_api_json.cpp new file mode 100644 index 0000000..727d79f --- /dev/null +++ b/class_db_api_json.cpp @@ -0,0 +1,247 @@ +/**************************************************************************/ +/* class_db_api_json.cpp */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#include "class_db_api_json.h" + +#ifdef DEBUG_METHODS_ENABLED + +#include "core/io/json.h" +#include "core/os/file_access.h" +#include "core/project_settings.h" +#include "core/version.h" + +void class_db_api_to_json(const String &p_output_file, ClassDB::APIType p_api) { + Dictionary classes_dict; + + List names; + + const StringName *k = NULL; + + while ((k = ClassDB::classes.next(k))) { + names.push_back(*k); + } + //must be alphabetically sorted for hash to compute + names.sort_custom(); + + for (List::Element *E = names.front(); E; E = E->next()) { + ClassDB::ClassInfo *t = ClassDB::classes.getptr(E->get()); + ERR_FAIL_COND(!t); + if (t->api != p_api || !t->exposed) + continue; + + Dictionary class_dict; + classes_dict[t->name] = class_dict; + + class_dict["inherits"] = t->inherits; + + { //methods + + List snames; + + k = NULL; + + while ((k = t->method_map.next(k))) { + String name = k->operator String(); + + ERR_CONTINUE(name.empty()); + + if (name[0] == '_') + continue; // Ignore non-virtual methods that start with an underscore + + snames.push_back(*k); + } + + snames.sort_custom(); + + Array methods; + + for (List::Element *F = snames.front(); F; F = F->next()) { + Dictionary method_dict; + methods.push_back(method_dict); + + MethodBind *mb = t->method_map[F->get()]; + method_dict["name"] = mb->get_name(); + method_dict["argument_count"] = mb->get_argument_count(); + method_dict["return_type"] = mb->get_argument_type(-1); + + Array arguments; + method_dict["arguments"] = arguments; + + for (int i = 0; i < mb->get_argument_count(); i++) { + Dictionary argument_dict; + arguments.push_back(argument_dict); + const PropertyInfo info = mb->get_argument_info(i); + argument_dict["type"] = info.type; + argument_dict["name"] = info.name; + argument_dict["hint"] = info.hint; + argument_dict["hint_string"] = info.hint_string; + } + + method_dict["default_argument_count"] = mb->get_default_argument_count(); + + Array default_arguments; + method_dict["default_arguments"] = default_arguments; + + for (int i = 0; i < mb->get_default_argument_count(); i++) { + Dictionary default_argument_dict; + default_arguments.push_back(default_argument_dict); + //hash should not change, i hope for tis + Variant da = mb->get_default_argument(i); + default_argument_dict["value"] = da; + } + + method_dict["hint_flags"] = mb->get_hint_flags(); + } + + if (!methods.empty()) { + class_dict["methods"] = methods; + } + } + + { //constants + + List snames; + + k = NULL; + + while ((k = t->constant_map.next(k))) { + snames.push_back(*k); + } + + snames.sort_custom(); + + Array constants; + + for (List::Element *F = snames.front(); F; F = F->next()) { + Dictionary constant_dict; + constants.push_back(constant_dict); + + constant_dict["name"] = F->get(); + constant_dict["value"] = t->constant_map[F->get()]; + } + + if (!constants.empty()) { + class_dict["constants"] = constants; + } + } + + { //signals + + List snames; + + k = NULL; + + while ((k = t->signal_map.next(k))) { + snames.push_back(*k); + } + + snames.sort_custom(); + + Array signals; + + for (List::Element *F = snames.front(); F; F = F->next()) { + Dictionary signal_dict; + signals.push_back(signal_dict); + + MethodInfo &mi = t->signal_map[F->get()]; + signal_dict["name"] = F->get(); + + Array arguments; + signal_dict["arguments"] = arguments; + for (int i = 0; i < mi.arguments.size(); i++) { + Dictionary argument_dict; + arguments.push_back(argument_dict); + argument_dict["type"] = mi.arguments[i].type; + } + } + + if (!signals.empty()) { + class_dict["signals"] = signals; + } + } + + { //properties + + List snames; + + k = NULL; + + while ((k = t->property_setget.next(k))) { + snames.push_back(*k); + } + + snames.sort_custom(); + + Array properties; + + for (List::Element *F = snames.front(); F; F = F->next()) { + Dictionary property_dict; + properties.push_back(property_dict); + + ClassDB::PropertySetGet *psg = t->property_setget.getptr(F->get()); + + property_dict["name"] = F->get(); + property_dict["setter"] = psg->setter; + property_dict["getter"] = psg->getter; + } + + if (!properties.empty()) { + class_dict["property_setget"] = properties; + } + } + + Array property_list; + + //property list + for (List::Element *F = t->property_list.front(); F; F = F->next()) { + Dictionary property_dict; + property_list.push_back(property_dict); + + property_dict["name"] = F->get().name; + property_dict["type"] = F->get().type; + property_dict["hint"] = F->get().hint; + property_dict["hint_string"] = F->get().hint_string; + property_dict["usage"] = F->get().usage; + } + + if (!property_list.empty()) { + class_dict["property_list"] = property_list; + } + } + + FileAccessRef f = FileAccess::open(p_output_file, FileAccess::WRITE); + ERR_FAIL_COND_MSG(!f, "Cannot open file '" + p_output_file + "'."); + f->store_string(JSON::print(classes_dict, /*indent: */ "\t")); + f->close(); + + print_line(String() + "ClassDB API JSON written to: " + ProjectSettings::get_singleton()->globalize_path(p_output_file)); +} + +#endif // DEBUG_METHODS_ENABLED diff --git a/class_db_api_json.h b/class_db_api_json.h new file mode 100644 index 0000000..9ae6aba --- /dev/null +++ b/class_db_api_json.h @@ -0,0 +1,46 @@ +/**************************************************************************/ +/* class_db_api_json.h */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#ifndef CLASS_DB_API_JSON_H +#define CLASS_DB_API_JSON_H + +// 'core/method_bind.h' defines DEBUG_METHODS_ENABLED, but it looks like we +// cannot include it here. That's why we include it through 'core/class_db.h'. +#include "core/class_db.h" + +#ifdef DEBUG_METHODS_ENABLED + +#include "core/ustring.h" + +void class_db_api_to_json(const String &p_output_file, ClassDB::APIType p_api); + +#endif // DEBUG_METHODS_ENABLED + +#endif // CLASS_DB_API_JSON_H diff --git a/config.py b/config.py new file mode 100644 index 0000000..5fb8359 --- /dev/null +++ b/config.py @@ -0,0 +1,77 @@ +supported_platforms = ["windows", "osx", "x11", "server", "android", "haiku", "javascript", "iphone"] + + +def can_build(env, platform): + return not env["arch"].startswith("rv") + + +def configure(env): + platform = env["platform"] + + if platform not in supported_platforms: + raise RuntimeError("This module does not currently support building for this platform") + + env.use_ptrcall = True + env.add_module_version_string("mono") + + from SCons.Script import BoolVariable, PathVariable, Variables, Help + + default_mono_static = platform in ["iphone", "javascript"] + default_mono_bundles_zlib = platform in ["javascript"] + + envvars = Variables() + envvars.Add( + PathVariable( + "mono_prefix", + "Path to the Mono installation directory for the target platform and architecture", + "", + PathVariable.PathAccept, + ) + ) + envvars.Add( + PathVariable( + "mono_bcl", + "Path to a custom Mono BCL (Base Class Library) directory for the target platform", + "", + PathVariable.PathAccept, + ) + ) + envvars.Add(BoolVariable("mono_static", "Statically link Mono", default_mono_static)) + envvars.Add(BoolVariable("mono_glue", "Build with the Mono glue sources", True)) + envvars.Add(BoolVariable("build_cil", "Build C# solutions", True)) + envvars.Add( + BoolVariable("copy_mono_root", "Make a copy of the Mono installation directory to bundle with the editor", True) + ) + + # TODO: It would be great if this could be detected automatically instead + envvars.Add( + BoolVariable( + "mono_bundles_zlib", "Specify if the Mono runtime was built with bundled zlib", default_mono_bundles_zlib + ) + ) + + envvars.Update(env) + Help(envvars.GenerateHelpText(env)) + + if env["mono_bundles_zlib"]: + # Mono may come with zlib bundled for WASM or on newer version when built with MinGW. + print("This Mono runtime comes with zlib bundled. Disabling 'builtin_zlib'...") + env["builtin_zlib"] = False + thirdparty_zlib_dir = "#thirdparty/zlib/" + env.Prepend(CPPPATH=[thirdparty_zlib_dir]) + + +def get_doc_classes(): + return [ + "CSharpScript", + "GodotSharp", + ] + + +def get_doc_path(): + return "doc_classes" + + +def is_enabled(): + # The module is disabled by default. Use module_mono_enabled=yes to enable it. + return False diff --git a/csharp_script.cpp b/csharp_script.cpp new file mode 100644 index 0000000..9da68c4 --- /dev/null +++ b/csharp_script.cpp @@ -0,0 +1,3482 @@ +/**************************************************************************/ +/* csharp_script.cpp */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#include "csharp_script.h" + +#include + +#include "core/io/json.h" +#include "core/os/file_access.h" +#include "core/os/os.h" +#include "core/os/thread.h" +#include "core/project_settings.h" + +#ifdef TOOLS_ENABLED +#include "core/os/keyboard.h" +#include "editor/bindings_generator.h" +#include "editor/csharp_project.h" +#include "editor/editor_node.h" +#include "editor/editor_settings.h" +#include "editor/node_dock.h" +#endif + +#ifdef DEBUG_METHODS_ENABLED +#include "class_db_api_json.h" +#endif + +#include "editor/editor_internal_calls.h" +#include "godotsharp_dirs.h" +#include "mono_gd/gd_mono_cache.h" +#include "mono_gd/gd_mono_class.h" +#include "mono_gd/gd_mono_marshal.h" +#include "mono_gd/gd_mono_utils.h" +#include "signal_awaiter_utils.h" +#include "utils/macros.h" +#include "utils/string_utils.h" +#include "utils/thread_local.h" + +#define CACHED_STRING_NAME(m_var) (CSharpLanguage::get_singleton()->get_string_names().m_var) + +#ifdef TOOLS_ENABLED +static bool _create_project_solution_if_needed() { + String sln_path = GodotSharpDirs::get_project_sln_path(); + String csproj_path = GodotSharpDirs::get_project_csproj_path(); + + if (!FileAccess::exists(sln_path) || !FileAccess::exists(csproj_path)) { + // A solution does not yet exist, create a new one + + CRASH_COND(CSharpLanguage::get_singleton()->get_godotsharp_editor() == NULL); + return CSharpLanguage::get_singleton()->get_godotsharp_editor()->call("CreateProjectSolution"); + } + + return true; +} +#endif + +CSharpLanguage *CSharpLanguage::singleton = NULL; + +String CSharpLanguage::get_name() const { + return "C#"; +} + +String CSharpLanguage::get_type() const { + return "CSharpScript"; +} + +String CSharpLanguage::get_extension() const { + return "cs"; +} + +Error CSharpLanguage::execute_file(const String &p_path) { + // ?? + return OK; +} + +void CSharpLanguage::init() { +#ifdef DEBUG_METHODS_ENABLED + if (OS::get_singleton()->get_cmdline_args().find("--class-db-json")) { + class_db_api_to_json("user://class_db_api.json", ClassDB::API_CORE); +#ifdef TOOLS_ENABLED + class_db_api_to_json("user://class_db_api_editor.json", ClassDB::API_EDITOR); +#endif + } +#endif + + gdmono = memnew(GDMono); + gdmono->initialize(); + +#if defined(TOOLS_ENABLED) && defined(DEBUG_METHODS_ENABLED) + // Generate bindings here, before loading assemblies. 'initialize_load_assemblies' aborts + // the applications if the api assemblies or the main tools assembly is missing, but this + // is not a problem for BindingsGenerator as it only needs the tools project editor assembly. + List cmdline_args = OS::get_singleton()->get_cmdline_args(); + BindingsGenerator::handle_cmdline_args(cmdline_args); +#endif + +#ifndef MONO_GLUE_ENABLED + print_line("Run this binary with '--generate-mono-glue path/to/modules/mono/glue'"); +#endif + + if (gdmono->is_runtime_initialized()) + gdmono->initialize_load_assemblies(); + +#ifdef TOOLS_ENABLED + EditorNode::add_init_callback(&_editor_init_callback); +#endif +} + +void CSharpLanguage::finish() { + finalizing = true; + + // Make sure all script binding gchandles are released before finalizing GDMono + for (Map::Element *E = script_bindings.front(); E; E = E->next()) { + CSharpScriptBinding &script_binding = E->value(); + + if (script_binding.gchandle.is_valid()) { + script_binding.gchandle->release(); + script_binding.inited = false; + } + } + + if (gdmono) { + memdelete(gdmono); + gdmono = NULL; + } + + // Clear here, after finalizing all domains to make sure there is nothing else referencing the elements. + script_bindings.clear(); + +#ifdef DEBUG_ENABLED + for (Map::Element *E = unsafe_object_references.front(); E; E = E->next()) { + const ObjectID &id = E->key(); + Object *obj = ObjectDB::get_instance(id); + + if (obj) { + ERR_PRINT("Leaked unsafe reference to object: " + obj->to_string()); + } else { + ERR_PRINT("Leaked unsafe reference to deleted object: " + itos(id)); + } + } +#endif + + finalizing = false; +} + +void CSharpLanguage::get_reserved_words(List *p_words) const { + static const char *_reserved_words[] = { + // Reserved keywords + "abstract", + "as", + "base", + "bool", + "break", + "byte", + "case", + "catch", + "char", + "checked", + "class", + "const", + "continue", + "decimal", + "default", + "delegate", + "do", + "double", + "else", + "enum", + "event", + "explicit", + "extern", + "false", + "finally", + "fixed", + "float", + "for", + "foreach", + "goto", + "if", + "implicit", + "in", + "int", + "interface", + "internal", + "is", + "lock", + "long", + "namespace", + "new", + "null", + "object", + "operator", + "out", + "override", + "params", + "private", + "protected", + "public", + "readonly", + "ref", + "return", + "sbyte", + "sealed", + "short", + "sizeof", + "stackalloc", + "static", + "string", + "struct", + "switch", + "this", + "throw", + "true", + "try", + "typeof", + "uint", + "ulong", + "unchecked", + "unsafe", + "ushort", + "using", + "virtual", + "void", + "volatile", + "while", + + // Contextual keywords. Not reserved words, but I guess we should include + // them because this seems to be used only for syntax highlighting. + "add", + "alias", + "ascending", + "async", + "await", + "by", + "descending", + "dynamic", + "equals", + "from", + "get", + "global", + "group", + "into", + "join", + "let", + "nameof", + "on", + "orderby", + "partial", + "remove", + "select", + "set", + "value", + "var", + "when", + "where", + "yield", + 0 + }; + + const char **w = _reserved_words; + + while (*w) { + p_words->push_back(*w); + w++; + } +} + +bool CSharpLanguage::is_control_flow_keyword(String p_keyword) const { + return p_keyword == "break" || + p_keyword == "case" || + p_keyword == "catch" || + p_keyword == "continue" || + p_keyword == "default" || + p_keyword == "do" || + p_keyword == "else" || + p_keyword == "finally" || + p_keyword == "for" || + p_keyword == "foreach" || + p_keyword == "goto" || + p_keyword == "if" || + p_keyword == "return" || + p_keyword == "switch" || + p_keyword == "throw" || + p_keyword == "try" || + p_keyword == "while"; +} + +void CSharpLanguage::get_comment_delimiters(List *p_delimiters) const { + p_delimiters->push_back("//"); // single-line comment + p_delimiters->push_back("/* */"); // delimited comment +} + +void CSharpLanguage::get_string_delimiters(List *p_delimiters) const { + p_delimiters->push_back("' '"); // character literal + p_delimiters->push_back("\" \""); // regular string literal + // Verbatim string literals (`@" "`) don't render correctly, so don't highlight them. + // Generic string highlighting suffices as a workaround for now. +} + +static String get_base_class_name(const String &p_base_class_name, const String p_class_name) { + String base_class = p_base_class_name; + if (p_class_name == base_class) { + base_class = "Godot." + base_class; + } + return base_class; +} + +Ref