Mono: Project building fixes

- Set (Csc/Vbc/Fsc)ToolExe environment variables to point to the batch files in Mono's bin directory when building with Mono's MSBuild.
- Set Mono's MSBuild as the default build tool on Windows.
- Generate projects with portable DebugType instead of full.

(cherry picked from commit 01397a10d9)
This commit is contained in:
Ignacio Etcheverry 2018-05-17 01:26:02 +02:00 committed by Hein-Pieter van Braam
parent d00926894e
commit 3d3e4e62af
5 changed files with 150 additions and 70 deletions

View File

@ -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();
private static MSBuildInfo GetMSBuildInfo()
{
MSBuildInfo msbuildInfo = new MSBuildInfo();
godot_icall_BuildInstance_get_MSBuildInfo(ref msbuildInfo.path, ref msbuildInfo.frameworkPathOverride);
if (msbuildInfo.path == null)
if (msbuildPath == null)
throw new FileNotFoundException("Cannot find the MSBuild executable.");
return msbuildInfo;
return msbuildPath;
}
private static string GetFrameworkPath()
{
return godot_icall_BuildInstance_get_FrameworkPath();
}
private static string MonoWindowsBinDir
{
get
{
string monoWinBinDir = godot_icall_BuildInstance_get_MonoWindowsBinDir();
if (monoWinBinDir == null)
throw new FileNotFoundException("Cannot find the Windows Mono binaries directory.");
return monoWinBinDir;
}
}
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);

View File

@ -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>

View File

@ -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");

View File

@ -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;
return GDMonoMarshal::mono_string_from_godot(build_tool != GodotSharpBuilds::XBUILD ? msbuild_path : xbuild_path);
#else
ERR_PRINT("Not implemented on this platform");
return;
(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);
}
ERR_EXPLAIN("Cannot find Mono's assemblies directory in the registry");
ERR_FAIL_V(NULL);
#else
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() {

View File

@ -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; }