Quellcode durchsuchen

WIP: Linux port
- Mono compiler can now execute on Linux
- Fixed a crash caused by assembly reload not properly cleaning up after itself
- Fixing an issue with project library wildcard search
- Fixed a runtime error in script code cause by the new UUID format

Marko Pintera vor 8 Jahren
Ursprung
Commit
831af46d78

+ 1 - 1
Source/BansheeEditor/Library/BsProjectLibrary.cpp

@@ -596,7 +596,7 @@ namespace bs
 		WString replace(L"\\\\&");
 		WString escapedPattern = std::regex_replace(pattern, escape, replace, std::regex_constants::match_default | std::regex_constants::format_sed);
 
-		std::wregex wildcard(L"\\\\\\*");
+		std::wregex wildcard(L"\\\\\\\\\\*");
 		WString wildcardReplace(L".*");
 		WString searchPattern = std::regex_replace(escapedPattern, wildcard, L".*");
 

+ 1 - 1
Source/BansheeEditorExec/CMakeLists.txt

@@ -27,7 +27,7 @@ set_property(TARGET BansheeEditorExec PROPERTY FOLDER Executable)
 
 # Plugin dependencies
 add_engine_dependencies(BansheeEditorExec)
-add_dependencies(BansheeEditorExec BansheeFBXImporter BansheeFontImporter BansheeFreeImgImporter SBansheeEditor)
+add_dependencies(BansheeEditorExec BansheeFBXImporter BansheeFontImporter BansheeFreeImgImporter SBansheeEditor MonoExec)
 
 # Compiler flags
 if(MSVC)

+ 2 - 2
Source/BansheeEngine/Utility/BsPaths.h

@@ -16,7 +16,7 @@ namespace bs
 	constexpr const char* GAME_RESOURCE_MAPPING_NAME = "ResourceMapping.asset";
 
 
-	/** Contains common engine paths. */
+	/** Contains common engine paths and utility method for searching for paths. */
 	class BS_EXPORT Paths
 	{
 	public:
@@ -45,7 +45,7 @@ namespace bs
 		 * Searches common locations for a specified path by querying if the file/directory exists and returns the found 
 		 * path.
 		 * 			
-		 * @param[in]	path	Relative path to search for (for example "Data\").				
+		 * @param[in]	path	Relative path to search for (for example "Data\").
 		 * @return				Path at which the relative path was found at. This path will be relative to the working 
 		 *						directory.
 		 */

+ 3 - 2
Source/BansheeMono/BsMonoAssembly.cpp

@@ -152,8 +152,9 @@ namespace bs
 
 		if(mMonoImage != nullptr && !mIsDependency)
 		{
-			// Note: I used to call mono_image_close and mono_assembly_close here but those 
-			// didn't seem to be necessary and were just crashing the program.
+			// Make sure to close the image, otherwise when we try to re-load this assembly the Mono will return the cached
+			// image
+			mono_image_close(mMonoImage);
 			mMonoImage = nullptr;
 		}
 

+ 63 - 0
Source/BansheeMono/BsMonoExec.cpp

@@ -0,0 +1,63 @@
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2017 Marko Pintera ([email protected]). All rights reserved. **********************//
+#ifdef _WIN32
+	#include <direct.h>
+	#define getcwd _getcwd
+#else
+	#include <unistd.h>
+#endif
+
+#include <mono/jit/jit.h>
+#include <mono/metadata/assembly.h>
+#include <mono/metadata/mono-config.h>
+#include <cstring>
+
+const char* LIB_DIR = "lib/";
+const char* ETC_DIR = "etc/";
+const char* ASSEMBLIES_DIR = "lib/mono/4.5/";
+
+// Starts up the Mono runtime, runs the managed assembly provided as the first parameter using the
+// runtime and passes the rest of the arguments to it. When done shuts down the Mono runtime.
+int main(int argc, char* argv[])
+{
+	// No assembly to run, or Mono directory not provided
+	if(argc < 3)
+		return 0;
+
+	char* monoDir = argv[2];
+
+	char* libDir = new char[strlen(monoDir) + strlen(LIB_DIR) + 1];
+	strcpy(libDir, monoDir);
+	strcat(libDir, LIB_DIR);
+
+	char* etcDir = new char[strlen(monoDir) + strlen(ETC_DIR) + 1];
+	strcpy(etcDir, monoDir);
+	strcat(etcDir, ETC_DIR);
+
+	char* assembliesDir = new char[strlen(monoDir) + strlen(ASSEMBLIES_DIR) + 1];
+	strcpy(assembliesDir, monoDir);
+	strcat(assembliesDir, ASSEMBLIES_DIR);
+
+	mono_set_dirs(libDir, etcDir);
+	mono_set_assemblies_path(assembliesDir);
+
+	delete[] assembliesDir;
+	delete[] etcDir;
+	delete[] libDir;
+
+	mono_config_parse(nullptr);
+
+	MonoDomain* domain = mono_jit_init(argv[1]);
+	if(domain == nullptr)
+		return 1;
+
+	MonoAssembly* assembly = mono_domain_assembly_open(domain, argv[1]);
+	if(assembly == nullptr)
+		return 1;
+
+	int returnVal = mono_jit_exec(domain, assembly, argc - 3, argv + 3);
+
+	mono_jit_cleanup(domain);
+
+	return returnVal;
+}

+ 10 - 3
Source/BansheeMono/BsMonoManager.cpp

@@ -347,13 +347,20 @@ namespace bs
 	Path MonoManager::getCompilerPath() const
 	{
 		Path compilerPath = Paths::findPath(MONO_COMPILER_DIR);
+		compilerPath.append("mcs.exe");
+		return compilerPath;
+	}
+
+	Path MonoManager::getMonoExecPath() const
+	{
+		Path path = Paths::getBinariesPath();
 
 #if BS_PLATFORM == BS_PLATFORM_WIN32
-		compilerPath.append("mcs.exe");
+		path.append("MonoExec.exe");
 #else
-		compilerPath.append("mcs");
+		path.append("MonoExec");
 #endif
 
-		return compilerPath;
+		return path;
 	}
 }

+ 4 - 1
Source/BansheeMono/BsMonoManager.h

@@ -65,9 +65,12 @@ namespace bs
 		/** Returns the absolute path to the Mono /etc folder that is required for initializing Mono. */
 		Path getMonoEtcFolder() const;
 
-		/**	Returns the absolute path to the Mono compiler. */
+		/**	Returns the absolute path to the Mono compiler managed executable. */
 		Path getCompilerPath() const;
 
+		/** Returns the absolute path to the executable capable of executing managed assemblies. */
+		Path getMonoExecPath() const;
+
 		/**
 		 * Registers a new script type. This should be done before any assembly loading is done. Upon assembly load these
 		 * script types will be initialized with necessary information about their managed counterparts.

+ 5 - 1
Source/BansheeMono/CMakeLists.txt

@@ -26,5 +26,9 @@ target_link_libraries(BansheeMono PRIVATE ${mono_LIBRARIES})
 ## Local libs
 target_link_libraries(BansheeMono PUBLIC BansheeEngine BansheeUtility BansheeCore)
 
+# Runtime executable
+add_executable(MonoExec BsMonoExec.cpp)
+target_link_libraries(MonoExec ${mono_LIBRARIES})
+
 # IDE specific
-set_property(TARGET BansheeMono PROPERTY FOLDER Plugins)
+set_property(TARGET BansheeMono PROPERTY FOLDER Plugins)

+ 8 - 0
Source/MBansheeEditor/General/EditorApplication.cs

@@ -195,6 +195,11 @@ namespace BansheeEditor
         /// </summary>
         internal static string CompilerPath { get { return Internal_GetCompilerPath(); } }
 
+		/// <summary>
+		/// Returns the absolute path to the executable capable of executing managed assemblies.
+        /// </summary>
+        internal static string MonoExecPath { get { return Internal_GetMonoExecPath(); } }
+
         /// <summary>
         /// Returns the path to the folder where the custom script assemblies are located at.
         /// </summary>
@@ -1000,6 +1005,9 @@ namespace BansheeEditor
         [MethodImpl(MethodImplOptions.InternalCall)]
         private static extern string Internal_GetCompilerPath();
 
+		[MethodImpl(MethodImplOptions.InternalCall)]
+		private static extern string Internal_GetMonoExecPath();
+
         [MethodImpl(MethodImplOptions.InternalCall)]
         private static extern string Internal_GetBuiltinReleaseAssemblyPath();
 

+ 9 - 1
Source/MBansheeEditor/Script/ScriptCompiler.cs

@@ -141,6 +141,14 @@ namespace BansheeEditor
             ProcessStartInfo procStartInfo = new ProcessStartInfo();
             StringBuilder argumentsBuilder = new StringBuilder();
 
+            argumentsBuilder.Append("\"" + EditorApplication.CompilerPath + "\"");
+
+            string monoDir = Path.GetDirectoryName(EditorApplication.CompilerPath);
+            monoDir = Path.Combine(monoDir, "../");
+
+            argumentsBuilder.Append(" \"" + monoDir + "\"");
+            argumentsBuilder.Append(" -noconfig");
+
             if (!string.IsNullOrEmpty(defines))
                 argumentsBuilder.Append(" -d:" + defines);
 
@@ -183,7 +191,7 @@ namespace BansheeEditor
 
             procStartInfo.Arguments = argumentsBuilder.ToString();
             procStartInfo.CreateNoWindow = true;
-            procStartInfo.FileName = EditorApplication.CompilerPath;
+            procStartInfo.FileName = EditorApplication.MonoExecPath;
             procStartInfo.RedirectStandardError = true;
             procStartInfo.RedirectStandardOutput = false;
             procStartInfo.UseShellExecute = false;

+ 1 - 1
Source/MBansheeEngine/Scene/Component.cs

@@ -16,7 +16,7 @@ namespace BansheeEngine
     public class Component : GameObject
     {
         // Internal use only
-        internal Component()
+        protected internal Component()
         { }
 
         /// <summary>

+ 8 - 0
Source/SBansheeEditor/Wrappers/BsScriptEditorApplication.cpp

@@ -48,6 +48,7 @@ namespace bs
 		metaData.scriptClass->addInternalCall("Internal_GetProjectName", (void*)&ScriptEditorApplication::internal_GetProjectName);
 		metaData.scriptClass->addInternalCall("Internal_GetProjectLoaded", (void*)&ScriptEditorApplication::internal_GetProjectLoaded);
 		metaData.scriptClass->addInternalCall("Internal_GetCompilerPath", (void*)&ScriptEditorApplication::internal_GetCompilerPath);
+		metaData.scriptClass->addInternalCall("Internal_GetMonoExecPath", (void*) &ScriptEditorApplication::internal_GetMonoExecPath);
 		metaData.scriptClass->addInternalCall("Internal_GetBuiltinReleaseAssemblyPath", (void*)&ScriptEditorApplication::internal_GetBuiltinReleaseAssemblyPath);
 		metaData.scriptClass->addInternalCall("Internal_GetBuiltinDebugAssemblyPath", (void*)&ScriptEditorApplication::internal_GetBuiltinDebugAssemblyPath);
 		metaData.scriptClass->addInternalCall("Internal_GetScriptAssemblyPath", (void*)&ScriptEditorApplication::internal_GetScriptAssemblyPath);
@@ -165,6 +166,13 @@ namespace bs
 		return MonoUtil::wstringToMono(compilerPath.toWString());
 	}
 
+	MonoString* ScriptEditorApplication::internal_GetMonoExecPath()
+	{
+		Path path = MonoManager::instance().getMonoExecPath();
+
+		return MonoUtil::wstringToMono(path.toWString());
+	}
+
 	MonoString* ScriptEditorApplication::internal_GetBuiltinReleaseAssemblyPath()
 	{
 		Path releaseAssemblyFolder = Paths::getReleaseAssemblyPath();

+ 1 - 0
Source/SBansheeEditor/Wrappers/BsScriptEditorApplication.h

@@ -47,6 +47,7 @@ namespace bs
 		static MonoString* internal_GetProjectName();
 		static bool internal_GetProjectLoaded();
 		static MonoString* internal_GetCompilerPath();
+		static MonoString* internal_GetMonoExecPath();
 		static MonoString* internal_GetBuiltinReleaseAssemblyPath();
 		static MonoString* internal_GetBuiltinDebugAssemblyPath();
 		static MonoString* internal_GetScriptAssemblyPath();

+ 3 - 3
Source/SBansheeEngine/Wrappers/BsScriptScene.cpp

@@ -23,7 +23,7 @@ namespace bs
 	HEvent ScriptScene::OnRefreshDomainLoadedConn;
 	HEvent ScriptScene::OnRefreshStartedConn;
 
-	String ScriptScene::ActiveSceneUUID;
+	UUID ScriptScene::ActiveSceneUUID;
 	WString ScriptScene::ActiveSceneName;
 	bool ScriptScene::IsGenericPrefab;
 
@@ -84,7 +84,7 @@ namespace bs
 	{
 		MonoMethod* uuidMethod = metaData.scriptClass->getMethod("GetSceneUUID");
 		if (uuidMethod != nullptr)
-			ActiveSceneUUID = MonoUtil::monoToString((MonoString*)uuidMethod->invoke(nullptr, nullptr));
+			ActiveSceneUUID = ScriptUUID::unbox(uuidMethod->invoke(nullptr, nullptr));
 
 		MonoMethod* nameMethod = metaData.scriptClass->getMethod("GetSceneName");
 		if (nameMethod != nullptr)
@@ -101,7 +101,7 @@ namespace bs
 		if (uuidMethod != nullptr)
 		{
 			void* params[1];
-			params[0] = MonoUtil::stringToMono(ActiveSceneUUID);
+			params[0] = ScriptUUID::box(ActiveSceneUUID);
 
 			uuidMethod->invoke(nullptr, params);
 		}

+ 1 - 1
Source/SBansheeEngine/Wrappers/BsScriptScene.h

@@ -35,7 +35,7 @@ namespace bs
 		static HEvent OnRefreshDomainLoadedConn;
 		static HEvent OnRefreshStartedConn;
 
-		static String ActiveSceneUUID;
+		static UUID ActiveSceneUUID;
 		static WString ActiveSceneName;
 		static bool IsGenericPrefab;