Pārlūkot izejas kodu

Merge pull request #23583 from neikeq/ee

Improve the C# API projects generation
Ignacio Etcheverry 6 gadi atpakaļ
vecāks
revīzija
6d7dc9d98b

+ 2 - 1
modules/mono/csharp_script.cpp

@@ -2770,7 +2770,8 @@ Error ResourceFormatSaverCSharpScript::save(const String &p_path, const RES &p_r
 					"Compile",
 					"Compile",
 					ProjectSettings::get_singleton()->globalize_path(p_path));
 					ProjectSettings::get_singleton()->globalize_path(p_path));
 		} else {
 		} else {
-			ERR_PRINTS("Cannot add " + p_path + " to the C# project because it could not be created.");
+			ERR_PRINTS("Failed to create C# project");
+			ERR_PRINTS("Cannot add " + p_path + " to the C# project");
 		}
 		}
 	}
 	}
 #endif
 #endif

+ 17 - 19
modules/mono/editor/GodotSharpTools/Project/ProjectGenerator.cs

@@ -6,22 +6,24 @@ namespace GodotSharpTools.Project
 {
 {
     public static class ProjectGenerator
     public static class ProjectGenerator
     {
     {
+        public const string CoreApiProjectName = "GodotSharp";
+        public const string EditorApiProjectName = "GodotSharpEditor";
         const string CoreApiProjectGuid = "{AEBF0036-DA76-4341-B651-A3F2856AB2FA}";
         const string CoreApiProjectGuid = "{AEBF0036-DA76-4341-B651-A3F2856AB2FA}";
         const string EditorApiProjectGuid = "{8FBEC238-D944-4074-8548-B3B524305905}";
         const string EditorApiProjectGuid = "{8FBEC238-D944-4074-8548-B3B524305905}";
 
 
         public static string GenCoreApiProject(string dir, string[] compileItems)
         public static string GenCoreApiProject(string dir, string[] compileItems)
         {
         {
-            string path = Path.Combine(dir, CoreApiProject + ".csproj");
+            string path = Path.Combine(dir, CoreApiProjectName + ".csproj");
 
 
             ProjectPropertyGroupElement mainGroup;
             ProjectPropertyGroupElement mainGroup;
-            var root = CreateLibraryProject(CoreApiProject, out mainGroup);
+            var root = CreateLibraryProject(CoreApiProjectName, out mainGroup);
 
 
             mainGroup.AddProperty("DocumentationFile", Path.Combine("$(OutputPath)", "$(AssemblyName).xml"));
             mainGroup.AddProperty("DocumentationFile", Path.Combine("$(OutputPath)", "$(AssemblyName).xml"));
             mainGroup.SetProperty("RootNamespace", "Godot");
             mainGroup.SetProperty("RootNamespace", "Godot");
             mainGroup.SetProperty("ProjectGuid", CoreApiProjectGuid);
             mainGroup.SetProperty("ProjectGuid", CoreApiProjectGuid);
 
 
-            GenAssemblyInfoFile(root, dir, CoreApiProject,
-                                new string[] { "[assembly: InternalsVisibleTo(\"" + EditorApiProject + "\")]" },
+            GenAssemblyInfoFile(root, dir, CoreApiProjectName,
+                                new string[] { "[assembly: InternalsVisibleTo(\"" + EditorApiProjectName + "\")]" },
                                 new string[] { "System.Runtime.CompilerServices" });
                                 new string[] { "System.Runtime.CompilerServices" });
 
 
             foreach (var item in compileItems)
             foreach (var item in compileItems)
@@ -31,34 +33,33 @@ namespace GodotSharpTools.Project
 
 
             root.Save(path);
             root.Save(path);
 
 
-            return root.GetGuid().ToString().ToUpper();
+            return CoreApiProjectGuid;
         }
         }
 
 
-        public static string GenEditorApiProject(string dir, string coreApiHintPath, string[] compileItems)
+        public static string GenEditorApiProject(string dir, string coreApiProjPath, string[] compileItems)
         {
         {
-            string path = Path.Combine(dir, EditorApiProject + ".csproj");
+            string path = Path.Combine(dir, EditorApiProjectName + ".csproj");
 
 
             ProjectPropertyGroupElement mainGroup;
             ProjectPropertyGroupElement mainGroup;
-            var root = CreateLibraryProject(EditorApiProject, out mainGroup);
+            var root = CreateLibraryProject(EditorApiProjectName, out mainGroup);
 
 
             mainGroup.AddProperty("DocumentationFile", Path.Combine("$(OutputPath)", "$(AssemblyName).xml"));
             mainGroup.AddProperty("DocumentationFile", Path.Combine("$(OutputPath)", "$(AssemblyName).xml"));
             mainGroup.SetProperty("RootNamespace", "Godot");
             mainGroup.SetProperty("RootNamespace", "Godot");
             mainGroup.SetProperty("ProjectGuid", EditorApiProjectGuid);
             mainGroup.SetProperty("ProjectGuid", EditorApiProjectGuid);
 
 
-            GenAssemblyInfoFile(root, dir, EditorApiProject);
+            GenAssemblyInfoFile(root, dir, EditorApiProjectName);
 
 
             foreach (var item in compileItems)
             foreach (var item in compileItems)
             {
             {
                 root.AddItem("Compile", item.RelativeToPath(dir).Replace("/", "\\"));
                 root.AddItem("Compile", item.RelativeToPath(dir).Replace("/", "\\"));
             }
             }
 
 
-            var coreApiRef = root.AddItem("Reference", CoreApiProject);
-            coreApiRef.AddMetadata("HintPath", coreApiHintPath);
+            var coreApiRef = root.AddItem("ProjectReference", coreApiProjPath.Replace("/", "\\"));
             coreApiRef.AddMetadata("Private", "False");
             coreApiRef.AddMetadata("Private", "False");
 
 
             root.Save(path);
             root.Save(path);
 
 
-            return root.GetGuid().ToString().ToUpper();
+            return EditorApiProjectGuid;
         }
         }
 
 
         public static string GenGameProject(string dir, string name, string[] compileItems)
         public static string GenGameProject(string dir, string name, string[] compileItems)
@@ -82,13 +83,13 @@ namespace GodotSharpTools.Project
             toolsGroup.AddProperty("WarningLevel", "4");
             toolsGroup.AddProperty("WarningLevel", "4");
             toolsGroup.AddProperty("ConsolePause", "false");
             toolsGroup.AddProperty("ConsolePause", "false");
 
 
-            var coreApiRef = root.AddItem("Reference", CoreApiProject);
-            coreApiRef.AddMetadata("HintPath", Path.Combine("$(ProjectDir)", ".mono", "assemblies", CoreApiProject + ".dll"));
+            var coreApiRef = root.AddItem("Reference", CoreApiProjectName);
+            coreApiRef.AddMetadata("HintPath", Path.Combine("$(ProjectDir)", ".mono", "assemblies", CoreApiProjectName + ".dll"));
             coreApiRef.AddMetadata("Private", "False");
             coreApiRef.AddMetadata("Private", "False");
 
 
-            var editorApiRef = root.AddItem("Reference", EditorApiProject);
+            var editorApiRef = root.AddItem("Reference", EditorApiProjectName);
             editorApiRef.Condition = " '$(Configuration)' == 'Tools' ";
             editorApiRef.Condition = " '$(Configuration)' == 'Tools' ";
-            editorApiRef.AddMetadata("HintPath", Path.Combine("$(ProjectDir)", ".mono", "assemblies", EditorApiProject + ".dll"));
+            editorApiRef.AddMetadata("HintPath", Path.Combine("$(ProjectDir)", ".mono", "assemblies", EditorApiProjectName + ".dll"));
             editorApiRef.AddMetadata("Private", "False");
             editorApiRef.AddMetadata("Private", "False");
 
 
             GenAssemblyInfoFile(root, dir, name);
             GenAssemblyInfoFile(root, dir, name);
@@ -187,9 +188,6 @@ namespace GodotSharpTools.Project
             }
             }
         }
         }
 
 
-        public const string CoreApiProject = "GodotSharp";
-        public const string EditorApiProject = "GodotSharpEditor";
-
         private const string assemblyInfoTemplate =
         private const string assemblyInfoTemplate =
 @"using System.Reflection;{0}
 @"using System.Reflection;{0}
 
 

+ 76 - 64
modules/mono/editor/bindings_generator.cpp

@@ -47,7 +47,6 @@
 #include "../utils/path_utils.h"
 #include "../utils/path_utils.h"
 #include "../utils/string_utils.h"
 #include "../utils/string_utils.h"
 #include "csharp_project.h"
 #include "csharp_project.h"
-#include "net_solution.h"
 
 
 #define CS_INDENT "    " // 4 whitespaces
 #define CS_INDENT "    " // 4 whitespaces
 
 
@@ -401,32 +400,29 @@ void BindingsGenerator::_generate_global_constants(List<String> &p_output) {
 	p_output.push_back(CLOSE_BLOCK); // end of namespace
 	p_output.push_back(CLOSE_BLOCK); // end of namespace
 }
 }
 
 
-Error BindingsGenerator::generate_cs_core_project(const String &p_output_dir, bool p_verbose_output) {
+Error BindingsGenerator::generate_cs_core_project(const String &p_solution_dir, DotNetSolution &r_solution, bool p_verbose_output) {
 
 
 	verbose_output = p_verbose_output;
 	verbose_output = p_verbose_output;
 
 
+	String proj_dir = p_solution_dir.plus_file(CORE_API_ASSEMBLY_NAME);
+
 	DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
 	DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
 	ERR_FAIL_COND_V(!da, ERR_CANT_CREATE);
 	ERR_FAIL_COND_V(!da, ERR_CANT_CREATE);
 
 
-	if (!DirAccess::exists(p_output_dir)) {
-		Error err = da->make_dir_recursive(p_output_dir);
+	if (!DirAccess::exists(proj_dir)) {
+		Error err = da->make_dir_recursive(proj_dir);
 		ERR_FAIL_COND_V(err != OK, ERR_CANT_CREATE);
 		ERR_FAIL_COND_V(err != OK, ERR_CANT_CREATE);
 	}
 	}
 
 
-	da->change_dir(p_output_dir);
+	da->change_dir(proj_dir);
 	da->make_dir("Core");
 	da->make_dir("Core");
 	da->make_dir("ObjectType");
 	da->make_dir("ObjectType");
 
 
-	String core_dir = path_join(p_output_dir, "Core");
-	String obj_type_dir = path_join(p_output_dir, "ObjectType");
+	String core_dir = path_join(proj_dir, "Core");
+	String obj_type_dir = path_join(proj_dir, "ObjectType");
 
 
 	Vector<String> compile_items;
 	Vector<String> compile_items;
 
 
-	NETSolution solution(API_ASSEMBLY_NAME);
-
-	if (!solution.set_path(p_output_dir))
-		return ERR_FILE_NOT_FOUND;
-
 	// Generate source file for global scope constants and enums
 	// Generate source file for global scope constants and enums
 	{
 	{
 		List<String> constants_source;
 		List<String> constants_source;
@@ -530,15 +526,15 @@ Error BindingsGenerator::generate_cs_core_project(const String &p_output_dir, bo
 
 
 	compile_items.push_back(internal_methods_file);
 	compile_items.push_back(internal_methods_file);
 
 
-	String guid = CSharpProject::generate_core_api_project(p_output_dir, compile_items);
+	String guid = CSharpProject::generate_core_api_project(proj_dir, compile_items);
 
 
-	solution.add_new_project(API_ASSEMBLY_NAME, guid);
+	DotNetSolution::ProjectInfo proj_info;
+	proj_info.guid = guid;
+	proj_info.relpath = String(CORE_API_ASSEMBLY_NAME).plus_file(CORE_API_ASSEMBLY_NAME ".csproj");
+	proj_info.configs.push_back("Debug");
+	proj_info.configs.push_back("Release");
 
 
-	Error sln_error = solution.save();
-	if (sln_error != OK) {
-		ERR_PRINT("Could not to save .NET solution.");
-		return sln_error;
-	}
+	r_solution.add_new_project(CORE_API_ASSEMBLY_NAME, proj_info);
 
 
 	if (verbose_output)
 	if (verbose_output)
 		OS::get_singleton()->print("The solution and C# project for the Core API was generated successfully\n");
 		OS::get_singleton()->print("The solution and C# project for the Core API was generated successfully\n");
@@ -546,32 +542,29 @@ Error BindingsGenerator::generate_cs_core_project(const String &p_output_dir, bo
 	return OK;
 	return OK;
 }
 }
 
 
-Error BindingsGenerator::generate_cs_editor_project(const String &p_output_dir, const String &p_core_dll_path, bool p_verbose_output) {
+Error BindingsGenerator::generate_cs_editor_project(const String &p_solution_dir, DotNetSolution &r_solution, bool p_verbose_output) {
 
 
 	verbose_output = p_verbose_output;
 	verbose_output = p_verbose_output;
 
 
+	String proj_dir = p_solution_dir.plus_file(EDITOR_API_ASSEMBLY_NAME);
+
 	DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
 	DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
 	ERR_FAIL_COND_V(!da, ERR_CANT_CREATE);
 	ERR_FAIL_COND_V(!da, ERR_CANT_CREATE);
 
 
-	if (!DirAccess::exists(p_output_dir)) {
-		Error err = da->make_dir_recursive(p_output_dir);
+	if (!DirAccess::exists(proj_dir)) {
+		Error err = da->make_dir_recursive(proj_dir);
 		ERR_FAIL_COND_V(err != OK, ERR_CANT_CREATE);
 		ERR_FAIL_COND_V(err != OK, ERR_CANT_CREATE);
 	}
 	}
 
 
-	da->change_dir(p_output_dir);
+	da->change_dir(proj_dir);
 	da->make_dir("Core");
 	da->make_dir("Core");
 	da->make_dir("ObjectType");
 	da->make_dir("ObjectType");
 
 
-	String core_dir = path_join(p_output_dir, "Core");
-	String obj_type_dir = path_join(p_output_dir, "ObjectType");
+	String core_dir = path_join(proj_dir, "Core");
+	String obj_type_dir = path_join(proj_dir, "ObjectType");
 
 
 	Vector<String> compile_items;
 	Vector<String> compile_items;
 
 
-	NETSolution solution(EDITOR_API_ASSEMBLY_NAME);
-
-	if (!solution.set_path(p_output_dir))
-		return ERR_FILE_NOT_FOUND;
-
 	for (OrderedHashMap<StringName, TypeInterface>::Element E = obj_types.front(); E; E = E.next()) {
 	for (OrderedHashMap<StringName, TypeInterface>::Element E = obj_types.front(); E; E = E.next()) {
 		const TypeInterface &itype = E.get();
 		const TypeInterface &itype = E.get();
 
 
@@ -632,19 +625,57 @@ Error BindingsGenerator::generate_cs_editor_project(const String &p_output_dir,
 
 
 	compile_items.push_back(internal_methods_file);
 	compile_items.push_back(internal_methods_file);
 
 
-	String guid = CSharpProject::generate_editor_api_project(p_output_dir, p_core_dll_path, compile_items);
+	String guid = CSharpProject::generate_editor_api_project(proj_dir, "../" CORE_API_ASSEMBLY_NAME "/" CORE_API_ASSEMBLY_NAME ".csproj", compile_items);
+
+	DotNetSolution::ProjectInfo proj_info;
+	proj_info.guid = guid;
+	proj_info.relpath = String(EDITOR_API_ASSEMBLY_NAME).plus_file(EDITOR_API_ASSEMBLY_NAME ".csproj");
+	proj_info.configs.push_back("Debug");
+	proj_info.configs.push_back("Release");
+
+	r_solution.add_new_project(EDITOR_API_ASSEMBLY_NAME, proj_info);
+
+	if (verbose_output)
+		OS::get_singleton()->print("The solution and C# project for the Editor API was generated successfully\n");
+
+	return OK;
+}
 
 
-	solution.add_new_project(EDITOR_API_ASSEMBLY_NAME, guid);
+Error BindingsGenerator::generate_cs_api(const String &p_output_dir, bool p_verbose_output) {
+
+	DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+	ERR_FAIL_COND_V(!da, ERR_CANT_CREATE);
+
+	if (!DirAccess::exists(p_output_dir)) {
+		Error err = da->make_dir_recursive(p_output_dir);
+		ERR_FAIL_COND_V(err != OK, ERR_CANT_CREATE);
+	}
+
+	DotNetSolution solution(API_SOLUTION_NAME);
+
+	if (!solution.set_path(p_output_dir))
+		return ERR_FILE_NOT_FOUND;
+
+	Error proj_err;
+
+	proj_err = generate_cs_core_project(p_output_dir, solution, p_verbose_output);
+	if (proj_err != OK) {
+		ERR_PRINT("Generation of the Core API C# project failed");
+		return proj_err;
+	}
+
+	proj_err = generate_cs_editor_project(p_output_dir, solution, p_verbose_output);
+	if (proj_err != OK) {
+		ERR_PRINT("Generation of the Editor API C# project failed");
+		return proj_err;
+	}
 
 
 	Error sln_error = solution.save();
 	Error sln_error = solution.save();
 	if (sln_error != OK) {
 	if (sln_error != OK) {
-		ERR_PRINT("Could not to save .NET solution.");
+		ERR_PRINT("Failed to save API solution");
 		return sln_error;
 		return sln_error;
 	}
 	}
 
 
-	if (verbose_output)
-		OS::get_singleton()->print("The solution and C# project for the Editor API was generated successfully\n");
-
 	return OK;
 	return OK;
 }
 }
 
 
@@ -2368,12 +2399,11 @@ void BindingsGenerator::initialize() {
 
 
 void BindingsGenerator::handle_cmdline_args(const List<String> &p_cmdline_args) {
 void BindingsGenerator::handle_cmdline_args(const List<String> &p_cmdline_args) {
 
 
-	const int NUM_OPTIONS = 3;
+	const int NUM_OPTIONS = 2;
 	int options_left = NUM_OPTIONS;
 	int options_left = NUM_OPTIONS;
 
 
 	String mono_glue_option = "--generate-mono-glue";
 	String mono_glue_option = "--generate-mono-glue";
-	String cs_core_api_option = "--generate-cs-core-api";
-	String cs_editor_api_option = "--generate-cs-editor-api";
+	String cs_api_option = "--generate-cs-api";
 
 
 	verbose_output = true;
 	verbose_output = true;
 
 
@@ -2387,42 +2417,24 @@ void BindingsGenerator::handle_cmdline_args(const List<String> &p_cmdline_args)
 
 
 			if (path_elem) {
 			if (path_elem) {
 				if (get_singleton()->generate_glue(path_elem->get()) != OK)
 				if (get_singleton()->generate_glue(path_elem->get()) != OK)
-					ERR_PRINT("Mono glue generation failed");
+					ERR_PRINTS(mono_glue_option + ": Failed to generate mono glue");
 				elem = elem->next();
 				elem = elem->next();
 			} else {
 			} else {
-				ERR_PRINTS("--generate-mono-glue: No output directory specified");
+				ERR_PRINTS(mono_glue_option + ": No output directory specified");
 			}
 			}
 
 
 			--options_left;
 			--options_left;
 
 
-		} else if (elem->get() == cs_core_api_option) {
+		} else if (elem->get() == cs_api_option) {
 
 
 			const List<String>::Element *path_elem = elem->next();
 			const List<String>::Element *path_elem = elem->next();
 
 
 			if (path_elem) {
 			if (path_elem) {
-				if (get_singleton()->generate_cs_core_project(path_elem->get()) != OK)
-					ERR_PRINT("Generation of solution and C# project for the Core API failed");
+				if (get_singleton()->generate_cs_api(path_elem->get()) != OK)
+					ERR_PRINTS(cs_api_option + ": Failed to generate the C# API");
 				elem = elem->next();
 				elem = elem->next();
 			} else {
 			} else {
-				ERR_PRINTS(cs_core_api_option + ": No output directory specified");
-			}
-
-			--options_left;
-
-		} else if (elem->get() == cs_editor_api_option) {
-
-			const List<String>::Element *path_elem = elem->next();
-
-			if (path_elem) {
-				if (path_elem->next()) {
-					if (get_singleton()->generate_cs_editor_project(path_elem->get(), path_elem->next()->get()) != OK)
-						ERR_PRINT("Generation of solution and C# project for the Editor API failed");
-					elem = path_elem->next();
-				} else {
-					ERR_PRINTS(cs_editor_api_option + ": No hint path for the Core API dll specified");
-				}
-			} else {
-				ERR_PRINTS(cs_editor_api_option + ": No output directory specified");
+				ERR_PRINTS(cs_api_option + ": No output directory specified");
 			}
 			}
 
 
 			--options_left;
 			--options_left;
@@ -2434,7 +2446,7 @@ void BindingsGenerator::handle_cmdline_args(const List<String> &p_cmdline_args)
 	verbose_output = false;
 	verbose_output = false;
 
 
 	if (options_left != NUM_OPTIONS)
 	if (options_left != NUM_OPTIONS)
-		exit(0);
+		::exit(0);
 }
 }
 
 
 #endif
 #endif

+ 4 - 2
modules/mono/editor/bindings_generator.h

@@ -32,6 +32,7 @@
 #define BINDINGS_GENERATOR_H
 #define BINDINGS_GENERATOR_H
 
 
 #include "core/class_db.h"
 #include "core/class_db.h"
+#include "dotnet_solution.h"
 #include "editor/doc/doc_data.h"
 #include "editor/doc/doc_data.h"
 #include "editor/editor_help.h"
 #include "editor/editor_help.h"
 
 
@@ -556,8 +557,9 @@ class BindingsGenerator {
 	static BindingsGenerator *singleton;
 	static BindingsGenerator *singleton;
 
 
 public:
 public:
-	Error generate_cs_core_project(const String &p_output_dir, bool p_verbose_output = true);
-	Error generate_cs_editor_project(const String &p_output_dir, const String &p_core_dll_path, bool p_verbose_output = true);
+	Error generate_cs_core_project(const String &p_solution_dir, DotNetSolution &r_solution, bool p_verbose_output = true);
+	Error generate_cs_editor_project(const String &p_solution_dir, DotNetSolution &r_solution, bool p_verbose_output = true);
+	Error generate_cs_api(const String &p_output_dir, bool p_verbose_output = true);
 	Error generate_glue(const String &p_output_dir);
 	Error generate_glue(const String &p_output_dir);
 
 
 	static uint32_t get_version();
 	static uint32_t get_version();

+ 13 - 3
modules/mono/editor/csharp_project.cpp

@@ -31,6 +31,8 @@
 #include "csharp_project.h"
 #include "csharp_project.h"
 
 
 #include "core/io/json.h"
 #include "core/io/json.h"
+#include "core/os/dir_access.h"
+#include "core/os/file_access.h"
 #include "core/os/os.h"
 #include "core/os/os.h"
 #include "core/project_settings.h"
 #include "core/project_settings.h"
 
 
@@ -62,16 +64,16 @@ String generate_core_api_project(const String &p_dir, const Vector<String> &p_fi
 	return ret ? GDMonoMarshal::mono_string_to_godot((MonoString *)ret) : String();
 	return ret ? GDMonoMarshal::mono_string_to_godot((MonoString *)ret) : String();
 }
 }
 
 
-String generate_editor_api_project(const String &p_dir, const String &p_core_dll_path, const Vector<String> &p_files) {
+String generate_editor_api_project(const String &p_dir, const String &p_core_proj_path, const Vector<String> &p_files) {
 
 
 	_GDMONO_SCOPE_DOMAIN_(TOOLS_DOMAIN)
 	_GDMONO_SCOPE_DOMAIN_(TOOLS_DOMAIN)
 
 
 	GDMonoClass *klass = GDMono::get_singleton()->get_editor_tools_assembly()->get_class("GodotSharpTools.Project", "ProjectGenerator");
 	GDMonoClass *klass = GDMono::get_singleton()->get_editor_tools_assembly()->get_class("GodotSharpTools.Project", "ProjectGenerator");
 
 
 	Variant dir = p_dir;
 	Variant dir = p_dir;
-	Variant core_dll_path = p_core_dll_path;
+	Variant core_proj_path = p_core_proj_path;
 	Variant compile_items = p_files;
 	Variant compile_items = p_files;
-	const Variant *args[3] = { &dir, &core_dll_path, &compile_items };
+	const Variant *args[3] = { &dir, &core_proj_path, &compile_items };
 	MonoException *exc = NULL;
 	MonoException *exc = NULL;
 	MonoObject *ret = klass->get_method("GenEditorApiProject", 3)->invoke(NULL, args, &exc);
 	MonoObject *ret = klass->get_method("GenEditorApiProject", 3)->invoke(NULL, args, &exc);
 
 
@@ -127,6 +129,14 @@ Error generate_scripts_metadata(const String &p_project_path, const String &p_ou
 
 
 	_GDMONO_SCOPE_DOMAIN_(TOOLS_DOMAIN)
 	_GDMONO_SCOPE_DOMAIN_(TOOLS_DOMAIN)
 
 
+	if (FileAccess::exists(p_output_path)) {
+		DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+		Error rm_err = da->remove(p_output_path);
+
+		ERR_EXPLAIN("Failed to remove old scripts metadata file");
+		ERR_FAIL_COND_V(rm_err != OK, rm_err);
+	}
+
 	GDMonoClass *project_utils = GDMono::get_singleton()->get_editor_tools_assembly()->get_class("GodotSharpTools.Project", "ProjectUtils");
 	GDMonoClass *project_utils = GDMono::get_singleton()->get_editor_tools_assembly()->get_class("GodotSharpTools.Project", "ProjectUtils");
 
 
 	void *args[2] = {
 	void *args[2] = {

+ 35 - 26
modules/mono/editor/net_solution.cpp → modules/mono/editor/dotnet_solution.cpp

@@ -1,5 +1,5 @@
 /*************************************************************************/
 /*************************************************************************/
-/*  net_solution.cpp                                                     */
+/*  dotnet_solution.cpp                                                  */
 /*************************************************************************/
 /*************************************************************************/
 /*                       This file is part of:                           */
 /*                       This file is part of:                           */
 /*                           GODOT ENGINE                                */
 /*                           GODOT ENGINE                                */
@@ -28,7 +28,7 @@
 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
 /*************************************************************************/
 /*************************************************************************/
 
 
-#include "net_solution.h"
+#include "dotnet_solution.h"
 
 
 #include "core/os/dir_access.h"
 #include "core/os/dir_access.h"
 #include "core/os/file_access.h"
 #include "core/os/file_access.h"
@@ -58,27 +58,26 @@
 	"\t\t{%0}.%1|Any CPU.ActiveCfg = %1|Any CPU\n" \
 	"\t\t{%0}.%1|Any CPU.ActiveCfg = %1|Any CPU\n" \
 	"\t\t{%0}.%1|Any CPU.Build.0 = %1|Any CPU"
 	"\t\t{%0}.%1|Any CPU.Build.0 = %1|Any CPU"
 
 
-void NETSolution::add_new_project(const String &p_name, const String &p_guid, const Vector<String> &p_extra_configs) {
-	if (projects.has(p_name))
-		WARN_PRINT("Overriding existing project.");
-
-	ProjectInfo procinfo;
-	procinfo.guid = p_guid;
+void DotNetSolution::add_new_project(const String &p_name, const ProjectInfo &p_project_info) {
+	projects[p_name] = p_project_info;
+}
 
 
-	procinfo.configs.push_back("Debug");
-	procinfo.configs.push_back("Release");
+bool DotNetSolution::has_project(const String &p_name) const {
+	return projects.find(p_name) != NULL;
+}
 
 
-	for (int i = 0; i < p_extra_configs.size(); i++) {
-		procinfo.configs.push_back(p_extra_configs[i]);
-	}
+const DotNetSolution::ProjectInfo &DotNetSolution::get_project_info(const String &p_name) const {
+	return projects[p_name];
+}
 
 
-	projects[p_name] = procinfo;
+bool DotNetSolution::remove_project(const String &p_name) {
+	return projects.erase(p_name);
 }
 }
 
 
-Error NETSolution::save() {
+Error DotNetSolution::save() {
 	bool dir_exists = DirAccess::exists(path);
 	bool dir_exists = DirAccess::exists(path);
 	ERR_EXPLAIN("The directory does not exist.");
 	ERR_EXPLAIN("The directory does not exist.");
-	ERR_FAIL_COND_V(!dir_exists, ERR_FILE_BAD_PATH);
+	ERR_FAIL_COND_V(!dir_exists, ERR_FILE_NOT_FOUND);
 
 
 	String projs_decl;
 	String projs_decl;
 	String sln_platform_cfg;
 	String sln_platform_cfg;
@@ -86,34 +85,40 @@ Error NETSolution::save() {
 
 
 	for (Map<String, ProjectInfo>::Element *E = projects.front(); E; E = E->next()) {
 	for (Map<String, ProjectInfo>::Element *E = projects.front(); E; E = E->next()) {
 		const String &name = E->key();
 		const String &name = E->key();
-		const ProjectInfo &procinfo = E->value();
+		const ProjectInfo &proj_info = E->value();
 
 
-		projs_decl += sformat(PROJECT_DECLARATION, name, name + ".csproj", procinfo.guid);
+		bool is_front = E == projects.front();
 
 
-		for (int i = 0; i < procinfo.configs.size(); i++) {
-			const String &config = procinfo.configs[i];
+		if (!is_front)
+			projs_decl += "\n";
 
 
-			if (i != 0) {
+		projs_decl += sformat(PROJECT_DECLARATION, name, proj_info.relpath.replace("/", "\\"), proj_info.guid);
+
+		for (int i = 0; i < proj_info.configs.size(); i++) {
+			const String &config = proj_info.configs[i];
+
+			if (i != 0 || !is_front) {
 				sln_platform_cfg += "\n";
 				sln_platform_cfg += "\n";
 				proj_platform_cfg += "\n";
 				proj_platform_cfg += "\n";
 			}
 			}
 
 
 			sln_platform_cfg += sformat(SOLUTION_PLATFORMS_CONFIG, config);
 			sln_platform_cfg += sformat(SOLUTION_PLATFORMS_CONFIG, config);
-			proj_platform_cfg += sformat(PROJECT_PLATFORMS_CONFIG, procinfo.guid, config);
+			proj_platform_cfg += sformat(PROJECT_PLATFORMS_CONFIG, proj_info.guid, config);
 		}
 		}
 	}
 	}
 
 
 	String content = sformat(SOLUTION_TEMPLATE, projs_decl, sln_platform_cfg, proj_platform_cfg);
 	String content = sformat(SOLUTION_TEMPLATE, projs_decl, sln_platform_cfg, proj_platform_cfg);
 
 
-	FileAccessRef file = FileAccess::open(path_join(path, name + ".sln"), FileAccess::WRITE);
-	ERR_FAIL_COND_V(!file, ERR_FILE_CANT_WRITE);
+	FileAccess *file = FileAccess::open(path_join(path, name + ".sln"), FileAccess::WRITE);
+	ERR_FAIL_NULL_V(file, ERR_FILE_CANT_WRITE);
 	file->store_string(content);
 	file->store_string(content);
 	file->close();
 	file->close();
+	memdelete(file);
 
 
 	return OK;
 	return OK;
 }
 }
 
 
-bool NETSolution::set_path(const String &p_existing_path) {
+bool DotNetSolution::set_path(const String &p_existing_path) {
 	if (p_existing_path.is_abs_path()) {
 	if (p_existing_path.is_abs_path()) {
 		path = p_existing_path;
 		path = p_existing_path;
 	} else {
 	} else {
@@ -126,6 +131,10 @@ bool NETSolution::set_path(const String &p_existing_path) {
 	return true;
 	return true;
 }
 }
 
 
-NETSolution::NETSolution(const String &p_name) {
+String DotNetSolution::get_path() {
+	return path;
+}
+
+DotNetSolution::DotNetSolution(const String &p_name) {
 	name = p_name;
 	name = p_name;
 }
 }

+ 14 - 9
modules/mono/editor/net_solution.h → modules/mono/editor/dotnet_solution.h

@@ -1,5 +1,5 @@
 /*************************************************************************/
 /*************************************************************************/
-/*  net_solution.h                                                       */
+/*  dotnet_solution.h                                                    */
 /*************************************************************************/
 /*************************************************************************/
 /*                       This file is part of:                           */
 /*                       This file is part of:                           */
 /*                           GODOT ENGINE                                */
 /*                           GODOT ENGINE                                */
@@ -34,23 +34,28 @@
 #include "core/map.h"
 #include "core/map.h"
 #include "core/ustring.h"
 #include "core/ustring.h"
 
 
-struct NETSolution {
+struct DotNetSolution {
 	String name;
 	String name;
 
 
-	void add_new_project(const String &p_name, const String &p_guid, const Vector<String> &p_extra_configs = Vector<String>());
+	struct ProjectInfo {
+		String guid;
+		String relpath; // Must be relative to the solution directory
+		Vector<String> configs;
+	};
+
+	void add_new_project(const String &p_name, const ProjectInfo &p_project_info);
+	bool has_project(const String &p_name) const;
+	const ProjectInfo &get_project_info(const String &p_name) const;
+	bool remove_project(const String &p_name);
 
 
 	Error save();
 	Error save();
 
 
 	bool set_path(const String &p_existing_path);
 	bool set_path(const String &p_existing_path);
+	String get_path();
 
 
-	NETSolution(const String &p_name);
+	DotNetSolution(const String &p_name);
 
 
 private:
 private:
-	struct ProjectInfo {
-		String guid;
-		Vector<String> configs;
-	};
-
 	String path;
 	String path;
 	Map<String, ProjectInfo> projects;
 	Map<String, ProjectInfo> projects;
 };
 };

+ 30 - 44
modules/mono/editor/godotsharp_builds.cpp

@@ -227,20 +227,24 @@ void GodotSharpBuilds::show_build_error_dialog(const String &p_message) {
 	MonoBottomPanel::get_singleton()->show_build_tab();
 	MonoBottomPanel::get_singleton()->show_build_tab();
 }
 }
 
 
-bool GodotSharpBuilds::build_api_sln(const String &p_name, const String &p_api_sln_dir, const String &p_config) {
+bool GodotSharpBuilds::build_api_sln(const String &p_api_sln_dir, const String &p_config) {
 
 
-	String api_sln_file = p_api_sln_dir.plus_file(p_name + ".sln");
-	String api_assembly_dir = p_api_sln_dir.plus_file("bin").plus_file(p_config);
-	String api_assembly_file = api_assembly_dir.plus_file(p_name + ".dll");
+	String api_sln_file = p_api_sln_dir.plus_file(API_SOLUTION_NAME ".sln");
 
 
-	if (!FileAccess::exists(api_assembly_file)) {
+	String core_api_assembly_dir = p_api_sln_dir.plus_file(CORE_API_ASSEMBLY_NAME).plus_file("bin").plus_file(p_config);
+	String core_api_assembly_file = core_api_assembly_dir.plus_file(CORE_API_ASSEMBLY_NAME ".dll");
+
+	String editor_api_assembly_dir = p_api_sln_dir.plus_file(EDITOR_API_ASSEMBLY_NAME).plus_file("bin").plus_file(p_config);
+	String editor_api_assembly_file = editor_api_assembly_dir.plus_file(EDITOR_API_ASSEMBLY_NAME ".dll");
+
+	if (!FileAccess::exists(core_api_assembly_file) || !FileAccess::exists(editor_api_assembly_file)) {
 		MonoBuildInfo api_build_info(api_sln_file, p_config);
 		MonoBuildInfo api_build_info(api_sln_file, p_config);
 		// TODO Replace this global NoWarn with '#pragma warning' directives on generated files,
 		// TODO Replace this global NoWarn with '#pragma warning' directives on generated files,
 		// once we start to actively document manually maintained C# classes
 		// once we start to actively document manually maintained C# classes
 		api_build_info.custom_props.push_back("NoWarn=1591"); // Ignore missing documentation warnings
 		api_build_info.custom_props.push_back("NoWarn=1591"); // Ignore missing documentation warnings
 
 
 		if (!GodotSharpBuilds::get_singleton()->build(api_build_info)) {
 		if (!GodotSharpBuilds::get_singleton()->build(api_build_info)) {
-			show_build_error_dialog("Failed to build " + p_name + " solution.");
+			show_build_error_dialog("Failed to build " API_SOLUTION_NAME " solution.");
 			return false;
 			return false;
 		}
 		}
 	}
 	}
@@ -302,9 +306,9 @@ String GodotSharpBuilds::_api_folder_name(APIAssembly::Type p_api_type) {
 		   "_" + String::num_uint64(CS_GLUE_VERSION);
 		   "_" + String::num_uint64(CS_GLUE_VERSION);
 }
 }
 
 
-bool GodotSharpBuilds::make_api_sln(APIAssembly::Type p_api_type) {
+bool GodotSharpBuilds::make_api_assembly(APIAssembly::Type p_api_type) {
 
 
-	String api_name = p_api_type == APIAssembly::API_CORE ? API_ASSEMBLY_NAME : EDITOR_API_ASSEMBLY_NAME;
+	String api_name = p_api_type == APIAssembly::API_CORE ? CORE_API_ASSEMBLY_NAME : EDITOR_API_ASSEMBLY_NAME;
 
 
 	String editor_prebuilt_api_dir = GodotSharpDirs::get_data_editor_prebuilt_api_dir();
 	String editor_prebuilt_api_dir = GodotSharpDirs::get_data_editor_prebuilt_api_dir();
 	String res_assemblies_dir = GodotSharpDirs::get_res_assemblies_dir();
 	String res_assemblies_dir = GodotSharpDirs::get_res_assemblies_dir();
@@ -317,55 +321,35 @@ bool GodotSharpBuilds::make_api_sln(APIAssembly::Type p_api_type) {
 
 
 	String api_build_config = "Release";
 	String api_build_config = "Release";
 
 
-	EditorProgress pr("mono_build_release_" + api_name, "Building " + api_name + " solution...", 3);
+	EditorProgress pr("mono_build_release_" API_SOLUTION_NAME, "Building " API_SOLUTION_NAME " solution...", 3);
 
 
-	pr.step("Generating " + api_name + " solution", 0);
+	pr.step("Generating " API_SOLUTION_NAME " solution", 0);
 
 
-	String core_api_sln_dir = GodotSharpDirs::get_mono_solutions_dir()
-									  .plus_file(_api_folder_name(APIAssembly::API_CORE))
-									  .plus_file(API_ASSEMBLY_NAME);
-	String editor_api_sln_dir = GodotSharpDirs::get_mono_solutions_dir()
-										.plus_file(_api_folder_name(APIAssembly::API_EDITOR))
-										.plus_file(EDITOR_API_ASSEMBLY_NAME);
+	String api_sln_dir = GodotSharpDirs::get_mono_solutions_dir()
+								 .plus_file(_api_folder_name(APIAssembly::API_CORE));
 
 
-	String api_sln_dir = p_api_type == APIAssembly::API_CORE ? core_api_sln_dir : editor_api_sln_dir;
-	String api_sln_file = api_sln_dir.plus_file(api_name + ".sln");
+	String api_sln_file = api_sln_dir.plus_file(API_SOLUTION_NAME ".sln");
 
 
 	if (!DirAccess::exists(api_sln_dir) || !FileAccess::exists(api_sln_file)) {
 	if (!DirAccess::exists(api_sln_dir) || !FileAccess::exists(api_sln_file)) {
-		String core_api_assembly;
-
-		if (p_api_type == APIAssembly::API_EDITOR) {
-			core_api_assembly = core_api_sln_dir.plus_file("bin")
-										.plus_file(api_build_config)
-										.plus_file(API_ASSEMBLY_NAME ".dll");
-		}
-
-#ifndef DEBUG_METHODS_ENABLED
-#error "How am I supposed to generate the bindings?"
-#endif
-
 		BindingsGenerator *gen = BindingsGenerator::get_singleton();
 		BindingsGenerator *gen = BindingsGenerator::get_singleton();
 		bool gen_verbose = OS::get_singleton()->is_stdout_verbose();
 		bool gen_verbose = OS::get_singleton()->is_stdout_verbose();
 
 
-		Error err = p_api_type == APIAssembly::API_CORE ?
-							gen->generate_cs_core_project(api_sln_dir, gen_verbose) :
-							gen->generate_cs_editor_project(api_sln_dir, core_api_assembly, gen_verbose);
-
+		Error err = gen->generate_cs_api(api_sln_dir, gen_verbose);
 		if (err != OK) {
 		if (err != OK) {
-			show_build_error_dialog("Failed to generate " + api_name + " solution. Error: " + itos(err));
+			show_build_error_dialog("Failed to generate " API_SOLUTION_NAME " solution. Error: " + itos(err));
 			return false;
 			return false;
 		}
 		}
 	}
 	}
 
 
-	pr.step("Building " + api_name + " solution", 1);
+	pr.step("Building " API_SOLUTION_NAME " solution", 1);
 
 
-	if (!GodotSharpBuilds::build_api_sln(api_name, api_sln_dir, api_build_config))
+	if (!GodotSharpBuilds::build_api_sln(api_sln_dir, api_build_config))
 		return false;
 		return false;
 
 
 	pr.step("Copying " + api_name + " assembly", 2);
 	pr.step("Copying " + api_name + " assembly", 2);
 
 
 	// Copy the built assembly to the assemblies directory
 	// Copy the built assembly to the assemblies directory
-	String api_assembly_dir = api_sln_dir.plus_file("bin").plus_file(api_build_config);
+	String api_assembly_dir = api_sln_dir.plus_file(api_name).plus_file("bin").plus_file(api_build_config);
 	if (!GodotSharpBuilds::copy_api_assembly(api_assembly_dir, res_assemblies_dir, api_name, p_api_type))
 	if (!GodotSharpBuilds::copy_api_assembly(api_assembly_dir, res_assemblies_dir, api_name, p_api_type))
 		return false;
 		return false;
 
 
@@ -377,10 +361,10 @@ bool GodotSharpBuilds::build_project_blocking(const String &p_config) {
 	if (!FileAccess::exists(GodotSharpDirs::get_project_sln_path()))
 	if (!FileAccess::exists(GodotSharpDirs::get_project_sln_path()))
 		return true; // No solution to build
 		return true; // No solution to build
 
 
-	if (!GodotSharpBuilds::make_api_sln(APIAssembly::API_CORE))
+	if (!GodotSharpBuilds::make_api_assembly(APIAssembly::API_CORE))
 		return false;
 		return false;
 
 
-	if (!GodotSharpBuilds::make_api_sln(APIAssembly::API_EDITOR))
+	if (!GodotSharpBuilds::make_api_assembly(APIAssembly::API_EDITOR))
 		return false;
 		return false;
 
 
 	EditorProgress pr("mono_project_debug_build", "Building project solution...", 1);
 	EditorProgress pr("mono_project_debug_build", "Building project solution...", 1);
@@ -403,11 +387,13 @@ bool GodotSharpBuilds::editor_build_callback() {
 	Error metadata_err = CSharpProject::generate_scripts_metadata(GodotSharpDirs::get_project_csproj_path(), scripts_metadata_path_editor);
 	Error metadata_err = CSharpProject::generate_scripts_metadata(GodotSharpDirs::get_project_csproj_path(), scripts_metadata_path_editor);
 	ERR_FAIL_COND_V(metadata_err != OK, false);
 	ERR_FAIL_COND_V(metadata_err != OK, false);
 
 
-	DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
-	Error copy_err = da->copy(scripts_metadata_path_editor, scripts_metadata_path_player);
+	if (FileAccess::exists(scripts_metadata_path_editor)) {
+		DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+		Error copy_err = da->copy(scripts_metadata_path_editor, scripts_metadata_path_player);
 
 
-	ERR_EXPLAIN("Failed to copy scripts metadata file");
-	ERR_FAIL_COND_V(copy_err != OK, false);
+		ERR_EXPLAIN("Failed to copy scripts metadata file");
+		ERR_FAIL_COND_V(copy_err != OK, false);
+	}
 
 
 	return build_project_blocking("Tools");
 	return build_project_blocking("Tools");
 }
 }

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

@@ -84,10 +84,10 @@ public:
 	bool build(const MonoBuildInfo &p_build_info);
 	bool build(const MonoBuildInfo &p_build_info);
 	bool build_async(const MonoBuildInfo &p_build_info, GodotSharpBuild_ExitCallback p_callback = NULL);
 	bool build_async(const MonoBuildInfo &p_build_info, GodotSharpBuild_ExitCallback p_callback = NULL);
 
 
-	static bool build_api_sln(const String &p_name, const String &p_api_sln_dir, const String &p_config);
+	static bool build_api_sln(const String &p_api_sln_dir, const String &p_config);
 	static bool copy_api_assembly(const String &p_src_dir, const String &p_dst_dir, const String &p_assembly_name, APIAssembly::Type p_api_type);
 	static bool copy_api_assembly(const String &p_src_dir, const String &p_dst_dir, const String &p_assembly_name, APIAssembly::Type p_api_type);
 
 
-	static bool make_api_sln(APIAssembly::Type p_api_type);
+	static bool make_api_assembly(APIAssembly::Type p_api_type);
 
 
 	static bool build_project_blocking(const String &p_config);
 	static bool build_project_blocking(const String &p_config);
 
 

+ 14 - 10
modules/mono/editor/godotsharp_editor.cpp

@@ -42,8 +42,8 @@
 #include "../utils/path_utils.h"
 #include "../utils/path_utils.h"
 #include "bindings_generator.h"
 #include "bindings_generator.h"
 #include "csharp_project.h"
 #include "csharp_project.h"
+#include "dotnet_solution.h"
 #include "godotsharp_export.h"
 #include "godotsharp_export.h"
-#include "net_solution.h"
 
 
 #ifdef OSX_ENABLED
 #ifdef OSX_ENABLED
 #include "../utils/osx_utils.h"
 #include "../utils/osx_utils.h"
@@ -71,17 +71,21 @@ bool GodotSharpEditor::_create_project_solution() {
 
 
 	if (guid.length()) {
 	if (guid.length()) {
 
 
-		NETSolution solution(name);
+		DotNetSolution solution(name);
 
 
 		if (!solution.set_path(path)) {
 		if (!solution.set_path(path)) {
 			show_error_dialog(TTR("Failed to create solution."));
 			show_error_dialog(TTR("Failed to create solution."));
 			return false;
 			return false;
 		}
 		}
 
 
-		Vector<String> extra_configs;
-		extra_configs.push_back("Tools");
+		DotNetSolution::ProjectInfo proj_info;
+		proj_info.guid = guid;
+		proj_info.relpath = name + ".csproj";
+		proj_info.configs.push_back("Debug");
+		proj_info.configs.push_back("Release");
+		proj_info.configs.push_back("Tools");
 
 
-		solution.add_new_project(name, guid, extra_configs);
+		solution.add_new_project(name, proj_info);
 
 
 		Error sln_error = solution.save();
 		Error sln_error = solution.save();
 
 
@@ -90,10 +94,10 @@ bool GodotSharpEditor::_create_project_solution() {
 			return false;
 			return false;
 		}
 		}
 
 
-		if (!GodotSharpBuilds::make_api_sln(APIAssembly::API_CORE))
+		if (!GodotSharpBuilds::make_api_assembly(APIAssembly::API_CORE))
 			return false;
 			return false;
 
 
-		if (!GodotSharpBuilds::make_api_sln(APIAssembly::API_EDITOR))
+		if (!GodotSharpBuilds::make_api_assembly(APIAssembly::API_EDITOR))
 			return false;
 			return false;
 
 
 		pr.step(TTR("Done"));
 		pr.step(TTR("Done"));
@@ -122,15 +126,15 @@ void GodotSharpEditor::_make_api_solutions_if_needed_impl() {
 	// If the project has a solution and C# project make sure the API assemblies are present and up to date
 	// If the project has a solution and C# project make sure the API assemblies are present and up to date
 	String res_assemblies_dir = GodotSharpDirs::get_res_assemblies_dir();
 	String res_assemblies_dir = GodotSharpDirs::get_res_assemblies_dir();
 
 
-	if (!FileAccess::exists(res_assemblies_dir.plus_file(API_ASSEMBLY_NAME ".dll")) ||
+	if (!FileAccess::exists(res_assemblies_dir.plus_file(CORE_API_ASSEMBLY_NAME ".dll")) ||
 			GDMono::get_singleton()->metadata_is_api_assembly_invalidated(APIAssembly::API_CORE)) {
 			GDMono::get_singleton()->metadata_is_api_assembly_invalidated(APIAssembly::API_CORE)) {
-		if (!GodotSharpBuilds::make_api_sln(APIAssembly::API_CORE))
+		if (!GodotSharpBuilds::make_api_assembly(APIAssembly::API_CORE))
 			return;
 			return;
 	}
 	}
 
 
 	if (!FileAccess::exists(res_assemblies_dir.plus_file(EDITOR_API_ASSEMBLY_NAME ".dll")) ||
 	if (!FileAccess::exists(res_assemblies_dir.plus_file(EDITOR_API_ASSEMBLY_NAME ".dll")) ||
 			GDMono::get_singleton()->metadata_is_api_assembly_invalidated(APIAssembly::API_EDITOR)) {
 			GDMono::get_singleton()->metadata_is_api_assembly_invalidated(APIAssembly::API_EDITOR)) {
-		if (!GodotSharpBuilds::make_api_sln(APIAssembly::API_EDITOR))
+		if (!GodotSharpBuilds::make_api_assembly(APIAssembly::API_EDITOR))
 			return; // Redundant? I don't think so
 			return; // Redundant? I don't think so
 	}
 	}
 }
 }

+ 2 - 1
modules/mono/godotsharp_defs.h

@@ -36,7 +36,8 @@
 #define BINDINGS_GLOBAL_SCOPE_CLASS "GD"
 #define BINDINGS_GLOBAL_SCOPE_CLASS "GD"
 #define BINDINGS_PTR_FIELD "ptr"
 #define BINDINGS_PTR_FIELD "ptr"
 #define BINDINGS_NATIVE_NAME_FIELD "nativeName"
 #define BINDINGS_NATIVE_NAME_FIELD "nativeName"
-#define API_ASSEMBLY_NAME "GodotSharp"
+#define API_SOLUTION_NAME "GodotSharp"
+#define CORE_API_ASSEMBLY_NAME "GodotSharp"
 #define EDITOR_API_ASSEMBLY_NAME "GodotSharpEditor"
 #define EDITOR_API_ASSEMBLY_NAME "GodotSharpEditor"
 #define EDITOR_TOOLS_ASSEMBLY_NAME "GodotSharpTools"
 #define EDITOR_TOOLS_ASSEMBLY_NAME "GodotSharpTools"
 
 

+ 4 - 4
modules/mono/mono_gd/gd_mono.cpp

@@ -496,12 +496,12 @@ bool GDMono::_load_core_api_assembly() {
 	}
 	}
 #endif
 #endif
 
 
-	String assembly_path = GodotSharpDirs::get_res_assemblies_dir().plus_file(API_ASSEMBLY_NAME ".dll");
+	String assembly_path = GodotSharpDirs::get_res_assemblies_dir().plus_file(CORE_API_ASSEMBLY_NAME ".dll");
 
 
 	if (!FileAccess::exists(assembly_path))
 	if (!FileAccess::exists(assembly_path))
 		return false;
 		return false;
 
 
-	bool success = load_assembly_from(API_ASSEMBLY_NAME,
+	bool success = load_assembly_from(CORE_API_ASSEMBLY_NAME,
 			assembly_path,
 			assembly_path,
 			&core_api_assembly);
 			&core_api_assembly);
 
 
@@ -635,7 +635,7 @@ void GDMono::metadata_set_api_assembly_invalidated(APIAssembly::Type p_api_type,
 
 
 	String assembly_path = GodotSharpDirs::get_res_assemblies_dir()
 	String assembly_path = GodotSharpDirs::get_res_assemblies_dir()
 								   .plus_file(p_api_type == APIAssembly::API_CORE ?
 								   .plus_file(p_api_type == APIAssembly::API_CORE ?
-													  API_ASSEMBLY_NAME ".dll" :
+													  CORE_API_ASSEMBLY_NAME ".dll" :
 													  EDITOR_API_ASSEMBLY_NAME ".dll");
 													  EDITOR_API_ASSEMBLY_NAME ".dll");
 
 
 	ERR_FAIL_COND(!FileAccess::exists(assembly_path));
 	ERR_FAIL_COND(!FileAccess::exists(assembly_path));
@@ -666,7 +666,7 @@ bool GDMono::metadata_is_api_assembly_invalidated(APIAssembly::Type p_api_type)
 
 
 	String assembly_path = GodotSharpDirs::get_res_assemblies_dir()
 	String assembly_path = GodotSharpDirs::get_res_assemblies_dir()
 								   .plus_file(p_api_type == APIAssembly::API_CORE ?
 								   .plus_file(p_api_type == APIAssembly::API_CORE ?
-													  API_ASSEMBLY_NAME ".dll" :
+													  CORE_API_ASSEMBLY_NAME ".dll" :
 													  EDITOR_API_ASSEMBLY_NAME ".dll");
 													  EDITOR_API_ASSEMBLY_NAME ".dll");
 
 
 	if (!FileAccess::exists(assembly_path))
 	if (!FileAccess::exists(assembly_path))

+ 10 - 10
modules/mono/mono_gd/gd_mono_utils.cpp

@@ -631,36 +631,36 @@ void set_pending_exception(MonoException *p_exc) {
 _THREAD_LOCAL_(int)
 _THREAD_LOCAL_(int)
 current_invoke_count = 0;
 current_invoke_count = 0;
 
 
-MonoObject *runtime_invoke(MonoMethod *p_method, void *p_obj, void **p_params, MonoException **p_exc) {
+MonoObject *runtime_invoke(MonoMethod *p_method, void *p_obj, void **p_params, MonoException **r_exc) {
 	GD_MONO_BEGIN_RUNTIME_INVOKE;
 	GD_MONO_BEGIN_RUNTIME_INVOKE;
-	MonoObject *ret = mono_runtime_invoke(p_method, p_obj, p_params, (MonoObject **)p_exc);
+	MonoObject *ret = mono_runtime_invoke(p_method, p_obj, p_params, (MonoObject **)r_exc);
 	GD_MONO_END_RUNTIME_INVOKE;
 	GD_MONO_END_RUNTIME_INVOKE;
 	return ret;
 	return ret;
 }
 }
 
 
-MonoObject *runtime_invoke_array(MonoMethod *p_method, void *p_obj, MonoArray *p_params, MonoException **p_exc) {
+MonoObject *runtime_invoke_array(MonoMethod *p_method, void *p_obj, MonoArray *p_params, MonoException **r_exc) {
 	GD_MONO_BEGIN_RUNTIME_INVOKE;
 	GD_MONO_BEGIN_RUNTIME_INVOKE;
-	MonoObject *ret = mono_runtime_invoke_array(p_method, p_obj, p_params, (MonoObject **)p_exc);
+	MonoObject *ret = mono_runtime_invoke_array(p_method, p_obj, p_params, (MonoObject **)r_exc);
 	GD_MONO_END_RUNTIME_INVOKE;
 	GD_MONO_END_RUNTIME_INVOKE;
 	return ret;
 	return ret;
 }
 }
 
 
-MonoString *object_to_string(MonoObject *p_obj, MonoException **p_exc) {
+MonoString *object_to_string(MonoObject *p_obj, MonoException **r_exc) {
 	GD_MONO_BEGIN_RUNTIME_INVOKE;
 	GD_MONO_BEGIN_RUNTIME_INVOKE;
-	MonoString *ret = mono_object_to_string(p_obj, (MonoObject **)p_exc);
+	MonoString *ret = mono_object_to_string(p_obj, (MonoObject **)r_exc);
 	GD_MONO_END_RUNTIME_INVOKE;
 	GD_MONO_END_RUNTIME_INVOKE;
 	return ret;
 	return ret;
 }
 }
 
 
-void property_set_value(MonoProperty *p_prop, void *p_obj, void **p_params, MonoException **p_exc) {
+void property_set_value(MonoProperty *p_prop, void *p_obj, void **p_params, MonoException **r_exc) {
 	GD_MONO_BEGIN_RUNTIME_INVOKE;
 	GD_MONO_BEGIN_RUNTIME_INVOKE;
-	mono_property_set_value(p_prop, p_obj, p_params, (MonoObject **)p_exc);
+	mono_property_set_value(p_prop, p_obj, p_params, (MonoObject **)r_exc);
 	GD_MONO_END_RUNTIME_INVOKE;
 	GD_MONO_END_RUNTIME_INVOKE;
 }
 }
 
 
-MonoObject *property_get_value(MonoProperty *p_prop, void *p_obj, void **p_params, MonoException **p_exc) {
+MonoObject *property_get_value(MonoProperty *p_prop, void *p_obj, void **p_params, MonoException **r_exc) {
 	GD_MONO_BEGIN_RUNTIME_INVOKE;
 	GD_MONO_BEGIN_RUNTIME_INVOKE;
-	MonoObject *ret = mono_property_get_value(p_prop, p_obj, p_params, (MonoObject **)p_exc);
+	MonoObject *ret = mono_property_get_value(p_prop, p_obj, p_params, (MonoObject **)r_exc);
 	GD_MONO_END_RUNTIME_INVOKE;
 	GD_MONO_END_RUNTIME_INVOKE;
 	return ret;
 	return ret;
 }
 }

+ 5 - 5
modules/mono/mono_gd/gd_mono_utils.h

@@ -233,13 +233,13 @@ _FORCE_INLINE_ int &get_runtime_invoke_count_ref() {
 	return current_invoke_count;
 	return current_invoke_count;
 }
 }
 
 
-MonoObject *runtime_invoke(MonoMethod *p_method, void *p_obj, void **p_params, MonoException **p_exc);
-MonoObject *runtime_invoke_array(MonoMethod *p_method, void *p_obj, MonoArray *p_params, MonoException **p_exc);
+MonoObject *runtime_invoke(MonoMethod *p_method, void *p_obj, void **p_params, MonoException **r_exc);
+MonoObject *runtime_invoke_array(MonoMethod *p_method, void *p_obj, MonoArray *p_params, MonoException **r_exc);
 
 
-MonoString *object_to_string(MonoObject *p_obj, MonoException **p_exc);
+MonoString *object_to_string(MonoObject *p_obj, MonoException **r_exc);
 
 
-void property_set_value(MonoProperty *p_prop, void *p_obj, void **p_params, MonoException **p_exc);
-MonoObject *property_get_value(MonoProperty *p_prop, void *p_obj, void **p_params, MonoException **p_exc);
+void property_set_value(MonoProperty *p_prop, void *p_obj, void **p_params, MonoException **r_exc);
+MonoObject *property_get_value(MonoProperty *p_prop, void *p_obj, void **p_params, MonoException **r_exc);
 
 
 uint64_t unbox_enum_value(MonoObject *p_boxed, MonoType *p_enum_basetype, bool &r_error);
 uint64_t unbox_enum_value(MonoObject *p_boxed, MonoType *p_enum_basetype, bool &r_error);
 
 

+ 6 - 4
modules/mono/utils/path_utils.cpp

@@ -88,7 +88,7 @@ void fix_path(const String &p_path, String &r_out) {
 bool rel_path_to_abs(const String &p_existing_path, String &r_abs_path) {
 bool rel_path_to_abs(const String &p_existing_path, String &r_abs_path) {
 #ifdef WINDOWS_ENABLED
 #ifdef WINDOWS_ENABLED
 	CharType ret[_MAX_PATH];
 	CharType ret[_MAX_PATH];
-	if (_wfullpath(ret, p_existing_path.c_str(), _MAX_PATH)) {
+	if (::_wfullpath(ret, p_existing_path.c_str(), _MAX_PATH)) {
 		String abspath = String(ret).replace("\\", "/");
 		String abspath = String(ret).replace("\\", "/");
 		int pos = abspath.find(":/");
 		int pos = abspath.find(":/");
 		if (pos != -1) {
 		if (pos != -1) {
@@ -99,10 +99,12 @@ bool rel_path_to_abs(const String &p_existing_path, String &r_abs_path) {
 		return true;
 		return true;
 	}
 	}
 #else
 #else
-	char ret[PATH_MAX];
-	if (realpath(p_existing_path.utf8().get_data(), ret)) {
+	char *resolved_path = ::realpath(p_existing_path.utf8().get_data(), NULL);
+	if (resolved_path) {
 		String retstr;
 		String retstr;
-		if (!retstr.parse_utf8(ret)) {
+		bool success = !retstr.parse_utf8(resolved_path);
+		::free(resolved_path);
+		if (success) {
 			r_abs_path = retstr;
 			r_abs_path = retstr;
 			return true;
 			return true;
 		}
 		}