Merge pull request #38115 from neikeq/mono-debug-exported-games
Mono/C#: Allow debugging exported games
This commit is contained in:
commit
90330a04cc
@ -168,13 +168,13 @@ namespace GodotTools.Export
|
||||
|
||||
// Add dependency assemblies
|
||||
|
||||
var dependencies = new Godot.Collections.Dictionary<string, string>();
|
||||
var assemblies = new Godot.Collections.Dictionary<string, string>();
|
||||
|
||||
string projectDllName = GodotSharpEditor.ProjectAssemblyName;
|
||||
string projectDllSrcDir = Path.Combine(GodotSharpDirs.ResTempAssembliesBaseDir, buildConfig);
|
||||
string projectDllSrcPath = Path.Combine(projectDllSrcDir, $"{projectDllName}.dll");
|
||||
|
||||
dependencies[projectDllName] = projectDllSrcPath;
|
||||
assemblies[projectDllName] = projectDllSrcPath;
|
||||
|
||||
if (platform == OS.Platforms.Android)
|
||||
{
|
||||
@ -184,15 +184,15 @@ namespace GodotTools.Export
|
||||
if (!File.Exists(monoAndroidAssemblyPath))
|
||||
throw new FileNotFoundException("Assembly not found: 'Mono.Android'", monoAndroidAssemblyPath);
|
||||
|
||||
dependencies["Mono.Android"] = monoAndroidAssemblyPath;
|
||||
assemblies["Mono.Android"] = monoAndroidAssemblyPath;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
@ -211,20 +211,32 @@ namespace GodotTools.Export
|
||||
Directory.CreateDirectory(outputDataGameAssembliesDir);
|
||||
}
|
||||
|
||||
foreach (var dependency in dependencies)
|
||||
foreach (var assembly in assemblies)
|
||||
{
|
||||
string dependSrcPath = dependency.Value;
|
||||
void AddToAssembliesDir(string fileSrcPath)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
if (assembliesInsidePck)
|
||||
{
|
||||
string dependDstPath = Path.Combine(resAssembliesDir, dependSrcPath.GetFile());
|
||||
AddFile(dependSrcPath, dependDstPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
string dependDstPath = Path.Combine(outputDataDir, "Assemblies", dependSrcPath.GetFile());
|
||||
File.Copy(dependSrcPath, dependDstPath);
|
||||
}
|
||||
string assemblySrcPath = assembly.Value;
|
||||
|
||||
string assemblyPathWithoutExtension = Path.ChangeExtension(assemblySrcPath, null);
|
||||
string pdbSrcPath = assemblyPathWithoutExtension + ".pdb";
|
||||
|
||||
AddToAssembliesDir(assemblySrcPath);
|
||||
|
||||
if (File.Exists(pdbSrcPath))
|
||||
AddToAssembliesDir(pdbSrcPath);
|
||||
}
|
||||
|
||||
// AOT compilation
|
||||
@ -254,7 +266,7 @@ namespace GodotTools.Export
|
||||
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))
|
||||
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)]
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -231,14 +231,14 @@ int32_t godot_icall_ScriptClassParser_ParseFile(MonoString *p_filepath, MonoObje
|
||||
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 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) {
|
||||
|
@ -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]));
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
for (int i = 0; i < mono_image_get_table_rows(image, MONO_TABLE_ASSEMBLYREF); i++) {
|
||||
String ref_name = get_assemblyref_name(image, i);
|
||||
|
||||
if (r_dependencies.has(ref_name))
|
||||
if (r_assembly_dependencies.has(ref_name))
|
||||
continue;
|
||||
|
||||
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 + "'.");
|
||||
|
||||
// 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 + "'.");
|
||||
}
|
||||
|
||||
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");
|
||||
ERR_FAIL_NULL_V(export_domain, FAILED);
|
||||
_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;
|
||||
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_path = p_initial_dependencies[*key];
|
||||
String assembly_path = p_initial_assemblies[*key];
|
||||
|
||||
GDMonoAssembly *assembly = nullptr;
|
||||
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 + "'.");
|
||||
|
||||
Error err = get_assembly_dependencies(assembly, search_dirs, r_dependencies);
|
||||
Error err = get_assembly_dependencies(assembly, search_dirs, r_assembly_dependencies);
|
||||
if (err != OK)
|
||||
return err;
|
||||
}
|
||||
|
@ -41,8 +41,8 @@ namespace GodotSharpExport {
|
||||
|
||||
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
|
||||
|
||||
|
@ -129,12 +129,8 @@ void gd_mono_profiler_init() {
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(DEBUG_ENABLED)
|
||||
|
||||
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();
|
||||
|
||||
#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
|
||||
#endif
|
||||
|
||||
// Debugging enabled
|
||||
|
||||
mono_debug_init(MONO_DEBUG_FORMAT_MONO);
|
||||
|
||||
// --debugger-agent=help
|
||||
const char *options[] = {
|
||||
"--soft-breakpoints",
|
||||
@ -167,7 +167,6 @@ void gd_mono_debug_init() {
|
||||
mono_jit_parse_options(2, (char **)options);
|
||||
}
|
||||
|
||||
#endif // defined(DEBUG_ENABLED)
|
||||
#endif // !defined(JAVASCRIPT_ENABLED)
|
||||
|
||||
#if defined(JAVASCRIPT_ENABLED)
|
||||
@ -175,6 +174,7 @@ MonoDomain *gd_initialize_mono_runtime() {
|
||||
const char *vfs_prefix = "managed";
|
||||
int enable_debugging = 0;
|
||||
|
||||
// TODO: Provide a way to enable debugging on WASM release builds.
|
||||
#ifdef DEBUG_ENABLED
|
||||
enable_debugging = 1;
|
||||
#endif
|
||||
@ -185,9 +185,7 @@ MonoDomain *gd_initialize_mono_runtime() {
|
||||
}
|
||||
#else
|
||||
MonoDomain *gd_initialize_mono_runtime() {
|
||||
#ifdef DEBUG_ENABLED
|
||||
gd_mono_debug_init();
|
||||
#endif
|
||||
|
||||
#if defined(IPHONE_ENABLED) || defined(ANDROID_ENABLED)
|
||||
// I don't know whether this actually matters or not
|
||||
|
Loading…
Reference in New Issue
Block a user