From 270af6fa089ccfb93ace68ada8d476bd902b10fa Mon Sep 17 00:00:00 2001 From: Ignacio Etcheverry Date: Wed, 3 Jul 2019 09:44:53 +0200 Subject: Re-write mono module editor code in C# Make the build system automatically build the C# Api assemblies to be shipped with the editor. Make the editor, editor player and debug export templates use Api assemblies built with debug symbols. Always run MSBuild to build the editor tools and Api assemblies when building Godot. Several bugs fixed related to assembly hot reloading and restoring state. Fix StringExtensions internal calls not being registered correctly, resulting in MissingMethodException. --- modules/mono/editor/godotsharp_builds.cpp | 632 ------------------------------ 1 file changed, 632 deletions(-) delete mode 100644 modules/mono/editor/godotsharp_builds.cpp (limited to 'modules/mono/editor/godotsharp_builds.cpp') diff --git a/modules/mono/editor/godotsharp_builds.cpp b/modules/mono/editor/godotsharp_builds.cpp deleted file mode 100644 index a962d6df27..0000000000 --- a/modules/mono/editor/godotsharp_builds.cpp +++ /dev/null @@ -1,632 +0,0 @@ -/*************************************************************************/ -/* godotsharp_builds.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 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 "godotsharp_builds.h" - -#include "core/os/os.h" -#include "core/vector.h" -#include "main/main.h" - -#include "../glue/cs_glue_version.gen.h" -#include "../godotsharp_dirs.h" -#include "../mono_gd/gd_mono_class.h" -#include "../mono_gd/gd_mono_marshal.h" -#include "../utils/path_utils.h" -#include "bindings_generator.h" -#include "csharp_project.h" -#include "godotsharp_editor.h" - -#define PROP_NAME_MSBUILD_MONO "MSBuild (Mono)" -#define PROP_NAME_MSBUILD_VS "MSBuild (VS Build Tools)" -#define PROP_NAME_XBUILD "xbuild (Deprecated)" - -void godot_icall_BuildInstance_ExitCallback(MonoString *p_solution, MonoString *p_config, int p_exit_code) { - - String solution = GDMonoMarshal::mono_string_to_godot(p_solution); - String config = GDMonoMarshal::mono_string_to_godot(p_config); - GodotSharpBuilds::get_singleton()->build_exit_callback(MonoBuildInfo(solution, config), p_exit_code); -} - -static Vector _get_msbuild_hint_dirs() { - Vector ret; -#ifdef OSX_ENABLED - ret.push_back("/Library/Frameworks/Mono.framework/Versions/Current/bin/"); - ret.push_back("/usr/local/var/homebrew/linked/mono/bin/"); -#endif - ret.push_back("/opt/novell/mono/bin/"); - return ret; -} - -#ifdef UNIX_ENABLED -String _find_build_engine_on_unix(const String &p_name) { - String ret = path_which(p_name); - - if (ret.length()) - return ret; - - String ret_fallback = path_which(p_name + ".exe"); - if (ret_fallback.length()) - return ret_fallback; - - static Vector locations = _get_msbuild_hint_dirs(); - - for (int i = 0; i < locations.size(); i++) { - String hint_path = locations[i] + p_name; - - if (FileAccess::exists(hint_path)) { - return hint_path; - } - } - - return String(); -} -#endif - -MonoString *godot_icall_BuildInstance_get_MSBuildPath() { - - GodotSharpBuilds::BuildTool build_tool = GodotSharpBuilds::BuildTool(int(EditorSettings::get_singleton()->get("mono/builds/build_tool"))); - -#if defined(WINDOWS_ENABLED) - switch (build_tool) { - case GodotSharpBuilds::MSBUILD_VS: { - static String msbuild_tools_path; - - if (msbuild_tools_path.empty() || !FileAccess::exists(msbuild_tools_path)) { - // Try to search it again if it wasn't found last time or if it was removed from its location - msbuild_tools_path = MonoRegUtils::find_msbuild_tools_path(); - - if (msbuild_tools_path.empty()) { - ERR_PRINTS("Cannot find executable for '" PROP_NAME_MSBUILD_VS "'. Tried with path: " + msbuild_tools_path); - return NULL; - } - } - - if (!msbuild_tools_path.ends_with("\\")) - msbuild_tools_path += "\\"; - - return GDMonoMarshal::mono_string_from_godot(msbuild_tools_path + "MSBuild.exe"); - } break; - case GodotSharpBuilds::MSBUILD_MONO: { - String msbuild_path = GDMono::get_singleton()->get_mono_reg_info().bin_dir.plus_file("msbuild.bat"); - - if (!FileAccess::exists(msbuild_path)) { - ERR_PRINTS("Cannot find executable for '" PROP_NAME_MSBUILD_MONO "'. Tried with path: " + msbuild_path); - return NULL; - } - - return GDMonoMarshal::mono_string_from_godot(msbuild_path); - } break; - case GodotSharpBuilds::XBUILD: { - String xbuild_path = GDMono::get_singleton()->get_mono_reg_info().bin_dir.plus_file("xbuild.bat"); - - if (!FileAccess::exists(xbuild_path)) { - ERR_PRINTS("Cannot find executable for '" PROP_NAME_XBUILD "'. Tried with path: " + xbuild_path); - return NULL; - } - - return GDMonoMarshal::mono_string_from_godot(xbuild_path); - } break; - default: - ERR_EXPLAIN("You don't deserve to live"); - CRASH_NOW(); - } -#elif defined(UNIX_ENABLED) - static String msbuild_path; - static String xbuild_path; - - if (build_tool == GodotSharpBuilds::XBUILD) { - if (xbuild_path.empty() || !FileAccess::exists(xbuild_path)) { - // Try to search it again if it wasn't found last time or if it was removed from its location - xbuild_path = _find_build_engine_on_unix("msbuild"); - } - - if (xbuild_path.empty()) { - ERR_PRINT("Cannot find binary for '" PROP_NAME_XBUILD "'"); - return NULL; - } - } else { - if (msbuild_path.empty() || !FileAccess::exists(msbuild_path)) { - // Try to search it again if it wasn't found last time or if it was removed from its location - msbuild_path = _find_build_engine_on_unix("msbuild"); - } - - if (msbuild_path.empty()) { - ERR_PRINT("Cannot find binary for '" PROP_NAME_MSBUILD_MONO "'"); - return NULL; - } - } - - return GDMonoMarshal::mono_string_from_godot(build_tool != GodotSharpBuilds::XBUILD ? msbuild_path : xbuild_path); -#else - (void)build_tool; // UNUSED - - ERR_EXPLAIN("Not implemented on this platform"); - ERR_FAIL_V(NULL); -#endif -} - -MonoString *godot_icall_BuildInstance_get_MonoWindowsBinDir() { - -#if defined(WINDOWS_ENABLED) - const MonoRegInfo &mono_reg_info = GDMono::get_singleton()->get_mono_reg_info(); - if (mono_reg_info.bin_dir.length()) { - return GDMonoMarshal::mono_string_from_godot(mono_reg_info.bin_dir); - } - - ERR_EXPLAIN("Cannot find Mono's binaries directory in the registry"); - ERR_FAIL_V(NULL); -#else - return NULL; -#endif -} - -MonoBoolean godot_icall_BuildInstance_get_UsingMonoMSBuildOnWindows() { - -#if defined(WINDOWS_ENABLED) - return GodotSharpBuilds::BuildTool(int(EditorSettings::get_singleton()->get("mono/builds/build_tool"))) == GodotSharpBuilds::MSBUILD_MONO; -#else - return false; -#endif -} - -MonoBoolean godot_icall_BuildInstance_get_PrintBuildOutput() { - - return (bool)EDITOR_GET("mono/builds/print_build_output"); -} - -void GodotSharpBuilds::register_internal_calls() { - - static bool registered = false; - ERR_FAIL_COND(registered); - registered = true; - - mono_add_internal_call("GodotSharpTools.Build.BuildSystem::godot_icall_BuildInstance_ExitCallback", (void *)godot_icall_BuildInstance_ExitCallback); - mono_add_internal_call("GodotSharpTools.Build.BuildInstance::godot_icall_BuildInstance_get_MSBuildPath", (void *)godot_icall_BuildInstance_get_MSBuildPath); - mono_add_internal_call("GodotSharpTools.Build.BuildInstance::godot_icall_BuildInstance_get_MonoWindowsBinDir", (void *)godot_icall_BuildInstance_get_MonoWindowsBinDir); - mono_add_internal_call("GodotSharpTools.Build.BuildInstance::godot_icall_BuildInstance_get_UsingMonoMSBuildOnWindows", (void *)godot_icall_BuildInstance_get_UsingMonoMSBuildOnWindows); - mono_add_internal_call("GodotSharpTools.Build.BuildInstance::godot_icall_BuildInstance_get_PrintBuildOutput", (void *)godot_icall_BuildInstance_get_PrintBuildOutput); -} - -void GodotSharpBuilds::show_build_error_dialog(const String &p_message) { - - GodotSharpEditor::get_singleton()->show_error_dialog(p_message, "Build error"); - MonoBottomPanel::get_singleton()->show_build_tab(); -} - -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(API_SOLUTION_NAME ".sln"); - - 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); - // TODO Replace this global NoWarn with '#pragma warning' directives on generated files, - // once we start to actively document manually maintained C# classes - api_build_info.custom_props.push_back("NoWarn=1591"); // Ignore missing documentation warnings - - if (!GodotSharpBuilds::get_singleton()->build(api_build_info)) { - show_build_error_dialog("Failed to build " API_SOLUTION_NAME " solution."); - return false; - } - } - - return true; -} - -bool GodotSharpBuilds::copy_api_assembly(const String &p_src_dir, const String &p_dst_dir, const String &p_assembly_name, APIAssembly::Type p_api_type) { - - // Create destination directory if needed - if (!DirAccess::exists(p_dst_dir)) { - DirAccess *da = DirAccess::create_for_path(p_dst_dir); - Error err = da->make_dir_recursive(p_dst_dir); - memdelete(da); - - if (err != OK) { - show_build_error_dialog("Failed to create destination directory for the API assemblies. Error: " + itos(err)); - return false; - } - } - - String assembly_file = p_assembly_name + ".dll"; - String assembly_src = p_src_dir.plus_file(assembly_file); - String assembly_dst = p_dst_dir.plus_file(assembly_file); - - if (!FileAccess::exists(assembly_dst) || - FileAccess::get_modified_time(assembly_src) > FileAccess::get_modified_time(assembly_dst) || - GDMono::get_singleton()->metadata_is_api_assembly_invalidated(p_api_type)) { - DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); - - String xml_file = p_assembly_name + ".xml"; - if (da->copy(p_src_dir.plus_file(xml_file), p_dst_dir.plus_file(xml_file)) != OK) - WARN_PRINTS("Failed to copy " + xml_file); - - String pdb_file = p_assembly_name + ".pdb"; - if (da->copy(p_src_dir.plus_file(pdb_file), p_dst_dir.plus_file(pdb_file)) != OK) - WARN_PRINTS("Failed to copy " + pdb_file); - - Error err = da->copy(assembly_src, assembly_dst); - - if (err != OK) { - show_build_error_dialog("Failed to copy " + assembly_file); - return false; - } - - GDMono::get_singleton()->metadata_set_api_assembly_invalidated(p_api_type, false); - } - - return true; -} - -String GodotSharpBuilds::_api_folder_name(APIAssembly::Type p_api_type) { - - uint64_t api_hash = p_api_type == APIAssembly::API_CORE ? - GDMono::get_singleton()->get_api_core_hash() : - GDMono::get_singleton()->get_api_editor_hash(); - return String::num_uint64(api_hash) + - "_" + String::num_uint64(BindingsGenerator::get_version()) + - "_" + String::num_uint64(CS_GLUE_VERSION); -} - -bool GodotSharpBuilds::make_api_assembly(APIAssembly::Type p_api_type) { - - 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 res_assemblies_dir = GodotSharpDirs::get_res_assemblies_dir(); - - if (FileAccess::exists(editor_prebuilt_api_dir.plus_file(api_name + ".dll"))) { - EditorProgress pr("mono_copy_prebuilt_api_assembly", "Copying prebuilt " + api_name + " assembly...", 1); - pr.step("Copying " + api_name + " assembly", 0); - return GodotSharpBuilds::copy_api_assembly(editor_prebuilt_api_dir, res_assemblies_dir, api_name, p_api_type); - } - - String api_build_config = "Release"; - - EditorProgress pr("mono_build_release_" API_SOLUTION_NAME, "Building " API_SOLUTION_NAME " solution...", 3); - - pr.step("Generating " API_SOLUTION_NAME " solution", 0); - - String api_sln_dir = GodotSharpDirs::get_mono_solutions_dir() - .plus_file(_api_folder_name(APIAssembly::API_CORE)); - - String api_sln_file = api_sln_dir.plus_file(API_SOLUTION_NAME ".sln"); - - if (!DirAccess::exists(api_sln_dir) || !FileAccess::exists(api_sln_file)) { - BindingsGenerator bindings_generator; - - if (!OS::get_singleton()->is_stdout_verbose()) { - bindings_generator.set_log_print_enabled(false); - } - - Error err = bindings_generator.generate_cs_api(api_sln_dir); - if (err != OK) { - show_build_error_dialog("Failed to generate " API_SOLUTION_NAME " solution. Error: " + itos(err)); - return false; - } - } - - pr.step("Building " API_SOLUTION_NAME " solution", 1); - - if (!GodotSharpBuilds::build_api_sln(api_sln_dir, api_build_config)) - return false; - - pr.step("Copying " + api_name + " assembly", 2); - - // Copy the built assembly to the assemblies directory - 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)) - return false; - - return true; -} - -bool GodotSharpBuilds::build_project_blocking(const String &p_config, const Vector &p_godot_defines) { - - if (!FileAccess::exists(GodotSharpDirs::get_project_sln_path())) - return true; // No solution to build - - if (!GodotSharpBuilds::make_api_assembly(APIAssembly::API_CORE)) - return false; - - if (!GodotSharpBuilds::make_api_assembly(APIAssembly::API_EDITOR)) - return false; - - EditorProgress pr("mono_project_debug_build", "Building project solution...", 1); - pr.step("Building project solution", 0); - - MonoBuildInfo build_info(GodotSharpDirs::get_project_sln_path(), p_config); - - // Add Godot defines -#ifdef WINDOWS_ENABLED - String constants = "GodotDefineConstants=\""; -#else - String constants = "GodotDefineConstants=\\\""; -#endif - - for (int i = 0; i < p_godot_defines.size(); i++) { - constants += "GODOT_" + p_godot_defines[i].to_upper().replace("-", "_").replace(" ", "_").replace(";", "_") + ";"; - } - -#ifdef REAL_T_IS_DOUBLE - constants += "GODOT_REAL_T_IS_DOUBLE;"; -#endif - -#ifdef WINDOWS_ENABLED - constants += "\""; -#else - constants += "\\\""; -#endif - build_info.custom_props.push_back(constants); - - if (!GodotSharpBuilds::get_singleton()->build(build_info)) { - GodotSharpBuilds::show_build_error_dialog("Failed to build project solution"); - return false; - } - - return true; -} - -bool GodotSharpBuilds::editor_build_callback() { - - if (!FileAccess::exists(GodotSharpDirs::get_project_sln_path())) - return true; // No solution to build - - String scripts_metadata_path_editor = GodotSharpDirs::get_res_metadata_dir().plus_file("scripts_metadata.editor"); - String scripts_metadata_path_player = GodotSharpDirs::get_res_metadata_dir().plus_file("scripts_metadata.editor_player"); - - Error metadata_err = CSharpProject::generate_scripts_metadata(GodotSharpDirs::get_project_csproj_path(), scripts_metadata_path_editor); - ERR_FAIL_COND_V(metadata_err != OK, false); - - 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); - } - - Vector godot_defines; - godot_defines.push_back(OS::get_singleton()->get_name()); - godot_defines.push_back(sizeof(void *) == 4 ? "32" : "64"); - return build_project_blocking("Tools", godot_defines); -} - -GodotSharpBuilds *GodotSharpBuilds::singleton = NULL; - -void GodotSharpBuilds::build_exit_callback(const MonoBuildInfo &p_build_info, int p_exit_code) { - - BuildProcess *match = builds.getptr(p_build_info); - ERR_FAIL_NULL(match); - - BuildProcess &bp = *match; - bp.on_exit(p_exit_code); -} - -void GodotSharpBuilds::restart_build(MonoBuildTab *p_build_tab) { -} - -void GodotSharpBuilds::stop_build(MonoBuildTab *p_build_tab) { -} - -bool GodotSharpBuilds::build(const MonoBuildInfo &p_build_info) { - - BuildProcess *match = builds.getptr(p_build_info); - - if (match) { - BuildProcess &bp = *match; - bp.start(true); - return bp.exit_code == 0; - } else { - BuildProcess bp = BuildProcess(p_build_info); - bp.start(true); - builds.set(p_build_info, bp); - return bp.exit_code == 0; - } -} - -bool GodotSharpBuilds::build_async(const MonoBuildInfo &p_build_info, GodotSharpBuild_ExitCallback p_callback) { - - BuildProcess *match = builds.getptr(p_build_info); - - if (match) { - BuildProcess &bp = *match; - bp.start(); - return !bp.exited; // failed to start - } else { - BuildProcess bp = BuildProcess(p_build_info, p_callback); - bp.start(); - builds.set(p_build_info, bp); - return !bp.exited; // failed to start - } -} - -GodotSharpBuilds::GodotSharpBuilds() { - - singleton = this; - - EditorNode::get_singleton()->add_build_callback(&GodotSharpBuilds::editor_build_callback); - - // Build tool settings - EditorSettings *ed_settings = EditorSettings::get_singleton(); - -#ifdef WINDOWS_ENABLED - EDITOR_DEF("mono/builds/build_tool", MSBUILD_VS); -#else - EDITOR_DEF("mono/builds/build_tool", MSBUILD_MONO); -#endif - - ed_settings->add_property_hint(PropertyInfo(Variant::INT, "mono/builds/build_tool", PROPERTY_HINT_ENUM, - PROP_NAME_MSBUILD_MONO -#ifdef WINDOWS_ENABLED - "," PROP_NAME_MSBUILD_VS -#endif - "," PROP_NAME_XBUILD)); - - EDITOR_DEF("mono/builds/print_build_output", false); -} - -GodotSharpBuilds::~GodotSharpBuilds() { - - singleton = NULL; -} - -void GodotSharpBuilds::BuildProcess::on_exit(int p_exit_code) { - - exited = true; - exit_code = p_exit_code; - build_tab->on_build_exit(p_exit_code == 0 ? MonoBuildTab::RESULT_SUCCESS : MonoBuildTab::RESULT_ERROR); - build_instance.unref(); - - if (exit_callback) - exit_callback(exit_code); -} - -void GodotSharpBuilds::BuildProcess::start(bool p_blocking) { - - _GDMONO_SCOPE_DOMAIN_(TOOLS_DOMAIN) - - exit_code = -1; - - String log_dirpath = build_info.get_log_dirpath(); - - if (build_tab) { - build_tab->on_build_start(); - } else { - build_tab = memnew(MonoBuildTab(build_info, log_dirpath)); - MonoBottomPanel::get_singleton()->add_build_tab(build_tab); - } - - if (p_blocking) { - // Required in order to update the build tasks list - Main::iteration(); - } - - if (!exited) { - exited = true; - String message = "Tried to start build process, but it is already running"; - build_tab->on_build_exec_failed(message); - ERR_EXPLAIN(message); - ERR_FAIL(); - } - - exited = false; - - // Remove old issues file - - String issues_file = get_msbuild_issues_filename(); - 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(log_dirpath).plus_file(issues_file); - String message = "Cannot remove issues file: " + file_path; - build_tab->on_build_exec_failed(message); - ERR_EXPLAIN(message); - ERR_FAIL(); - } - } - - GDMonoClass *klass = GDMono::get_singleton()->get_editor_tools_assembly()->get_class("GodotSharpTools.Build", "BuildInstance"); - - MonoObject *mono_object = mono_object_new(mono_domain_get(), klass->get_mono_ptr()); - - // Construct - - Variant solution = build_info.solution; - Variant config = build_info.configuration; - - const Variant *ctor_args[2] = { &solution, &config }; - - MonoException *exc = NULL; - GDMonoMethod *ctor = klass->get_method(".ctor", 2); - ctor->invoke(mono_object, ctor_args, &exc); - - if (exc) { - exited = true; - GDMonoUtils::debug_unhandled_exception(exc); - String message = "The build constructor threw an exception.\n" + GDMonoUtils::get_exception_name_and_message(exc); - build_tab->on_build_exec_failed(message); - ERR_EXPLAIN(message); - ERR_FAIL(); - } - - // Call Build - - 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 }; - - exc = NULL; - GDMonoMethod *build_method = klass->get_method(p_blocking ? "Build" : "BuildAsync", 3); - build_method->invoke(mono_object, args, &exc); - - if (exc) { - exited = true; - GDMonoUtils::debug_unhandled_exception(exc); - String message = "The build method threw an exception.\n" + GDMonoUtils::get_exception_name_and_message(exc); - build_tab->on_build_exec_failed(message); - ERR_EXPLAIN(message); - ERR_FAIL(); - } - - // Build returned - - if (p_blocking) { - exited = true; - exit_code = klass->get_field("exitCode")->get_int_value(mono_object); - - if (exit_code != 0) { - String log_filepath = build_info.get_log_dirpath().plus_file(get_msbuild_log_filename()); - print_verbose("MSBuild exited with code: " + itos(exit_code) + ". Log file: " + log_filepath); - } - - build_tab->on_build_exit(exit_code == 0 ? MonoBuildTab::RESULT_SUCCESS : MonoBuildTab::RESULT_ERROR); - } else { - build_instance = MonoGCHandle::create_strong(mono_object); - exited = false; - } -} - -GodotSharpBuilds::BuildProcess::BuildProcess(const MonoBuildInfo &p_build_info, GodotSharpBuild_ExitCallback p_callback) : - build_info(p_build_info), - build_tab(NULL), - exit_callback(p_callback), - exited(true), - exit_code(-1) { -} -- cgit v1.2.3