Browse Source

Merge pull request #18949 from neikeq/alo

Mono: Project building fixes
Rémi Verschelde 7 years ago
parent
commit
c3510cd981

+ 64 - 20
modules/mono/editor/GodotSharpTools/Build/BuildSystem.cs

@@ -16,24 +16,48 @@ namespace GodotSharpTools.Build
         private extern static void godot_icall_BuildInstance_ExitCallback(string solution, string config, int exitCode);
 
         [MethodImpl(MethodImplOptions.InternalCall)]
-        private extern static void godot_icall_BuildInstance_get_MSBuildInfo(ref string msbuildPath, ref string frameworkPath);
+        private extern static string godot_icall_BuildInstance_get_MSBuildPath();
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private extern static string godot_icall_BuildInstance_get_FrameworkPath();
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private extern static string godot_icall_BuildInstance_get_MonoWindowsBinDir();
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private extern static bool godot_icall_BuildInstance_get_UsingMonoMSBuildOnWindows();
 
-        private struct MSBuildInfo
+        private static string GetMSBuildPath()
         {
-            public string path;
-            public string frameworkPathOverride;
+            string msbuildPath = godot_icall_BuildInstance_get_MSBuildPath();
+
+            if (msbuildPath == null)
+                throw new FileNotFoundException("Cannot find the MSBuild executable.");
+
+            return msbuildPath;
         }
 
-        private static MSBuildInfo GetMSBuildInfo()
+        private static string GetFrameworkPath()
         {
-            MSBuildInfo msbuildInfo = new MSBuildInfo();
+            return godot_icall_BuildInstance_get_FrameworkPath();
+        }
 
-            godot_icall_BuildInstance_get_MSBuildInfo(ref msbuildInfo.path, ref msbuildInfo.frameworkPathOverride);
+        private static string MonoWindowsBinDir
+        {
+            get
+            {
+                string monoWinBinDir = godot_icall_BuildInstance_get_MonoWindowsBinDir();
 
-            if (msbuildInfo.path == null)
-                throw new FileNotFoundException("Cannot find the MSBuild executable.");
+                if (monoWinBinDir == null)
+                    throw new FileNotFoundException("Cannot find the Windows Mono binaries directory.");
+
+                return monoWinBinDir;
+            }
+        }
 
-            return msbuildInfo;
+        private static bool UsingMonoMSBuildOnWindows
+        {
+            get
+            {
+                return godot_icall_BuildInstance_get_UsingMonoMSBuildOnWindows();
+            }
         }
 
         private string solution;
@@ -54,25 +78,35 @@ namespace GodotSharpTools.Build
 
         public bool Build(string loggerAssemblyPath, string loggerOutputDir, string[] customProperties = null)
         {
-            MSBuildInfo msbuildInfo = GetMSBuildInfo();
-
             List<string> customPropertiesList = new List<string>();
 
             if (customProperties != null)
                 customPropertiesList.AddRange(customProperties);
 
-            if (msbuildInfo.frameworkPathOverride != null)
-                customPropertiesList.Add("FrameworkPathOverride=" + msbuildInfo.frameworkPathOverride);
+            string frameworkPath = GetFrameworkPath();
+
+            if (!string.IsNullOrEmpty(frameworkPath))
+                customPropertiesList.Add("FrameworkPathOverride=" + frameworkPath);
 
             string compilerArgs = BuildArguments(loggerAssemblyPath, loggerOutputDir, customPropertiesList);
 
-            ProcessStartInfo startInfo = new ProcessStartInfo(msbuildInfo.path, compilerArgs);
+            ProcessStartInfo startInfo = new ProcessStartInfo(GetMSBuildPath(), compilerArgs);
 
             // No console output, thanks
             startInfo.RedirectStandardOutput = true;
             startInfo.RedirectStandardError = true;
             startInfo.UseShellExecute = false;
 
+            if (UsingMonoMSBuildOnWindows)
+            {
+                // These environment variables are required for Mono's MSBuild to find the compilers.
+                // We use the batch files in Mono's bin directory to make sure the compilers are executed with mono.
+                string monoWinBinDir = MonoWindowsBinDir;
+                startInfo.EnvironmentVariables.Add("CscToolExe", Path.Combine(monoWinBinDir, "csc.bat"));
+                startInfo.EnvironmentVariables.Add("VbcToolExe", Path.Combine(monoWinBinDir, "vbc.bat"));
+                startInfo.EnvironmentVariables.Add("FscToolExe", Path.Combine(monoWinBinDir, "fsharpc.bat"));
+            }
+
             // Needed when running from Developer Command Prompt for VS
             RemovePlatformVariable(startInfo.EnvironmentVariables);
 
@@ -98,25 +132,35 @@ namespace GodotSharpTools.Build
             if (process != null)
                 throw new InvalidOperationException("Already in use");
 
-            MSBuildInfo msbuildInfo = GetMSBuildInfo();
-
             List<string> customPropertiesList = new List<string>();
 
             if (customProperties != null)
                 customPropertiesList.AddRange(customProperties);
 
-            if (msbuildInfo.frameworkPathOverride.Length > 0)
-                customPropertiesList.Add("FrameworkPathOverride=" + msbuildInfo.frameworkPathOverride);
+            string frameworkPath = GetFrameworkPath();
+
+            if (!string.IsNullOrEmpty(frameworkPath))
+                customPropertiesList.Add("FrameworkPathOverride=" + frameworkPath);
 
             string compilerArgs = BuildArguments(loggerAssemblyPath, loggerOutputDir, customPropertiesList);
 
-            ProcessStartInfo startInfo = new ProcessStartInfo(msbuildInfo.path, compilerArgs);
+            ProcessStartInfo startInfo = new ProcessStartInfo(GetMSBuildPath(), compilerArgs);
 
             // No console output, thanks
             startInfo.RedirectStandardOutput = true;
             startInfo.RedirectStandardError = true;
             startInfo.UseShellExecute = false;
 
+            if (UsingMonoMSBuildOnWindows)
+            {
+                // These environment variables are required for Mono's MSBuild to find the compilers.
+                // We use the batch files in Mono's bin directory to make sure the compilers are executed with mono.
+                string monoWinBinDir = MonoWindowsBinDir;
+                startInfo.EnvironmentVariables.Add("CscToolExe", Path.Combine(monoWinBinDir, "csc.bat"));
+                startInfo.EnvironmentVariables.Add("VbcToolExe", Path.Combine(monoWinBinDir, "vbc.bat"));
+                startInfo.EnvironmentVariables.Add("FscToolExe", Path.Combine(monoWinBinDir, "fsharpc.bat"));
+            }
+
             // Needed when running from Developer Command Prompt for VS
             RemovePlatformVariable(startInfo.EnvironmentVariables);
 

+ 2 - 2
modules/mono/editor/GodotSharpTools/GodotSharpTools.csproj

@@ -11,7 +11,7 @@
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
     <DebugSymbols>true</DebugSymbols>
-    <DebugType>full</DebugType>
+    <DebugType>portable</DebugType>
     <Optimize>false</Optimize>
     <OutputPath>bin\Debug</OutputPath>
     <DefineConstants>DEBUG;</DefineConstants>
@@ -20,7 +20,7 @@
     <ConsolePause>false</ConsolePause>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
-    <DebugType>full</DebugType>
+    <DebugType>portable</DebugType>
     <Optimize>true</Optimize>
     <OutputPath>bin\Release</OutputPath>
     <ErrorReport>prompt</ErrorReport>

+ 3 - 3
modules/mono/editor/GodotSharpTools/Project/ProjectGenerator.cs

@@ -70,7 +70,7 @@ namespace GodotSharpTools.Project
             var toolsGroup = root.AddPropertyGroup();
             toolsGroup.Condition = " '$(Configuration)|$(Platform)' == 'Tools|AnyCPU' ";
             toolsGroup.AddProperty("DebugSymbols", "true");
-            toolsGroup.AddProperty("DebugType", "full");
+            toolsGroup.AddProperty("DebugType", "portable");
             toolsGroup.AddProperty("Optimize", "false");
             toolsGroup.AddProperty("DefineConstants", "DEBUG;TOOLS;");
             toolsGroup.AddProperty("ErrorReport", "prompt");
@@ -148,7 +148,7 @@ namespace GodotSharpTools.Project
             var debugGroup = root.AddPropertyGroup();
             debugGroup.Condition = " '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ";
             debugGroup.AddProperty("DebugSymbols", "true");
-            debugGroup.AddProperty("DebugType", "full");
+            debugGroup.AddProperty("DebugType", "portable");
             debugGroup.AddProperty("Optimize", "false");
             debugGroup.AddProperty("DefineConstants", "DEBUG;");
             debugGroup.AddProperty("ErrorReport", "prompt");
@@ -157,7 +157,7 @@ namespace GodotSharpTools.Project
 
             var releaseGroup = root.AddPropertyGroup();
             releaseGroup.Condition = " '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ";
-            releaseGroup.AddProperty("DebugType", "full");
+            releaseGroup.AddProperty("DebugType", "portable");
             releaseGroup.AddProperty("Optimize", "true");
             releaseGroup.AddProperty("ErrorReport", "prompt");
             releaseGroup.AddProperty("WarningLevel", "4");

+ 75 - 38
modules/mono/editor/godotsharp_builds.cpp

@@ -39,6 +39,10 @@
 #include "bindings_generator.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);
@@ -76,46 +80,42 @@ String _find_build_engine_on_unix(const String &p_name) {
 }
 #endif
 
-void godot_icall_BuildInstance_get_MSBuildInfo(MonoString **r_msbuild_path, MonoString **r_framework_path) {
+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: {
+		case GodotSharpBuilds::MSBUILD_VS: {
 			static String msbuild_tools_path = MonoRegUtils::find_msbuild_tools_path();
 
 			if (msbuild_tools_path.length()) {
 				if (!msbuild_tools_path.ends_with("\\"))
 					msbuild_tools_path += "\\";
 
-				// FrameworkPathOverride
-				const MonoRegInfo &mono_reg_info = GDMono::get_singleton()->get_mono_reg_info();
-				if (mono_reg_info.assembly_dir.length()) {
-					*r_msbuild_path = GDMonoMarshal::mono_string_from_godot(msbuild_tools_path + "MSBuild.exe");
-
-					String framework_path = path_join(mono_reg_info.assembly_dir, "mono", "4.5");
-					*r_framework_path = GDMonoMarshal::mono_string_from_godot(framework_path);
-				} else {
-					ERR_PRINT("Cannot find Mono's assemblies directory in the registry");
-				}
-
-				return;
+				return GDMonoMarshal::mono_string_from_godot(msbuild_tools_path + "MSBuild.exe");
 			}
 
 			if (OS::get_singleton()->is_stdout_verbose())
-				OS::get_singleton()->print("Cannot find System's MSBuild. Trying with Mono's...\n");
-		} // fall through
+				OS::get_singleton()->print("Cannot find executable for '" PROP_NAME_MSBUILD_VS "'. Trying with '" PROP_NAME_MSBUILD_MONO "'...\n");
+		} // FALL THROUGH
 		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)) {
-				WARN_PRINTS("Cannot find msbuild ('mono/builds/build_tool'). Tried with path: " + msbuild_path);
+				WARN_PRINTS("Cannot find executable for '" PROP_NAME_MSBUILD_MONO "'. Tried with path: " + msbuild_path);
 			}
 
-			*r_msbuild_path = GDMonoMarshal::mono_string_from_godot(msbuild_path);
+			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");
 
-			return;
+			if (!FileAccess::exists(xbuild_path)) {
+				WARN_PRINTS("Cannot find executable for '" PROP_NAME_XBUILD "'. Tried with path: " + xbuild_path);
+			}
+
+			return GDMonoMarshal::mono_string_from_godot(xbuild_path);
 		} break;
 		default:
 			ERR_EXPLAIN("You don't deserve to live");
@@ -125,31 +125,74 @@ void godot_icall_BuildInstance_get_MSBuildInfo(MonoString **r_msbuild_path, Mono
 	static String msbuild_path = _find_build_engine_on_unix("msbuild");
 	static String xbuild_path = _find_build_engine_on_unix("xbuild");
 
-	if (build_tool != GodotSharpBuilds::XBUILD) {
-		if (msbuild_path.empty()) {
-			WARN_PRINT("Cannot find msbuild ('mono/builds/build_tool').");
+	if (build_tool == GodotSharpBuilds::XBUILD) {
+		if (xbuild_path.empty()) {
+			WARN_PRINT("Cannot find binary for '" PROP_NAME_XBUILD "'");
 			return;
 		}
 	} else {
-		if (xbuild_path.empty()) {
-			WARN_PRINT("Cannot find xbuild ('mono/builds/build_tool').");
+		if (msbuild_path.empty()) {
+			WARN_PRINT("Cannot find binary for '" PROP_NAME_MSBUILD_MONO "'");
 			return;
 		}
 	}
 
-	*r_msbuild_path = GDMonoMarshal::mono_string_from_godot(build_tool != GodotSharpBuilds::XBUILD ? msbuild_path : xbuild_path);
+	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_FrameworkPath() {
+
+#if defined(WINDOWS_ENABLED)
+	const MonoRegInfo &mono_reg_info = GDMono::get_singleton()->get_mono_reg_info();
+	if (mono_reg_info.assembly_dir.length()) {
+		String framework_path = path_join(mono_reg_info.assembly_dir, "mono", "4.5");
+		return GDMonoMarshal::mono_string_from_godot(framework_path);
+	}
 
-	return;
+	ERR_EXPLAIN("Cannot find Mono's assemblies directory in the registry");
+	ERR_FAIL_V(NULL);
 #else
-	ERR_PRINT("Not implemented on this platform");
-	return;
+	return 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
 }
 
 void GodotSharpBuilds::_register_internal_calls() {
 
 	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_MSBuildInfo", (void *)godot_icall_BuildInstance_get_MSBuildInfo);
+	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_FrameworkPath", (void *)godot_icall_BuildInstance_get_FrameworkPath);
+	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);
 }
 
 void GodotSharpBuilds::show_build_error_dialog(const String &p_message) {
@@ -386,20 +429,14 @@ GodotSharpBuilds::GodotSharpBuilds() {
 	// Build tool settings
 	EditorSettings *ed_settings = EditorSettings::get_singleton();
 
-#ifdef WINDOWS_ENABLED
-	// TODO: Default to MSBUILD_MONO if its csc.exe issue is fixed in the installed mono version
-	EDITOR_DEF("mono/builds/build_tool", MSBUILD);
-#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
-			"MSBuild (Mono),MSBuild (System)"
-#else
-			"MSBuild (Mono),xbuild (Deprecated)"
+			"," PROP_NAME_MSBUILD_VS
 #endif
-			));
+			"," PROP_NAME_XBUILD));
 }
 
 GodotSharpBuilds::~GodotSharpBuilds() {

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

@@ -68,10 +68,9 @@ public:
 	enum BuildTool {
 		MSBUILD_MONO,
 #ifdef WINDOWS_ENABLED
-		MSBUILD
-#else
-		XBUILD // Deprecated
+		MSBUILD_VS,
 #endif
+		XBUILD // Deprecated
 	};
 
 	_FORCE_INLINE_ static GodotSharpBuilds *get_singleton() { return singleton; }