Browse Source

Better logging for Mono errors and work on script debugging

BearishSun 9 years ago
parent
commit
46fe11386e

+ 39 - 18
Documentation/GitHub/compiling.md

@@ -8,32 +8,53 @@ It can be compiled using:
  - MSVC++ 14.0 (Visual Studio 2015)
  - Clang
  
-Use CMake to generate a VS solution, makefile or other type of build file. CMake root file is available at Source/CMakeLists.txt.
- 
 Banshee currently only compiles on Windows, but Mac & Linux ports are coming soon.
 
-# Third party dependencies
-Aside from the source code you will also need various third party dependencies. You may retrieve/compile those dependencies yourself by following a guide in "CompilingDependenciesManually.txt" (provided with the source code). 
+To compile follow these steps:
+ 1. Download source code
+ 2. Download [data files](#data) and extract them into the source directory
+ 3. Set up [third party dependencies](#dependencies)
+ 4. Generate a build file (e.g. Visual Studio solution or a Makefile) using CMake
+  - You can customize your build by choosing options like render API (DirectX, OpenGL), audio module and whether to build the entire editor or just the engine.
+ 5. Compile using your favorite tool
 
-Optionally, if you are using VS2015 you can avoid compiling dependencies by downloading the archive below, containing a set of pre-compiled dependencies. These should be extracted in the root of the directory containing Banshee source code.
+# <a name="data"></a>Data files
+Data files are non-code resources like images, shaders, etc. needed to run the editor, engine and example projects.
 
-[Download dependencies (VS2015)] (http://bearishsun.thalassa.feralhosting.com/BansheeDependencies_VS2015_v0.3.0.zip)
+[Download data files (Latest)] (http://bearishsun.thalassa.feralhosting.com/BansheeData_v0.3.0.zip)
 
 For older versions check the git release tag descriptions for links.
+ 
+# <a name="dependencies"></a>Third party dependencies
+Banshee relies on a variety of third party dependencies. We provide a set of pre-compiled dependencies needed for Visual Studio 2015, to save you the hassle of compiling them yourself. If you are not using VS2015 or want to compile the dependencies yourself, a guide is provided as well.
 
-## Windows dependencies
-For Windows additional dependencies not included in the dependencies package are needed.
+## Pre-compiled dependencies
+If going with the pre-compiled dependencies route, download the file below and extract it to the source directory.
 
-Make sure to:
- - Install Windows SDK if on Windows 8 or higher.
- - Install DirectX SDK.
-   - Set up DXSDK_DIR environment variable to point to the SDK install directory.
- - Install DirectX Debug Layer in Windows 10:
-   - Settings panel->System->Apps & features->Manage optional Features->Add a feature->Select "Graphics Tools"
+[Download dependencies (VS2015)] (http://bearishsun.thalassa.feralhosting.com/BansheeDependencies_VS2015_v0.3.0.zip)
 
-# Data files
-You will also need data files (non-code resources like images, shaders, etc.) in order to run the editor, engine and example projects.
+For older versions check the git release tag descriptions for links.
 
-[Download data files] (http://bearishsun.thalassa.feralhosting.com/BansheeData_v0.3.0.zip)
+You will also need to install the following dependencies manually:
+
+**DirectX SDK**
+ - Only for Windows 7 or earlier if using DirectX 11 render API
+ - Or for all Windows versions if using DirectX 9 render API
+ - Set up DXSDK_DIR environment variable pointing to the DirectX instalation
+ 
+**Windows SDK**
+ - Only for Windows 8 or later if using DirectX 11 render API
+ 
+**DirectX Debug Layer**
+ - Only for Windows 10 if using DirectX 11 render API
+ - Go to Settings panel (type "Settings" in Start)->System->Apps & features->Manage optional Features->Add a feature->Select "Graphics Tools"
+ 
+**FMOD Low Level Programmer API**
+ - Only if using the FMOD audio module (not selected by default)
+ - http://www.fmod.org/download/
+ - If CMake complains it cannot find FMOD, manually set the FMOD_INSTALL_DIRS to your installation directory 
+ - Copy the dynamic libraries from {INSTALLDIR}/api/lowlevel/lib into /bin folder in Banshee source code folder
+  - Use logging libraries for the Debug builds, and non-logging for OptimizedDebug and Release builds
+ 
+## Compiling dependencies manually
 
-For older versions check the git release tag descriptions for links.

+ 0 - 47
Source/BansheeEditorExec/BsEditorExec.cpp

@@ -2,10 +2,7 @@
 //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
 #include <iostream>
 #include <stdio.h>
-#include <fcntl.h>
-#include <io.h>
 #include "BsEditorApplication.h"
-#include "BsPlatform.h"
 #include "BsCrashHandler.h"
 
 #if BS_PLATFORM == BS_PLATFORM_WIN32
@@ -13,42 +10,6 @@
 
 using namespace BansheeEngine;
 
-#if BS_DEBUG_MODE
-void InitializeDebugConsole()
-{
-	//Create a console for this application
-	AllocConsole();
-
-	// Redirect standard output to console
-	freopen("CONIN$", "r", stdin);
-	freopen("CONOUT$", "w", stdout);
-	freopen("CONOUT$", "w", stderr);
-
-	// Clear streams to ensure they aren't in an error state
-	std::wcout.clear();
-	std::cout.clear();
-	std::wcerr.clear();
-	std::cerr.clear();
-	std::wcin.clear();
-	std::cin.clear();
-}
-
-void ShutdownDebugConsole()
-{
-	//Write "Press any key to exit"
-	HANDLE ConsoleOutput = GetStdHandle(STD_OUTPUT_HANDLE);
-	DWORD CharsWritten;
-	WriteConsole(ConsoleOutput, "\nPress any key to exit", 22, &CharsWritten, 0);
-	//Disable line-based input mode so we can get a single character
-	HANDLE ConsoleInput = GetStdHandle(STD_INPUT_HANDLE);
-	SetConsoleMode(ConsoleInput, 0);
-	//Read a single character
-	TCHAR InputBuffer;
-	DWORD CharsRead;
-	ReadConsole(ConsoleInput, &InputBuffer, 1, &CharsRead, 0);
-}
-#endif // End BS_DEBUG_MODE
-
 int CALLBACK WinMain(
 	_In_  HINSTANCE hInstance,
 	_In_  HINSTANCE hPrevInstance,
@@ -56,10 +17,6 @@ int CALLBACK WinMain(
 	_In_  int nCmdShow
 	)
 {
-#if BS_DEBUG_MODE
-	InitializeDebugConsole();
-#endif
-
 	CrashHandler::startUp();
 
 	__try
@@ -73,10 +30,6 @@ int CALLBACK WinMain(
 		PlatformUtility::terminate(true);
 	}
 
-#if BS_DEBUG_MODE
-	ShutdownDebugConsole();
-#endif
-
 	CrashHandler::shutDown();
 
 	return 0;

+ 1 - 0
Source/BansheeMono/Include/BsMonoAssembly.h

@@ -99,6 +99,7 @@ namespace BansheeEngine
 		WString mPath;
 		MonoImage* mMonoImage;
 		::MonoAssembly* mMonoAssembly;
+		UINT8* mDebugData;
 		bool mIsLoaded;
 		bool mIsDependency;
 		

+ 15 - 6
Source/BansheeMono/Source/BsMonoAssembly.cpp

@@ -40,8 +40,8 @@ namespace BansheeEngine
 	}
 
 	MonoAssembly::MonoAssembly(const WString& path, const String& name)
-		: mName(name), mPath(path), mMonoImage(nullptr), mMonoAssembly(nullptr), mIsLoaded(false), mIsDependency(false)
-		, mHaveCachedClassList(false)
+		: mName(name), mPath(path), mMonoImage(nullptr), mMonoAssembly(nullptr), mDebugData(nullptr), mIsLoaded(false)
+		, mIsDependency(false), mHaveCachedClassList(false)
 	{
 
 	}
@@ -81,6 +81,7 @@ namespace BansheeEngine
 		}
 
 		// Load MDB file
+#if BS_DEBUG_MODE
 		Path mdbPath = mPath + L".mdb";
 		if (FileSystem::exists(mdbPath))
 		{
@@ -89,13 +90,13 @@ namespace BansheeEngine
 			if (mdbStream != nullptr)
 			{
 				UINT32 mdbSize = (UINT32)mdbStream->size();
-				mono_byte* mdbData = (mono_byte*)bs_stack_alloc(mdbSize);
-				mdbStream->read(mdbData, mdbSize);
+				mDebugData = (UINT8*)bs_alloc(mdbSize);
+				mdbStream->read(mDebugData, mdbSize);
 
-				mono_debug_open_image_from_memory(image, mdbData, mdbSize);
-				bs_stack_free(mdbData);
+				mono_debug_open_image_from_memory(image, mDebugData, mdbSize);
 			}
 		}
+#endif
 
 		mMonoAssembly = mono_assembly_load_from_full(image, imageName.c_str(), &status, false);
 		if (status != MONO_IMAGE_OK || mMonoAssembly == nullptr)
@@ -136,6 +137,14 @@ namespace BansheeEngine
 		if(!mIsLoaded)
 			return;
 
+		if(mDebugData != nullptr)
+		{
+			mono_debug_close_image(mMonoImage);
+
+			bs_free(mDebugData);
+			mDebugData = nullptr;
+		}
+
 		for(auto& entry : mClassesByRaw)
 			bs_delete(entry.second);
 

+ 74 - 3
Source/BansheeMono/Source/BsMonoManager.cpp

@@ -15,6 +15,7 @@
 #include <mono/metadata/mono-config.h>
 #include <mono/metadata/mono-gc.h>
 #include <mono/metadata/mono-debug.h>
+#include <mono/utils/mono-logger.h>
 
 namespace BansheeEngine
 {
@@ -34,6 +35,60 @@ namespace BansheeEngine
 		{ MONO_LIB_DIR + "mono\\4.5", "v4.0.30319" }
 	};
 
+	void monoLogCallback(const char* logDomain, const char* logLevel, const char* message, mono_bool fatal, void* userData)
+	{
+		static const char* monoErrorLevels[] =
+		{
+			nullptr,
+			"error",
+			"critical",
+			"warning",
+			"message",
+			"info",
+			"debug"
+		};
+
+		UINT32 errorLevel = 0;
+		if (logLevel != nullptr)
+		{
+			for (UINT32 i = 1; i < 7; i++)
+			{
+				if (strcmp(monoErrorLevels[i], logLevel) == 0)
+				{
+					errorLevel = i;
+					break;
+				}
+			}
+		}
+
+		if (errorLevel == 0)
+		{
+			LOGERR(StringUtil::format("Mono: {0} in domain {1}", message, logDomain));
+		}
+		else if (errorLevel <= 2)
+		{
+			LOGERR(StringUtil::format("Mono: {0} in domain {1} [{2}]", message, logDomain, logLevel));
+		}
+		else if (errorLevel <= 3)
+		{
+			LOGWRN(StringUtil::format("Mono: {0} in domain {1} [{2}]", message, logDomain, logLevel));
+		}
+		else
+		{
+			LOGDBG(StringUtil::format("Mono: {0} in domain {1} [{2}]", message, logDomain, logLevel));
+		}
+	}
+
+	void monoPrintCallback(const char* string, mono_bool isStdout)
+	{
+		LOGWRN(StringUtil::format("Mono error: {0}", string));
+	}
+
+	void monoPrintErrorCallback(const char* string, mono_bool isStdout)
+	{
+		LOGERR(StringUtil::format("Mono error: {0}", string));
+	}
+
 	MonoManager::MonoManager()
 		:mScriptDomain(nullptr), mRootDomain(nullptr), mIsCoreLoaded(false)
 	{
@@ -45,10 +100,22 @@ namespace BansheeEngine
 		mono_set_assemblies_path(assembliesDir.toString().c_str());
 
 #if BS_DEBUG_MODE
-		mono_set_signal_chaining(true);
 		mono_debug_init(MONO_DEBUG_FORMAT_MONO);
+
+		char* options[] = {
+			"--soft-breakpoints",
+			"--debugger-agent=transport=dt_socket,address=127.0.0.1:17615,embedding=1,server=y,suspend=n"
+		};
+		mono_jit_parse_options(2, options);
+		mono_trace_set_level_string("warning"); // Note: Switch to "debug" for detailed output, disabled for now due to spam
+#else
+		mono_trace_set_level_string("warning");
 #endif
 
+		mono_trace_set_log_handler(monoLogCallback, this);
+		mono_trace_set_print_handler(monoPrintCallback);
+		mono_trace_set_printerr_handler(monoPrintErrorCallback);
+
 		mono_config_parse(nullptr);
 
 		mRootDomain = mono_jit_init_version("BansheeMono", MONO_VERSION_DATA[(int)MONO_VERSION].version.c_str());
@@ -83,12 +150,16 @@ namespace BansheeEngine
 			String appDomainName = toString(path);
 
 			mScriptDomain = mono_domain_create_appdomain(const_cast<char *>(appDomainName.c_str()), nullptr);
-			mono_domain_set(mScriptDomain, false);
+			mono_domain_set(mScriptDomain, true);
 
 			if (mScriptDomain == nullptr)
 			{
 				BS_EXCEPT(InternalErrorException, "Cannot create script app domain.");
 			}
+
+#if BS_DEBUG_MODE
+			mono_debug_domain_create(mScriptDomain);
+#endif
 		}
 
 		auto iterFind = mAssemblies.find(name);
@@ -197,7 +268,7 @@ namespace BansheeEngine
 		{
 			onDomainUnload();
 
-			mono_domain_set(mono_get_root_domain(), false);
+			mono_domain_set(mono_get_root_domain(), true);
 			mono_domain_finalize(mScriptDomain, 2000);
 
 			MonoObject* exception = nullptr;