Explorar o código

Merge pull request #19387 from neikeq/y

Mono fixes and improvements
Ignacio Etcheverry %!s(int64=7) %!d(string=hai) anos
pai
achega
b4f66e04e8

+ 27 - 10
modules/mono/editor/GodotSharpTools/Build/BuildSystem.cs

@@ -78,6 +78,8 @@ namespace GodotSharpTools.Build
 
         public bool Build(string loggerAssemblyPath, string loggerOutputDir, string[] customProperties = null)
         {
+            bool debugMSBuild = IsDebugMSBuildRequested();
+
             List<string> customPropertiesList = new List<string>();
 
             if (customProperties != null)
@@ -92,9 +94,10 @@ namespace GodotSharpTools.Build
 
             ProcessStartInfo startInfo = new ProcessStartInfo(GetMSBuildPath(), compilerArgs);
 
-            // No console output, thanks
-            startInfo.RedirectStandardOutput = true;
-            startInfo.RedirectStandardError = true;
+            bool redirectOutput = !debugMSBuild;
+
+            startInfo.RedirectStandardOutput = redirectOutput;
+            startInfo.RedirectStandardError = redirectOutput;
             startInfo.UseShellExecute = false;
 
             if (UsingMonoMSBuildOnWindows)
@@ -116,8 +119,11 @@ namespace GodotSharpTools.Build
 
                 process.Start();
 
-                process.BeginOutputReadLine();
-                process.BeginErrorReadLine();
+                if (redirectOutput)
+                {
+                    process.BeginOutputReadLine();
+                    process.BeginErrorReadLine();
+                }
 
                 process.WaitForExit();
 
@@ -129,6 +135,8 @@ namespace GodotSharpTools.Build
 
         public bool BuildAsync(string loggerAssemblyPath, string loggerOutputDir, string[] customProperties = null)
         {
+            bool debugMSBuild = IsDebugMSBuildRequested();
+
             if (process != null)
                 throw new InvalidOperationException("Already in use");
 
@@ -146,9 +154,10 @@ namespace GodotSharpTools.Build
 
             ProcessStartInfo startInfo = new ProcessStartInfo(GetMSBuildPath(), compilerArgs);
 
-            // No console output, thanks
-            startInfo.RedirectStandardOutput = true;
-            startInfo.RedirectStandardError = true;
+            bool redirectOutput = !debugMSBuild;
+
+            startInfo.RedirectStandardOutput = redirectOutput;
+            startInfo.RedirectStandardError = redirectOutput;
             startInfo.UseShellExecute = false;
 
             if (UsingMonoMSBuildOnWindows)
@@ -171,8 +180,11 @@ namespace GodotSharpTools.Build
 
             process.Start();
 
-            process.BeginOutputReadLine();
-            process.BeginErrorReadLine();
+            if (redirectOutput)
+            {
+                process.BeginOutputReadLine();
+                process.BeginErrorReadLine();
+            }
 
             return true;
         }
@@ -220,6 +232,11 @@ namespace GodotSharpTools.Build
             Dispose();
         }
 
+        private static bool IsDebugMSBuildRequested()
+        {
+            return Environment.GetEnvironmentVariable("GODOT_DEBUG_MSBUILD").Trim() == "1";
+        }
+
         public void Dispose()
         {
             if (process != null)

+ 7 - 6
modules/mono/editor/godotsharp_builds.cpp

@@ -461,12 +461,12 @@ void GodotSharpBuilds::BuildProcess::start(bool p_blocking) {
 
 	exit_code = -1;
 
-	String logs_dir = GodotSharpDirs::get_build_logs_dir().plus_file(build_info.solution.md5_text() + "_" + build_info.configuration);
+	String log_dirpath = build_info.get_log_dirpath();
 
 	if (build_tab) {
 		build_tab->on_build_start();
 	} else {
-		build_tab = memnew(MonoBuildTab(build_info, logs_dir));
+		build_tab = memnew(MonoBuildTab(build_info, log_dirpath));
 		MonoBottomPanel::get_singleton()->add_build_tab(build_tab);
 	}
 
@@ -488,12 +488,12 @@ void GodotSharpBuilds::BuildProcess::start(bool p_blocking) {
 	// Remove old issues file
 
 	String issues_file = "msbuild_issues.csv";
-	DirAccessRef d = DirAccess::create_for_path(logs_dir);
+	DirAccessRef d = DirAccess::create_for_path(log_dirpath);
 	if (d->file_exists(issues_file)) {
 		Error err = d->remove(issues_file);
 		if (err != OK) {
 			exited = true;
-			String file_path = ProjectSettings::get_singleton()->localize_path(logs_dir).plus_file(issues_file);
+			String file_path = ProjectSettings::get_singleton()->localize_path(log_dirpath).plus_file(issues_file);
 			String message = "Cannot remove issues file: " + file_path;
 			build_tab->on_build_exec_failed(message);
 			ERR_EXPLAIN(message);
@@ -527,8 +527,9 @@ void GodotSharpBuilds::BuildProcess::start(bool p_blocking) {
 
 	// Call Build
 
-	Variant logger_assembly = OS::get_singleton()->get_executable_path().get_base_dir().plus_file(EDITOR_TOOLS_ASSEMBLY_NAME) + ".dll";
-	Variant logger_output_dir = logs_dir;
+	String logger_assembly_path = GDMono::get_singleton()->get_editor_tools_assembly()->get_path();
+	Variant logger_assembly = ProjectSettings::get_singleton()->globalize_path(logger_assembly_path);
+	Variant logger_output_dir = log_dirpath;
 	Variant custom_props = build_info.custom_props;
 
 	const Variant *args[3] = { &logger_assembly, &logger_output_dir, &custom_props };

+ 46 - 14
modules/mono/editor/mono_bottom_panel.cpp

@@ -73,7 +73,7 @@ void MonoBottomPanel::_update_build_tabs_list() {
 
 			if (no_current_tab || current_tab == i) {
 				build_tabs_list->select(i);
-				_build_tab_item_selected(i);
+				_build_tabs_item_selected(i);
 			}
 		}
 	}
@@ -105,21 +105,27 @@ void MonoBottomPanel::show_build_tab() {
 	ERR_PRINT("Builds tab not found");
 }
 
-void MonoBottomPanel::_build_tab_item_selected(int p_idx) {
+void MonoBottomPanel::_build_tabs_item_selected(int p_idx) {
 
 	ERR_FAIL_INDEX(p_idx, build_tabs->get_tab_count());
+
 	build_tabs->set_current_tab(p_idx);
+	if (!build_tabs->is_visible())
+		build_tabs->set_visible(true);
+
+	warnings_btn->set_visible(true);
+	errors_btn->set_visible(true);
+	view_log_btn->set_visible(true);
 }
 
-void MonoBottomPanel::_build_tab_changed(int p_idx) {
+void MonoBottomPanel::_build_tabs_nothing_selected() {
 
-	if (p_idx < 0 || p_idx >= build_tabs->get_tab_count()) {
-		warnings_btn->set_visible(false);
-		errors_btn->set_visible(false);
-	} else {
-		warnings_btn->set_visible(true);
-		errors_btn->set_visible(true);
-	}
+	if (build_tabs->get_tab_count() != 0) // just in case
+		build_tabs->set_visible(false);
+
+	warnings_btn->set_visible(false);
+	errors_btn->set_visible(false);
+	view_log_btn->set_visible(false);
 }
 
 void MonoBottomPanel::_warnings_toggled(bool p_pressed) {
@@ -148,6 +154,22 @@ void MonoBottomPanel::_build_project_pressed() {
 	CSharpLanguage::get_singleton()->reload_assemblies_if_needed(true);
 }
 
+void MonoBottomPanel::_view_log_pressed() {
+
+	if (build_tabs_list->is_anything_selected()) {
+		Vector<int> selected_items = build_tabs_list->get_selected_items();
+		CRASH_COND(selected_items.size() != 1);
+		int selected_item = selected_items[0];
+
+		MonoBuildTab *build_tab = Object::cast_to<MonoBuildTab>(build_tabs->get_tab_control(selected_item));
+		ERR_FAIL_NULL(build_tab);
+
+		String log_dirpath = build_tab->get_build_info().get_log_dirpath();
+
+		OS::get_singleton()->shell_open(log_dirpath.plus_file("msbuild_log.txt"));
+	}
+}
+
 void MonoBottomPanel::_notification(int p_what) {
 
 	switch (p_what) {
@@ -163,10 +185,11 @@ void MonoBottomPanel::_notification(int p_what) {
 void MonoBottomPanel::_bind_methods() {
 
 	ClassDB::bind_method(D_METHOD("_build_project_pressed"), &MonoBottomPanel::_build_project_pressed);
+	ClassDB::bind_method(D_METHOD("_view_log_pressed"), &MonoBottomPanel::_view_log_pressed);
 	ClassDB::bind_method(D_METHOD("_warnings_toggled", "pressed"), &MonoBottomPanel::_warnings_toggled);
 	ClassDB::bind_method(D_METHOD("_errors_toggled", "pressed"), &MonoBottomPanel::_errors_toggled);
-	ClassDB::bind_method(D_METHOD("_build_tab_item_selected", "idx"), &MonoBottomPanel::_build_tab_item_selected);
-	ClassDB::bind_method(D_METHOD("_build_tab_changed", "idx"), &MonoBottomPanel::_build_tab_changed);
+	ClassDB::bind_method(D_METHOD("_build_tabs_item_selected", "idx"), &MonoBottomPanel::_build_tabs_item_selected);
+	ClassDB::bind_method(D_METHOD("_build_tabs_nothing_selected"), &MonoBottomPanel::_build_tabs_nothing_selected);
 }
 
 MonoBottomPanel::MonoBottomPanel(EditorNode *p_editor) {
@@ -223,6 +246,15 @@ MonoBottomPanel::MonoBottomPanel(EditorNode *p_editor) {
 		errors_btn->connect("toggled", this, "_errors_toggled");
 		toolbar_hbc->add_child(errors_btn);
 
+		toolbar_hbc->add_spacer();
+
+		view_log_btn = memnew(Button);
+		view_log_btn->set_text(TTR("View log"));
+		view_log_btn->set_focus_mode(FOCUS_NONE);
+		view_log_btn->set_visible(false);
+		view_log_btn->connect("pressed", this, "_view_log_pressed");
+		toolbar_hbc->add_child(view_log_btn);
+
 		HSplitContainer *hsc = memnew(HSplitContainer);
 		hsc->set_h_size_flags(SIZE_EXPAND_FILL);
 		hsc->set_v_size_flags(SIZE_EXPAND_FILL);
@@ -230,14 +262,14 @@ MonoBottomPanel::MonoBottomPanel(EditorNode *p_editor) {
 
 		build_tabs_list = memnew(ItemList);
 		build_tabs_list->set_h_size_flags(SIZE_EXPAND_FILL);
-		build_tabs_list->connect("item_selected", this, "_build_tab_item_selected");
+		build_tabs_list->connect("item_selected", this, "_build_tabs_item_selected");
+		build_tabs_list->connect("nothing_selected", this, "_build_tabs_nothing_selected");
 		hsc->add_child(build_tabs_list);
 
 		build_tabs = memnew(TabContainer);
 		build_tabs->set_tab_align(TabContainer::ALIGN_LEFT);
 		build_tabs->set_h_size_flags(SIZE_EXPAND_FILL);
 		build_tabs->set_tabs_visible(false);
-		build_tabs->connect("tab_changed", this, "_build_tab_changed");
 		hsc->add_child(build_tabs);
 	}
 }

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

@@ -53,16 +53,18 @@ class MonoBottomPanel : public VBoxContainer {
 
 	Button *warnings_btn;
 	Button *errors_btn;
+	Button *view_log_btn;
 
 	void _update_build_tabs_list();
 
-	void _build_tab_item_selected(int p_idx);
-	void _build_tab_changed(int p_idx);
+	void _build_tabs_item_selected(int p_idx);
+	void _build_tabs_nothing_selected();
 
 	void _warnings_toggled(bool p_pressed);
 	void _errors_toggled(bool p_pressed);
 
 	void _build_project_pressed();
+	void _view_log_pressed();
 
 	static MonoBottomPanel *singleton;
 

+ 62 - 0
modules/mono/editor/mono_build_info.cpp

@@ -0,0 +1,62 @@
+/*************************************************************************/
+/*  mono_build_info.cpp                                                  */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md)    */
+/*                                                                       */
+/* 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 "mono_build_info.h"
+
+#include "../godotsharp_dirs.h"
+#include "../mono_gd/gd_mono_utils.h"
+
+uint32_t MonoBuildInfo::Hasher::hash(const MonoBuildInfo &p_key) {
+
+	uint32_t hash = 0;
+
+	GDMonoUtils::hash_combine(hash, p_key.solution.hash());
+	GDMonoUtils::hash_combine(hash, p_key.configuration.hash());
+
+	return hash;
+}
+
+bool MonoBuildInfo::operator==(const MonoBuildInfo &p_b) const {
+
+	return p_b.solution == solution && p_b.configuration == configuration;
+}
+
+String MonoBuildInfo::get_log_dirpath() {
+
+	return GodotSharpDirs::get_build_logs_dir().plus_file(solution.md5_text() + "_" + configuration);
+}
+
+MonoBuildInfo::MonoBuildInfo() {}
+
+MonoBuildInfo::MonoBuildInfo(const String &p_solution, const String &p_config) {
+
+	solution = p_solution;
+	configuration = p_config;
+}

+ 7 - 17
modules/mono/editor/mono_build_info.h

@@ -31,35 +31,25 @@
 #ifndef MONO_BUILD_INFO_H
 #define MONO_BUILD_INFO_H
 
-#include "../mono_gd/gd_mono_utils.h"
+#include "core/ustring.h"
+#include "core/vector.h"
 
 struct MonoBuildInfo {
 
 	struct Hasher {
-		static _FORCE_INLINE_ uint32_t hash(const MonoBuildInfo &p_key) {
-			uint32_t hash = 0;
-
-			GDMonoUtils::hash_combine(hash, p_key.solution.hash());
-			GDMonoUtils::hash_combine(hash, p_key.configuration.hash());
-
-			return hash;
-		}
+		static uint32_t hash(const MonoBuildInfo &p_key);
 	};
 
 	String solution;
 	String configuration;
 	Vector<String> custom_props;
 
-	MonoBuildInfo() {}
+	bool operator==(const MonoBuildInfo &p_b) const;
 
-	MonoBuildInfo(const String &p_solution, const String &p_config) {
-		solution = p_solution;
-		configuration = p_config;
-	}
+	String get_log_dirpath();
 
-	bool operator==(const MonoBuildInfo &p_b) const {
-		return p_b.solution == solution && p_b.configuration == configuration;
-	}
+	MonoBuildInfo();
+	MonoBuildInfo(const String &p_solution, const String &p_config);
 };
 
 #endif // MONO_BUILD_INFO_H

+ 19 - 0
modules/mono/mono_gd/gd_mono_marshal.cpp

@@ -606,6 +606,8 @@ MonoArray *Array_to_mono_array(const Array &p_array) {
 
 Array mono_array_to_Array(MonoArray *p_array) {
 	Array ret;
+	if (!p_array)
+		return ret;
 	int length = mono_array_length(p_array);
 	ret.resize(length);
 
@@ -631,6 +633,8 @@ MonoArray *PoolIntArray_to_mono_array(const PoolIntArray &p_array) {
 
 PoolIntArray mono_array_to_PoolIntArray(MonoArray *p_array) {
 	PoolIntArray ret;
+	if (!p_array)
+		return ret;
 	int length = mono_array_length(p_array);
 	ret.resize(length);
 	for (int i = 0; i < length; i++) {
@@ -653,6 +657,8 @@ MonoArray *PoolByteArray_to_mono_array(const PoolByteArray &p_array) {
 
 PoolByteArray mono_array_to_PoolByteArray(MonoArray *p_array) {
 	PoolByteArray ret;
+	if (!p_array)
+		return ret;
 	int length = mono_array_length(p_array);
 	ret.resize(length);
 
@@ -676,6 +682,8 @@ MonoArray *PoolRealArray_to_mono_array(const PoolRealArray &p_array) {
 
 PoolRealArray mono_array_to_PoolRealArray(MonoArray *p_array) {
 	PoolRealArray ret;
+	if (!p_array)
+		return ret;
 	int length = mono_array_length(p_array);
 	ret.resize(length);
 
@@ -700,6 +708,8 @@ MonoArray *PoolStringArray_to_mono_array(const PoolStringArray &p_array) {
 
 PoolStringArray mono_array_to_PoolStringArray(MonoArray *p_array) {
 	PoolStringArray ret;
+	if (!p_array)
+		return ret;
 	int length = mono_array_length(p_array);
 	ret.resize(length);
 
@@ -732,6 +742,8 @@ MonoArray *PoolColorArray_to_mono_array(const PoolColorArray &p_array) {
 
 PoolColorArray mono_array_to_PoolColorArray(MonoArray *p_array) {
 	PoolColorArray ret;
+	if (!p_array)
+		return ret;
 	int length = mono_array_length(p_array);
 	ret.resize(length);
 
@@ -763,6 +775,8 @@ MonoArray *PoolVector2Array_to_mono_array(const PoolVector2Array &p_array) {
 
 PoolVector2Array mono_array_to_PoolVector2Array(MonoArray *p_array) {
 	PoolVector2Array ret;
+	if (!p_array)
+		return ret;
 	int length = mono_array_length(p_array);
 	ret.resize(length);
 
@@ -795,6 +809,8 @@ MonoArray *PoolVector3Array_to_mono_array(const PoolVector3Array &p_array) {
 
 PoolVector3Array mono_array_to_PoolVector3Array(MonoArray *p_array) {
 	PoolVector3Array ret;
+	if (!p_array)
+		return ret;
 	int length = mono_array_length(p_array);
 	ret.resize(length);
 
@@ -835,6 +851,9 @@ MonoObject *Dictionary_to_mono_object(const Dictionary &p_dict) {
 Dictionary mono_object_to_Dictionary(MonoObject *p_dict) {
 	Dictionary ret;
 
+	if (!p_dict)
+		return ret;
+
 	GDMonoUtils::MarshalUtils_DictToArrays dict_to_arrays = CACHED_METHOD_THUNK(MarshalUtils, DictionaryToArrays);
 
 	MonoArray *keys = NULL;