Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mono: Project building fixes #18949

Merged
merged 1 commit into from
May 17, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 64 additions & 20 deletions modules/mono/editor/GodotSharpTools/Build/BuildSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,24 +16,48 @@ public class BuildInstance : IDisposable
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;
Expand All @@ -54,25 +78,35 @@ public BuildInstance(string solution, string config)

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

Expand All @@ -98,25 +132,35 @@ public bool BuildAsync(string loggerAssemblyPath, string loggerOutputDir, string
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);

Expand Down
4 changes: 2 additions & 2 deletions modules/mono/editor/GodotSharpTools/GodotSharpTools.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand All @@ -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>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ public static string GenGameProject(string dir, string name, string[] compileIte
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");
Expand Down Expand Up @@ -148,7 +148,7 @@ public static ProjectRootElement CreateLibraryProject(string name, out ProjectPr
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");
Expand All @@ -157,7 +157,7 @@ public static ProjectRootElement CreateLibraryProject(string name, out ProjectPr

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");
Expand Down
113 changes: 75 additions & 38 deletions modules/mono/editor/godotsharp_builds.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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");
Expand All @@ -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) {
Expand Down Expand Up @@ -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() {
Expand Down
5 changes: 2 additions & 3 deletions modules/mono/editor/godotsharp_builds.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,9 @@ class GodotSharpBuilds {
enum BuildTool {
MSBUILD_MONO,
#ifdef WINDOWS_ENABLED
MSBUILD
#else
XBUILD // Deprecated
MSBUILD_VS,
#endif
XBUILD // Deprecated
};

_FORCE_INLINE_ static GodotSharpBuilds *get_singleton() { return singleton; }
Expand Down