2
0
Эх сурвалжийг харах

Merge pull request #38115 from neikeq/mono-debug-exported-games

Mono/C#: Allow debugging exported games
Ignacio Roldán Etcheverry 5 жил өмнө
parent
commit
90330a04cc

+ 33 - 21
modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs

@@ -168,13 +168,13 @@ namespace GodotTools.Export
 
 
             // Add dependency assemblies
             // Add dependency assemblies
 
 
-            var dependencies = new Godot.Collections.Dictionary<string, string>();
+            var assemblies = new Godot.Collections.Dictionary<string, string>();
 
 
             string projectDllName = GodotSharpEditor.ProjectAssemblyName;
             string projectDllName = GodotSharpEditor.ProjectAssemblyName;
             string projectDllSrcDir = Path.Combine(GodotSharpDirs.ResTempAssembliesBaseDir, buildConfig);
             string projectDllSrcDir = Path.Combine(GodotSharpDirs.ResTempAssembliesBaseDir, buildConfig);
             string projectDllSrcPath = Path.Combine(projectDllSrcDir, $"{projectDllName}.dll");
             string projectDllSrcPath = Path.Combine(projectDllSrcDir, $"{projectDllName}.dll");
 
 
-            dependencies[projectDllName] = projectDllSrcPath;
+            assemblies[projectDllName] = projectDllSrcPath;
 
 
             if (platform == OS.Platforms.Android)
             if (platform == OS.Platforms.Android)
             {
             {
@@ -184,15 +184,15 @@ namespace GodotTools.Export
                 if (!File.Exists(monoAndroidAssemblyPath))
                 if (!File.Exists(monoAndroidAssemblyPath))
                     throw new FileNotFoundException("Assembly not found: 'Mono.Android'", monoAndroidAssemblyPath);
                     throw new FileNotFoundException("Assembly not found: 'Mono.Android'", monoAndroidAssemblyPath);
 
 
-                dependencies["Mono.Android"] = monoAndroidAssemblyPath;
+                assemblies["Mono.Android"] = monoAndroidAssemblyPath;
             }
             }
 
 
             string bclDir = DeterminePlatformBclDir(platform);
             string bclDir = DeterminePlatformBclDir(platform);
 
 
-            var initialDependencies = dependencies.Duplicate();
-            internal_GetExportedAssemblyDependencies(initialDependencies, buildConfig, bclDir, dependencies);
+            var initialAssemblies = assemblies.Duplicate();
+            internal_GetExportedAssemblyDependencies(initialAssemblies, buildConfig, bclDir, assemblies);
 
 
-            AddI18NAssemblies(dependencies, bclDir);
+            AddI18NAssemblies(assemblies, bclDir);
 
 
             string outputDataDir = null;
             string outputDataDir = null;
 
 
@@ -211,20 +211,32 @@ namespace GodotTools.Export
                     Directory.CreateDirectory(outputDataGameAssembliesDir);
                     Directory.CreateDirectory(outputDataGameAssembliesDir);
             }
             }
 
 
-            foreach (var dependency in dependencies)
+            foreach (var assembly in assemblies)
             {
             {
-                string dependSrcPath = dependency.Value;
-
-                if (assembliesInsidePck)
-                {
-                    string dependDstPath = Path.Combine(resAssembliesDir, dependSrcPath.GetFile());
-                    AddFile(dependSrcPath, dependDstPath);
-                }
-                else
+                void AddToAssembliesDir(string fileSrcPath)
                 {
                 {
-                    string dependDstPath = Path.Combine(outputDataDir, "Assemblies", dependSrcPath.GetFile());
-                    File.Copy(dependSrcPath, dependDstPath);
+                    if (assembliesInsidePck)
+                    {
+                        string fileDstPath = Path.Combine(resAssembliesDir, fileSrcPath.GetFile());
+                        AddFile(fileSrcPath, fileDstPath);
+                    }
+                    else
+                    {
+                        Debug.Assert(outputDataDir != null);
+                        string fileDstPath = Path.Combine(outputDataDir, "Assemblies", fileSrcPath.GetFile());
+                        File.Copy(fileSrcPath, fileDstPath);
+                    }
                 }
                 }
+
+                string assemblySrcPath = assembly.Value;
+
+                string assemblyPathWithoutExtension = Path.ChangeExtension(assemblySrcPath, null);
+                string pdbSrcPath = assemblyPathWithoutExtension + ".pdb";
+
+                AddToAssembliesDir(assemblySrcPath);
+
+                if (File.Exists(pdbSrcPath))
+                    AddToAssembliesDir(pdbSrcPath);
             }
             }
 
 
             // AOT compilation
             // AOT compilation
@@ -254,7 +266,7 @@ namespace GodotTools.Export
                     ToolchainPath = aotToolchainPath
                     ToolchainPath = aotToolchainPath
                 };
                 };
 
 
-                AotBuilder.CompileAssemblies(this, aotOpts, features, platform, isDebug, bclDir, outputDir, outputDataDir, dependencies);
+                AotBuilder.CompileAssemblies(this, aotOpts, features, platform, isDebug, bclDir, outputDir, outputDataDir, assemblies);
             }
             }
         }
         }
 
 
@@ -366,7 +378,7 @@ namespace GodotTools.Export
                     if (PlatformRequiresCustomBcl(platform))
                     if (PlatformRequiresCustomBcl(platform))
                         throw new FileNotFoundException($"Missing BCL (Base Class Library) for platform: {platform}");
                         throw new FileNotFoundException($"Missing BCL (Base Class Library) for platform: {platform}");
 
 
-                    platformBclDir = typeof(object).Assembly.Location; // Use the one we're running on
+                    platformBclDir = typeof(object).Assembly.Location.GetBaseDir(); // Use the one we're running on
                 }
                 }
             }
             }
 
 
@@ -425,7 +437,7 @@ namespace GodotTools.Export
         }
         }
 
 
         [MethodImpl(MethodImplOptions.InternalCall)]
         [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern void internal_GetExportedAssemblyDependencies(Godot.Collections.Dictionary<string, string> initialDependencies,
-            string buildConfig, string customBclDir, Godot.Collections.Dictionary<string, string> dependencies);
+        private static extern void internal_GetExportedAssemblyDependencies(Godot.Collections.Dictionary<string, string> initialAssemblies,
+            string buildConfig, string customBclDir, Godot.Collections.Dictionary<string, string> dependencyAssemblies);
     }
     }
 }
 }

+ 5 - 5
modules/mono/editor/editor_internal_calls.cpp

@@ -231,14 +231,14 @@ int32_t godot_icall_ScriptClassParser_ParseFile(MonoString *p_filepath, MonoObje
 	return err;
 	return err;
 }
 }
 
 
-uint32_t godot_icall_ExportPlugin_GetExportedAssemblyDependencies(MonoObject *p_initial_dependencies,
-		MonoString *p_build_config, MonoString *p_custom_bcl_dir, MonoObject *r_dependencies) {
-	Dictionary initial_dependencies = GDMonoMarshal::mono_object_to_variant(p_initial_dependencies);
+uint32_t godot_icall_ExportPlugin_GetExportedAssemblyDependencies(MonoObject *p_initial_assemblies,
+		MonoString *p_build_config, MonoString *p_custom_bcl_dir, MonoObject *r_assembly_dependencies) {
+	Dictionary initial_dependencies = GDMonoMarshal::mono_object_to_variant(p_initial_assemblies);
 	String build_config = GDMonoMarshal::mono_string_to_godot(p_build_config);
 	String build_config = GDMonoMarshal::mono_string_to_godot(p_build_config);
 	String custom_bcl_dir = GDMonoMarshal::mono_string_to_godot(p_custom_bcl_dir);
 	String custom_bcl_dir = GDMonoMarshal::mono_string_to_godot(p_custom_bcl_dir);
-	Dictionary dependencies = GDMonoMarshal::mono_object_to_variant(r_dependencies);
+	Dictionary assembly_dependencies = GDMonoMarshal::mono_object_to_variant(r_assembly_dependencies);
 
 
-	return GodotSharpExport::get_exported_assembly_dependencies(initial_dependencies, build_config, custom_bcl_dir, dependencies);
+	return GodotSharpExport::get_exported_assembly_dependencies(initial_dependencies, build_config, custom_bcl_dir, assembly_dependencies);
 }
 }
 
 
 MonoString *godot_icall_Internal_UpdateApiAssembliesFromPrebuilt(MonoString *p_config) {
 MonoString *godot_icall_Internal_UpdateApiAssembliesFromPrebuilt(MonoString *p_config) {

+ 9 - 9
modules/mono/editor/godotsharp_export.cpp

@@ -50,13 +50,13 @@ String get_assemblyref_name(MonoImage *p_image, int index) {
 	return String::utf8(mono_metadata_string_heap(p_image, cols[MONO_ASSEMBLYREF_NAME]));
 	return String::utf8(mono_metadata_string_heap(p_image, cols[MONO_ASSEMBLYREF_NAME]));
 }
 }
 
 
-Error get_assembly_dependencies(GDMonoAssembly *p_assembly, const Vector<String> &p_search_dirs, Dictionary &r_dependencies) {
+Error get_assembly_dependencies(GDMonoAssembly *p_assembly, const Vector<String> &p_search_dirs, Dictionary &r_assembly_dependencies) {
 	MonoImage *image = p_assembly->get_image();
 	MonoImage *image = p_assembly->get_image();
 
 
 	for (int i = 0; i < mono_image_get_table_rows(image, MONO_TABLE_ASSEMBLYREF); i++) {
 	for (int i = 0; i < mono_image_get_table_rows(image, MONO_TABLE_ASSEMBLYREF); i++) {
 		String ref_name = get_assemblyref_name(image, i);
 		String ref_name = get_assemblyref_name(image, i);
 
 
-		if (r_dependencies.has(ref_name))
+		if (r_assembly_dependencies.has(ref_name))
 			continue;
 			continue;
 
 
 		GDMonoAssembly *ref_assembly = nullptr;
 		GDMonoAssembly *ref_assembly = nullptr;
@@ -93,17 +93,17 @@ Error get_assembly_dependencies(GDMonoAssembly *p_assembly, const Vector<String>
 		ERR_FAIL_COND_V_MSG(!ref_assembly, ERR_CANT_RESOLVE, "Cannot load assembly (refonly): '" + ref_name + "'.");
 		ERR_FAIL_COND_V_MSG(!ref_assembly, ERR_CANT_RESOLVE, "Cannot load assembly (refonly): '" + ref_name + "'.");
 
 
 		// Use the path we got from the search. Don't try to get the path from the loaded assembly as we can't trust it will be from the selected BCL dir.
 		// Use the path we got from the search. Don't try to get the path from the loaded assembly as we can't trust it will be from the selected BCL dir.
-		r_dependencies[ref_name] = path;
+		r_assembly_dependencies[ref_name] = path;
 
 
-		Error err = get_assembly_dependencies(ref_assembly, p_search_dirs, r_dependencies);
+		Error err = get_assembly_dependencies(ref_assembly, p_search_dirs, r_assembly_dependencies);
 		ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot load one of the dependencies for the assembly: '" + ref_name + "'.");
 		ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot load one of the dependencies for the assembly: '" + ref_name + "'.");
 	}
 	}
 
 
 	return OK;
 	return OK;
 }
 }
 
 
-Error get_exported_assembly_dependencies(const Dictionary &p_initial_dependencies,
-		const String &p_build_config, const String &p_custom_bcl_dir, Dictionary &r_dependencies) {
+Error get_exported_assembly_dependencies(const Dictionary &p_initial_assemblies,
+		const String &p_build_config, const String &p_custom_bcl_dir, Dictionary &r_assembly_dependencies) {
 	MonoDomain *export_domain = GDMonoUtils::create_domain("GodotEngine.Domain.ProjectExport");
 	MonoDomain *export_domain = GDMonoUtils::create_domain("GodotEngine.Domain.ProjectExport");
 	ERR_FAIL_NULL_V(export_domain, FAILED);
 	ERR_FAIL_NULL_V(export_domain, FAILED);
 	_GDMONO_SCOPE_EXIT_DOMAIN_UNLOAD_(export_domain);
 	_GDMONO_SCOPE_EXIT_DOMAIN_UNLOAD_(export_domain);
@@ -113,16 +113,16 @@ Error get_exported_assembly_dependencies(const Dictionary &p_initial_dependencie
 	Vector<String> search_dirs;
 	Vector<String> search_dirs;
 	GDMonoAssembly::fill_search_dirs(search_dirs, p_build_config, p_custom_bcl_dir);
 	GDMonoAssembly::fill_search_dirs(search_dirs, p_build_config, p_custom_bcl_dir);
 
 
-	for (const Variant *key = p_initial_dependencies.next(); key; key = p_initial_dependencies.next(key)) {
+	for (const Variant *key = p_initial_assemblies.next(); key; key = p_initial_assemblies.next(key)) {
 		String assembly_name = *key;
 		String assembly_name = *key;
-		String assembly_path = p_initial_dependencies[*key];
+		String assembly_path = p_initial_assemblies[*key];
 
 
 		GDMonoAssembly *assembly = nullptr;
 		GDMonoAssembly *assembly = nullptr;
 		bool load_success = GDMono::get_singleton()->load_assembly_from(assembly_name, assembly_path, &assembly, /* refonly: */ true);
 		bool load_success = GDMono::get_singleton()->load_assembly_from(assembly_name, assembly_path, &assembly, /* refonly: */ true);
 
 
 		ERR_FAIL_COND_V_MSG(!load_success, ERR_CANT_RESOLVE, "Cannot load assembly (refonly): '" + assembly_name + "'.");
 		ERR_FAIL_COND_V_MSG(!load_success, ERR_CANT_RESOLVE, "Cannot load assembly (refonly): '" + assembly_name + "'.");
 
 
-		Error err = get_assembly_dependencies(assembly, search_dirs, r_dependencies);
+		Error err = get_assembly_dependencies(assembly, search_dirs, r_assembly_dependencies);
 		if (err != OK)
 		if (err != OK)
 			return err;
 			return err;
 	}
 	}

+ 2 - 2
modules/mono/editor/godotsharp_export.h

@@ -41,8 +41,8 @@ namespace GodotSharpExport {
 
 
 Error get_assembly_dependencies(GDMonoAssembly *p_assembly, const Vector<String> &p_search_dirs, Dictionary &r_dependencies);
 Error get_assembly_dependencies(GDMonoAssembly *p_assembly, const Vector<String> &p_search_dirs, Dictionary &r_dependencies);
 
 
-Error get_exported_assembly_dependencies(const Dictionary &p_initial_dependencies,
-		const String &p_build_config, const String &p_custom_lib_dir, Dictionary &r_dependencies);
+Error get_exported_assembly_dependencies(const Dictionary &p_initial_assemblies,
+		const String &p_build_config, const String &p_custom_lib_dir, Dictionary &r_assembly_dependencies);
 
 
 } // namespace GodotSharpExport
 } // namespace GodotSharpExport
 
 

+ 5 - 7
modules/mono/mono_gd/gd_mono.cpp

@@ -129,12 +129,8 @@ void gd_mono_profiler_init() {
 	}
 	}
 }
 }
 
 
-#if defined(DEBUG_ENABLED)
-
 void gd_mono_debug_init() {
 void gd_mono_debug_init() {
 
 
-	mono_debug_init(MONO_DEBUG_FORMAT_MONO);
-
 	CharString da_args = OS::get_singleton()->get_environment("GODOT_MONO_DEBUGGER_AGENT").utf8();
 	CharString da_args = OS::get_singleton()->get_environment("GODOT_MONO_DEBUGGER_AGENT").utf8();
 
 
 #ifdef TOOLS_ENABLED
 #ifdef TOOLS_ENABLED
@@ -159,6 +155,10 @@ void gd_mono_debug_init() {
 		return; // Exported games don't use the project settings to setup the debugger agent
 		return; // Exported games don't use the project settings to setup the debugger agent
 #endif
 #endif
 
 
+	// Debugging enabled
+
+	mono_debug_init(MONO_DEBUG_FORMAT_MONO);
+
 	// --debugger-agent=help
 	// --debugger-agent=help
 	const char *options[] = {
 	const char *options[] = {
 		"--soft-breakpoints",
 		"--soft-breakpoints",
@@ -167,7 +167,6 @@ void gd_mono_debug_init() {
 	mono_jit_parse_options(2, (char **)options);
 	mono_jit_parse_options(2, (char **)options);
 }
 }
 
 
-#endif // defined(DEBUG_ENABLED)
 #endif // !defined(JAVASCRIPT_ENABLED)
 #endif // !defined(JAVASCRIPT_ENABLED)
 
 
 #if defined(JAVASCRIPT_ENABLED)
 #if defined(JAVASCRIPT_ENABLED)
@@ -175,6 +174,7 @@ MonoDomain *gd_initialize_mono_runtime() {
 	const char *vfs_prefix = "managed";
 	const char *vfs_prefix = "managed";
 	int enable_debugging = 0;
 	int enable_debugging = 0;
 
 
+	// TODO: Provide a way to enable debugging on WASM release builds.
 #ifdef DEBUG_ENABLED
 #ifdef DEBUG_ENABLED
 	enable_debugging = 1;
 	enable_debugging = 1;
 #endif
 #endif
@@ -185,9 +185,7 @@ MonoDomain *gd_initialize_mono_runtime() {
 }
 }
 #else
 #else
 MonoDomain *gd_initialize_mono_runtime() {
 MonoDomain *gd_initialize_mono_runtime() {
-#ifdef DEBUG_ENABLED
 	gd_mono_debug_init();
 	gd_mono_debug_init();
-#endif
 
 
 #if defined(IPHONE_ENABLED) || defined(ANDROID_ENABLED)
 #if defined(IPHONE_ENABLED) || defined(ANDROID_ENABLED)
 	// I don't know whether this actually matters or not
 	// I don't know whether this actually matters or not