Buildsystem improvements for the Mono module
- Make sure to search the mono installation directory for the right architecture in the windows registry. - Do not build GodotSharpTools directly to #bin dir. Instead build to the default output path and copy it. This way we avoid MSBuild adding files we don't want to #bin. - Add hint path for MSBuild in OSX. - Copy shared library on Unix if not statically linking. - Use vswhere to search MSBuild and search for 14.0 tools version in the registry instead of 4.0. - SCons will only fallback xbuild when msbuild is not found if 'xbuild_fallback=yes' is passed to the command. - Use mono's assembly path as FrameworkPathOverride if using with system's MSBuild (not mono's fork). - Cleanup.
This commit is contained in:
parent
4396712137
commit
9f469887fc
6 changed files with 341 additions and 115 deletions
|
@ -53,68 +53,149 @@ if env['tools']:
|
|||
|
||||
vars = Variables()
|
||||
vars.Add(BoolVariable('mono_glue', 'Build with the mono glue sources', True))
|
||||
vars.Add(BoolVariable('xbuild_fallback', 'If MSBuild is not found, fallback to xbuild', False))
|
||||
vars.Update(env)
|
||||
|
||||
# Glue sources
|
||||
if env['mono_glue']:
|
||||
env.add_source_files(env.modules_sources, 'glue/*.cpp')
|
||||
else:
|
||||
env.Append(CPPDEFINES = [ 'MONO_GLUE_DISABLED' ])
|
||||
env.Append(CPPDEFINES=['MONO_GLUE_DISABLED'])
|
||||
|
||||
if ARGUMENTS.get('yolo_copy', False):
|
||||
env.Append(CPPDEFINES = [ 'YOLO_COPY' ])
|
||||
env.Append(CPPDEFINES=['YOLO_COPY'])
|
||||
|
||||
|
||||
# Build GodotSharpTools solution
|
||||
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
import mono_reg_utils as monoreg
|
||||
|
||||
|
||||
def find_msbuild_unix(filename):
|
||||
import os.path
|
||||
import sys
|
||||
|
||||
hint_dirs = ['/opt/novell/mono/bin']
|
||||
if sys.platform == "darwin":
|
||||
hint_dirs = ['/Library/Frameworks/Mono.framework/Versions/Current/bin'] + hint_dirs
|
||||
|
||||
for hint_dir in hint_dirs:
|
||||
hint_path = os.path.join(hint_dir, filename)
|
||||
if os.path.isfile(hint_path):
|
||||
return hint_path
|
||||
|
||||
for hint_dir in os.environ["PATH"].split(os.pathsep):
|
||||
hint_dir = hint_dir.strip('"')
|
||||
hint_path = os.path.join(hint_dir, filename)
|
||||
if os.path.isfile(hint_path) and os.access(hint_path, os.X_OK):
|
||||
return hint_path
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def find_msbuild_windows():
|
||||
import mono_reg_utils as monoreg
|
||||
|
||||
msbuild_tools_path = monoreg.find_msbuild_tools_path_reg()
|
||||
|
||||
if msbuild_tools_path:
|
||||
return (os.path.join(msbuild_tools_path, 'MSBuild.exe'), '')
|
||||
else:
|
||||
bits = env['bits']
|
||||
|
||||
if bits == '32':
|
||||
if os.getenv('MONO32_PREFIX'):
|
||||
mono_root = os.getenv('MONO32_PREFIX')
|
||||
else:
|
||||
mono_root = monoreg.find_mono_root_dir(bits)
|
||||
else:
|
||||
if os.getenv('MONO64_PREFIX'):
|
||||
mono_root = os.getenv('MONO64_PREFIX')
|
||||
else:
|
||||
mono_root = monoreg.find_mono_root_dir(bits)
|
||||
|
||||
if mono_root:
|
||||
msbuild_mono = os.path.join(mono_root, 'bin', 'msbuild.bat')
|
||||
|
||||
if os.path.isfile(msbuild_mono):
|
||||
return (msbuild_mono, os.path.join(mono_root, 'lib', 'mono', '4.5'))
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def mono_build_solution(source, target, env):
|
||||
if os.name == 'nt':
|
||||
msbuild_tools_path = monoreg.find_msbuild_tools_path_reg()
|
||||
if not msbuild_tools_path:
|
||||
raise RuntimeError('Cannot find MSBuild Tools Path in the registry')
|
||||
msbuild_path = os.path.join(msbuild_tools_path, 'MSBuild.exe')
|
||||
else:
|
||||
msbuild_path = 'msbuild'
|
||||
import subprocess
|
||||
import mono_reg_utils as monoreg
|
||||
from shutil import copyfile
|
||||
|
||||
output_path = os.path.abspath(os.path.join(str(target[0]), os.pardir))
|
||||
framework_path_override = ''
|
||||
|
||||
if os.name == 'nt':
|
||||
msbuild_info = find_msbuild_windows()
|
||||
if msbuild_info is None:
|
||||
raise RuntimeError('Cannot find MSBuild executable')
|
||||
msbuild_path = msbuild_windows[0]
|
||||
framework_path_override = msbuild_windows[1]
|
||||
else:
|
||||
msbuild_path = find_msbuild_unix('msbuild')
|
||||
if msbuild_path is None:
|
||||
xbuild_fallback = env['xbuild_fallback']
|
||||
|
||||
if xbuild_fallback and os.name == 'nt':
|
||||
print("Option 'xbuild_fallback' not supported on Windows")
|
||||
xbuild_fallback = False
|
||||
|
||||
if xbuild_fallback:
|
||||
print('Cannot find MSBuild executable, trying with xbuild')
|
||||
print('Warning: xbuild is deprecated')
|
||||
|
||||
msbuild_path = find_msbuild_unix('xbuild')
|
||||
|
||||
if msbuild_path is None:
|
||||
raise RuntimeError('Cannot find xbuild executable')
|
||||
else:
|
||||
raise RuntimeError('Cannot find MSBuild executable')
|
||||
|
||||
print('MSBuild path: ' + msbuild_path)
|
||||
|
||||
build_config = 'Release'
|
||||
|
||||
msbuild_args = [
|
||||
msbuild_path,
|
||||
os.path.abspath(str(source[0])),
|
||||
'/p:Configuration=Release',
|
||||
'/p:OutputPath=' + output_path
|
||||
'/p:Configuration=' + build_config,
|
||||
]
|
||||
|
||||
if framework_path_override:
|
||||
msbuild_args += ['/p:FrameworkPathOverride=' + framework_path_override]
|
||||
|
||||
msbuild_env = os.environ.copy()
|
||||
|
||||
# Needed when running from Developer Command Prompt for VS
|
||||
if 'PLATFORM' in msbuild_env:
|
||||
del msbuild_env['PLATFORM']
|
||||
|
||||
msbuild_alt_paths = [ 'xbuild' ]
|
||||
try:
|
||||
subprocess.check_call(msbuild_args, env=msbuild_env)
|
||||
except subprocess.CalledProcessError:
|
||||
raise RuntimeError('GodotSharpTools build failed')
|
||||
|
||||
while True:
|
||||
try:
|
||||
subprocess.check_call(msbuild_args, env = msbuild_env)
|
||||
break
|
||||
except subprocess.CalledProcessError:
|
||||
raise RuntimeError('GodotSharpTools build failed')
|
||||
except OSError:
|
||||
if os.name != 'nt':
|
||||
if not msbuild_alt_paths:
|
||||
raise RuntimeError('Could not find commands msbuild or xbuild')
|
||||
# Try xbuild
|
||||
msbuild_args[0] = msbuild_alt_paths.pop(0)
|
||||
else:
|
||||
raise RuntimeError('Could not find command MSBuild.exe')
|
||||
src_dir = os.path.abspath(os.path.join(str(source[0]), os.pardir, 'bin', build_config))
|
||||
dst_dir = os.path.abspath(os.path.join(str(target[0]), os.pardir))
|
||||
|
||||
if not os.path.isdir(dst_dir):
|
||||
if os.path.exists(dst_dir):
|
||||
raise RuntimeError('Target directory is a file')
|
||||
os.makedirs(dst_dir)
|
||||
|
||||
asm_file = 'GodotSharpTools.dll'
|
||||
|
||||
copyfile(os.path.join(src_dir, asm_file), os.path.join(dst_dir, asm_file))
|
||||
|
||||
|
||||
mono_sln_builder = Builder(action = mono_build_solution)
|
||||
env.Append(BUILDERS = { 'MonoBuildSolution' : mono_sln_builder })
|
||||
env.Append(BUILDERS={'MonoBuildSolution': mono_sln_builder})
|
||||
env.MonoBuildSolution(
|
||||
os.path.join(Dir('#bin').abspath, 'GodotSharpTools.dll'),
|
||||
'editor/GodotSharpTools/GodotSharpTools.sln'
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
import imp
|
||||
import os
|
||||
import sys
|
||||
from shutil import copyfile
|
||||
|
||||
from SCons.Script import BoolVariable, Environment, Variables
|
||||
|
||||
|
@ -16,8 +15,7 @@ def find_file_in_dir(directory, files, prefix='', extension=''):
|
|||
for curfile in files:
|
||||
if os.path.isfile(os.path.join(directory, prefix + curfile + extension)):
|
||||
return curfile
|
||||
|
||||
return None
|
||||
return ''
|
||||
|
||||
|
||||
def can_build(platform):
|
||||
|
@ -31,6 +29,22 @@ def is_enabled():
|
|||
return False
|
||||
|
||||
|
||||
def copy_file_no_replace(src_dir, dst_dir, name):
|
||||
from shutil import copyfile
|
||||
|
||||
src_path = os.path.join(src_dir, name)
|
||||
dst_path = os.path.join(dst_dir, name)
|
||||
need_copy = True
|
||||
|
||||
if not os.path.isdir(dst_dir):
|
||||
os.mkdir(dst_dir)
|
||||
elif os.path.exists(dst_path):
|
||||
need_copy = False
|
||||
|
||||
if need_copy:
|
||||
copyfile(src_path, dst_path)
|
||||
|
||||
|
||||
def configure(env):
|
||||
env.use_ptrcall = True
|
||||
|
||||
|
@ -38,6 +52,8 @@ def configure(env):
|
|||
envvars.Add(BoolVariable('mono_static', 'Statically link mono', False))
|
||||
envvars.Update(env)
|
||||
|
||||
bits = env['bits']
|
||||
|
||||
mono_static = env['mono_static']
|
||||
|
||||
mono_lib_names = ['mono-2.0-sgen', 'monosgen-2.0']
|
||||
|
@ -46,18 +62,18 @@ def configure(env):
|
|||
if mono_static:
|
||||
raise RuntimeError('mono-static: Not supported on Windows')
|
||||
|
||||
if env['bits'] == '32':
|
||||
if bits == '32':
|
||||
if os.getenv('MONO32_PREFIX'):
|
||||
mono_root = os.getenv('MONO32_PREFIX')
|
||||
elif os.name == 'nt':
|
||||
mono_root = monoreg.find_mono_root_dir()
|
||||
mono_root = monoreg.find_mono_root_dir(bits)
|
||||
else:
|
||||
if os.getenv('MONO64_PREFIX'):
|
||||
mono_root = os.getenv('MONO64_PREFIX')
|
||||
elif os.name == 'nt':
|
||||
mono_root = monoreg.find_mono_root_dir()
|
||||
mono_root = monoreg.find_mono_root_dir(bits)
|
||||
|
||||
if mono_root is None:
|
||||
if not mono_root:
|
||||
raise RuntimeError('Mono installation directory not found')
|
||||
|
||||
mono_lib_path = os.path.join(mono_root, 'lib')
|
||||
|
@ -67,7 +83,7 @@ def configure(env):
|
|||
|
||||
mono_lib_name = find_file_in_dir(mono_lib_path, mono_lib_names, extension='.lib')
|
||||
|
||||
if mono_lib_name is None:
|
||||
if not mono_lib_name:
|
||||
raise RuntimeError('Could not find mono library in: ' + mono_lib_path)
|
||||
|
||||
if os.getenv('VCINSTALLDIR'):
|
||||
|
@ -79,28 +95,23 @@ def configure(env):
|
|||
|
||||
mono_dll_name = find_file_in_dir(mono_bin_path, mono_lib_names, extension='.dll')
|
||||
|
||||
mono_dll_src = os.path.join(mono_bin_path, mono_dll_name + '.dll')
|
||||
mono_dll_dst = os.path.join('bin', mono_dll_name + '.dll')
|
||||
copy_mono_dll = True
|
||||
if not mono_dll_name:
|
||||
raise RuntimeError('Could not find mono shared library in: ' + mono_bin_path)
|
||||
|
||||
if not os.path.isdir('bin'):
|
||||
os.mkdir('bin')
|
||||
elif os.path.exists(mono_dll_dst):
|
||||
copy_mono_dll = False
|
||||
|
||||
if copy_mono_dll:
|
||||
copyfile(mono_dll_src, mono_dll_dst)
|
||||
copy_file_no_replace(mono_bin_path, 'bin', mono_dll_name + '.dll')
|
||||
else:
|
||||
mono_root = None
|
||||
sharedlib_ext = '.dylib' if sys.platform == 'darwin' else '.so'
|
||||
|
||||
if env['bits'] == '32':
|
||||
mono_root = ''
|
||||
|
||||
if bits == '32':
|
||||
if os.getenv('MONO32_PREFIX'):
|
||||
mono_root = os.getenv('MONO32_PREFIX')
|
||||
else:
|
||||
if os.getenv('MONO64_PREFIX'):
|
||||
mono_root = os.getenv('MONO64_PREFIX')
|
||||
|
||||
if mono_root is not None:
|
||||
if mono_root:
|
||||
mono_lib_path = os.path.join(mono_root, 'lib')
|
||||
|
||||
env.Append(LIBPATH=mono_lib_path)
|
||||
|
@ -108,7 +119,7 @@ def configure(env):
|
|||
|
||||
mono_lib = find_file_in_dir(mono_lib_path, mono_lib_names, prefix='lib', extension='.a')
|
||||
|
||||
if mono_lib is None:
|
||||
if not mono_lib:
|
||||
raise RuntimeError('Could not find mono library in: ' + mono_lib_path)
|
||||
|
||||
env.Append(CPPFLAGS=['-D_REENTRANT'])
|
||||
|
@ -130,12 +141,37 @@ def configure(env):
|
|||
elif sys.platform == "linux" or sys.platform == "linux2":
|
||||
env.Append(LIBS=['m', 'rt', 'dl', 'pthread'])
|
||||
|
||||
if not mono_static:
|
||||
mono_so_name = find_file_in_dir(mono_lib_path, mono_lib_names, prefix='lib', extension=sharedlib_ext)
|
||||
|
||||
if not mono_so_name:
|
||||
raise RuntimeError('Could not find mono shared library in: ' + mono_lib_path)
|
||||
|
||||
copy_file_no_replace(mono_lib_path, 'bin', 'lib' + mono_so_name + sharedlib_ext)
|
||||
else:
|
||||
if mono_static:
|
||||
raise RuntimeError('mono-static: Not supported with pkg-config. Specify a mono prefix manually')
|
||||
|
||||
env.ParseConfig('pkg-config monosgen-2 --cflags --libs')
|
||||
|
||||
mono_lib_path = ''
|
||||
mono_so_name = ''
|
||||
|
||||
tmpenv = Environment()
|
||||
tmpenv.ParseConfig('pkg-config monosgen-2 --libs-only-L')
|
||||
|
||||
for hint_dir in tmpenv['LIBPATH']:
|
||||
name_found = find_file_in_dir(hint_dir, mono_lib_names, prefix='lib', extension=sharedlib_ext)
|
||||
if name_found:
|
||||
mono_lib_path = hint_dir
|
||||
mono_so_name = name_found
|
||||
break
|
||||
|
||||
if not mono_so_name:
|
||||
raise RuntimeError('Could not find mono shared library in: ' + str(tmpenv['LIBPATH']))
|
||||
|
||||
copy_file_no_replace(mono_lib_path, 'bin', 'lib' + mono_so_name + sharedlib_ext)
|
||||
|
||||
env.Append(LINKFLAGS='-rdynamic')
|
||||
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ using System.Collections.Specialized;
|
|||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security;
|
||||
using Microsoft.Build.Framework;
|
||||
|
||||
|
@ -12,22 +13,36 @@ namespace GodotSharpTools.Build
|
|||
public class BuildInstance : IDisposable
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static void godot_icall_BuildInstance_ExitCallback(string solution, string config, int exitCode);
|
||||
private extern static void godot_icall_BuildInstance_ExitCallback(string solution, string config, int exitCode);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static string godot_icall_BuildInstance_get_MSBuildPath();
|
||||
private extern static MSBuildInfo godot_icall_BuildInstance_get_MSBuildInfo();
|
||||
|
||||
private static string MSBuildPath
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
private struct MSBuildInfo
|
||||
{
|
||||
get
|
||||
string path;
|
||||
string frameworkPathOverride;
|
||||
|
||||
public string MSBuildPath
|
||||
{
|
||||
string ret = godot_icall_BuildInstance_get_MSBuildPath();
|
||||
|
||||
if (ret == null)
|
||||
throw new FileNotFoundException("Cannot find the MSBuild executable.");
|
||||
|
||||
return ret;
|
||||
get { return path; }
|
||||
}
|
||||
|
||||
public string FrameworkPathOverride
|
||||
{
|
||||
get { return frameworkPathOverride; }
|
||||
}
|
||||
}
|
||||
|
||||
private static MSBuildInfo GetMSBuildInfo()
|
||||
{
|
||||
MSBuildInfo ret = godot_icall_BuildInstance_get_MSBuildInfo();
|
||||
|
||||
if (ret.MSBuildPath == null)
|
||||
throw new FileNotFoundException("Cannot find the MSBuild executable.");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
private string solution;
|
||||
|
@ -48,9 +63,19 @@ namespace GodotSharpTools.Build
|
|||
|
||||
public bool Build(string loggerAssemblyPath, string loggerOutputDir, string[] customProperties = null)
|
||||
{
|
||||
string compilerArgs = BuildArguments(loggerAssemblyPath, loggerOutputDir, customProperties);
|
||||
MSBuildInfo msbuildInfo = GetMSBuildInfo();
|
||||
|
||||
ProcessStartInfo startInfo = new ProcessStartInfo(MSBuildPath, compilerArgs);
|
||||
List<string> customPropertiesList = new List<string>();
|
||||
|
||||
if (customProperties != null)
|
||||
customPropertiesList.AddRange(customProperties);
|
||||
|
||||
if (msbuildInfo.FrameworkPathOverride.Length > 0)
|
||||
customPropertiesList.Add("FrameworkPathOverride=" + msbuildInfo.FrameworkPathOverride);
|
||||
|
||||
string compilerArgs = BuildArguments(loggerAssemblyPath, loggerOutputDir, customPropertiesList);
|
||||
|
||||
ProcessStartInfo startInfo = new ProcessStartInfo(msbuildInfo.MSBuildPath, compilerArgs);
|
||||
|
||||
// No console output, thanks
|
||||
startInfo.RedirectStandardOutput = true;
|
||||
|
@ -82,9 +107,19 @@ namespace GodotSharpTools.Build
|
|||
if (process != null)
|
||||
throw new InvalidOperationException("Already in use");
|
||||
|
||||
string compilerArgs = BuildArguments(loggerAssemblyPath, loggerOutputDir, customProperties);
|
||||
MSBuildInfo msbuildInfo = GetMSBuildInfo();
|
||||
|
||||
ProcessStartInfo startInfo = new ProcessStartInfo("msbuild", compilerArgs);
|
||||
List<string> customPropertiesList = new List<string>();
|
||||
|
||||
if (customProperties != null)
|
||||
customPropertiesList.AddRange(customProperties);
|
||||
|
||||
if (msbuildInfo.FrameworkPathOverride.Length > 0)
|
||||
customPropertiesList.Add("FrameworkPathOverride=" + msbuildInfo.FrameworkPathOverride);
|
||||
|
||||
string compilerArgs = BuildArguments(loggerAssemblyPath, loggerOutputDir, customPropertiesList);
|
||||
|
||||
ProcessStartInfo startInfo = new ProcessStartInfo(msbuildInfo.MSBuildPath, compilerArgs);
|
||||
|
||||
// No console output, thanks
|
||||
startInfo.RedirectStandardOutput = true;
|
||||
|
@ -101,10 +136,13 @@ namespace GodotSharpTools.Build
|
|||
|
||||
process.Start();
|
||||
|
||||
process.BeginOutputReadLine();
|
||||
process.BeginErrorReadLine();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private string BuildArguments(string loggerAssemblyPath, string loggerOutputDir, string[] customProperties)
|
||||
private string BuildArguments(string loggerAssemblyPath, string loggerOutputDir, List<string> customProperties)
|
||||
{
|
||||
string arguments = string.Format(@"""{0}"" /v:normal /t:Build ""/p:{1}"" ""/l:{2},{3};{4}""",
|
||||
solution,
|
||||
|
@ -114,12 +152,9 @@ namespace GodotSharpTools.Build
|
|||
loggerOutputDir
|
||||
);
|
||||
|
||||
if (customProperties != null)
|
||||
foreach (string customProperty in customProperties)
|
||||
{
|
||||
foreach (string customProperty in customProperties)
|
||||
{
|
||||
arguments += " /p:" + customProperty;
|
||||
}
|
||||
arguments += " \"/p:" + customProperty + "\"";
|
||||
}
|
||||
|
||||
return arguments;
|
||||
|
|
|
@ -71,10 +71,15 @@ String _find_build_engine_on_unix(const String &p_name) {
|
|||
}
|
||||
#endif
|
||||
|
||||
MonoString *godot_icall_BuildInstance_get_MSBuildPath() {
|
||||
MonoString **godot_icall_BuildInstance_get_MSBuildInfo() {
|
||||
|
||||
GodotSharpBuilds::BuildTool build_tool = GodotSharpBuilds::BuildTool(int(EditorSettings::get_singleton()->get("mono/builds/build_tool")));
|
||||
|
||||
MonoString *res[2] = {
|
||||
NULL, // MSBuildPath
|
||||
NULL // FrameworkPathOverride
|
||||
};
|
||||
|
||||
#if defined(WINDOWS_ENABLED)
|
||||
switch (build_tool) {
|
||||
case GodotSharpBuilds::MSBUILD: {
|
||||
|
@ -84,11 +89,17 @@ MonoString *godot_icall_BuildInstance_get_MSBuildPath() {
|
|||
if (!msbuild_tools_path.ends_with("\\"))
|
||||
msbuild_tools_path += "\\";
|
||||
|
||||
return GDMonoMarshal::mono_string_from_godot(msbuild_tools_path + "MSBuild.exe");
|
||||
res[0] = GDMonoMarshal::mono_string_from_godot(msbuild_tools_path + "MSBuild.exe");
|
||||
|
||||
// FrameworkPathOverride
|
||||
res[1] = GDMonoMarshal::mono_string_from_godot(GDMono::get_singleton()->get_mono_reg_info().assembly_dir);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
OS::get_singleton()->print("Cannot find System's MSBuild. Trying with Mono's...\n");
|
||||
}
|
||||
if (OS::get_singleton()->is_stdout_verbose())
|
||||
OS::get_singleton()->print("Cannot find System's MSBuild. Trying with Mono's...\n");
|
||||
} // fall through
|
||||
case GodotSharpBuilds::MSBUILD_MONO: {
|
||||
String msbuild_path = GDMono::get_singleton()->get_mono_reg_info().bin_dir.plus_file("msbuild.bat");
|
||||
|
||||
|
@ -96,17 +107,9 @@ MonoString *godot_icall_BuildInstance_get_MSBuildPath() {
|
|||
WARN_PRINTS("Cannot find msbuild ('mono/builds/build_tool'). Tried with path: " + msbuild_path);
|
||||
}
|
||||
|
||||
return GDMonoMarshal::mono_string_from_godot(msbuild_path);
|
||||
}
|
||||
case GodotSharpBuilds::XBUILD: {
|
||||
String xbuild_path = GDMono::get_singleton()->get_mono_reg_info().bin_dir.plus_file("xbuild.bat");
|
||||
|
||||
if (!FileAccess::exists(xbuild_path)) {
|
||||
WARN_PRINTS("Cannot find xbuild ('mono/builds/build_tool'). Tried with path: " + xbuild_path);
|
||||
}
|
||||
|
||||
return GDMonoMarshal::mono_string_from_godot(xbuild_path);
|
||||
}
|
||||
res[0] = GDMonoMarshal::mono_string_from_godot(msbuild_path);
|
||||
return res;
|
||||
} break;
|
||||
default:
|
||||
ERR_EXPLAIN("You don't deserve to live");
|
||||
CRASH_NOW();
|
||||
|
@ -118,25 +121,26 @@ MonoString *godot_icall_BuildInstance_get_MSBuildPath() {
|
|||
if (build_tool != GodotSharpBuilds::XBUILD) {
|
||||
if (msbuild_path.empty()) {
|
||||
WARN_PRINT("Cannot find msbuild ('mono/builds/build_tool').");
|
||||
return NULL;
|
||||
return res;
|
||||
}
|
||||
} else {
|
||||
if (xbuild_path.empty()) {
|
||||
WARN_PRINT("Cannot find xbuild ('mono/builds/build_tool').");
|
||||
return NULL;
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
return GDMonoMarshal::mono_string_from_godot(build_tool != GodotSharpBuilds::XBUILD ? msbuild_path : xbuild_path);
|
||||
res[0] = GDMonoMarshal::mono_string_from_godot(build_tool != GodotSharpBuilds::XBUILD ? msbuild_path : xbuild_path);
|
||||
return res;
|
||||
#else
|
||||
return NULL;
|
||||
return res;
|
||||
#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_MSBuildPath", (void *)godot_icall_BuildInstance_get_MSBuildPath);
|
||||
mono_add_internal_call("GodotSharpTools.Build.BuildInstance::godot_icall_BuildInstance_get_MSBuildInfo", (void *)godot_icall_BuildInstance_get_MSBuildInfo);
|
||||
}
|
||||
|
||||
void GodotSharpBuilds::show_build_error_dialog(const String &p_message) {
|
||||
|
@ -353,9 +357,22 @@ GodotSharpBuilds::GodotSharpBuilds() {
|
|||
// Build tool settings
|
||||
EditorSettings *ed_settings = EditorSettings::get_singleton();
|
||||
if (!ed_settings->has_setting("mono/builds/build_tool")) {
|
||||
ed_settings->set_setting("mono/builds/build_tool", MSBUILD);
|
||||
ed_settings->set_setting("mono/builds/build_tool",
|
||||
#ifdef WINDOWS_ENABLED
|
||||
// TODO: Default to MSBUILD_MONO if its csc.exe issue is fixed in the installed mono version
|
||||
MSBUILD
|
||||
#else
|
||||
MSBUILD_MONO
|
||||
#endif
|
||||
);
|
||||
}
|
||||
ed_settings->add_property_hint(PropertyInfo(Variant::INT, "mono/builds/build_tool", PROPERTY_HINT_ENUM, "MSBuild (System),MSBuild (Mono),xbuild"));
|
||||
ed_settings->add_property_hint(PropertyInfo(Variant::INT, "mono/builds/build_tool", PROPERTY_HINT_ENUM,
|
||||
#ifdef WINDOWS_ENABLED
|
||||
"MSBuild (Mono),MSBuild (System)"
|
||||
#else
|
||||
"MSBuild (Mono),xbuild (Deprecated)"
|
||||
#endif
|
||||
));
|
||||
}
|
||||
|
||||
GodotSharpBuilds::~GodotSharpBuilds() {
|
||||
|
|
|
@ -67,9 +67,12 @@ public:
|
|||
};
|
||||
|
||||
enum BuildTool {
|
||||
MSBUILD,
|
||||
MSBUILD_MONO,
|
||||
XBUILD
|
||||
#ifdef WINDOWS_ENABLED
|
||||
MSBUILD
|
||||
#else
|
||||
XBUILD // Deprecated
|
||||
#endif
|
||||
};
|
||||
|
||||
_FORCE_INLINE_ static GodotSharpBuilds *get_singleton() { return singleton; }
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import os
|
||||
import platform
|
||||
|
||||
if os.name == 'nt':
|
||||
import sys
|
||||
|
@ -11,8 +12,7 @@ if os.name == 'nt':
|
|||
def _reg_open_key(key, subkey):
|
||||
try:
|
||||
return winreg.OpenKey(key, subkey)
|
||||
except (WindowsError, EnvironmentError) as e:
|
||||
import platform
|
||||
except WindowsError, OSError:
|
||||
if platform.architecture()[0] == '32bit':
|
||||
bitness_sam = winreg.KEY_WOW64_64KEY
|
||||
else:
|
||||
|
@ -20,39 +20,93 @@ def _reg_open_key(key, subkey):
|
|||
return winreg.OpenKey(key, subkey, 0, winreg.KEY_READ | bitness_sam)
|
||||
|
||||
|
||||
def _find_mono_in_reg(subkey):
|
||||
def _reg_open_key_bits(key, subkey, bits):
|
||||
sam = winreg.KEY_READ
|
||||
|
||||
if platform.architecture()[0] == '32bit':
|
||||
if bits == '64':
|
||||
# Force 32bit process to search in 64bit registry
|
||||
sam |= winreg.KEY_WOW64_64KEY
|
||||
else:
|
||||
if bits == '32':
|
||||
# Force 64bit process to search in 32bit registry
|
||||
sam |= winreg.KEY_WOW64_32KEY
|
||||
|
||||
return winreg.OpenKey(key, subkey, 0, sam)
|
||||
|
||||
|
||||
def _find_mono_in_reg(subkey, bits):
|
||||
try:
|
||||
with _reg_open_key(winreg.HKEY_LOCAL_MACHINE, subkey) as hKey:
|
||||
with _reg_open_key_bits(winreg.HKEY_LOCAL_MACHINE, subkey, bits) as hKey:
|
||||
value, regtype = winreg.QueryValueEx(hKey, 'SdkInstallRoot')
|
||||
return value
|
||||
except (WindowsError, EnvironmentError) as e:
|
||||
except WindowsError, OSError:
|
||||
return None
|
||||
|
||||
def _find_mono_in_reg_old(subkey):
|
||||
|
||||
def _find_mono_in_reg_old(subkey, bits):
|
||||
try:
|
||||
with _reg_open_key(winreg.HKEY_LOCAL_MACHINE, subkey) as hKey:
|
||||
with _reg_open_key_bits(winreg.HKEY_LOCAL_MACHINE, subkey, bits) as hKey:
|
||||
default_clr, regtype = winreg.QueryValueEx(hKey, 'DefaultCLR')
|
||||
if default_clr:
|
||||
return _find_mono_in_reg(subkey + '\\' + default_clr)
|
||||
return _find_mono_in_reg(subkey + '\\' + default_clr, bits)
|
||||
return None
|
||||
except (WindowsError, EnvironmentError):
|
||||
return None
|
||||
|
||||
|
||||
def find_mono_root_dir():
|
||||
dir = _find_mono_in_reg(r'SOFTWARE\Mono')
|
||||
if dir:
|
||||
return dir
|
||||
dir = _find_mono_in_reg_old(r'SOFTWARE\Novell\Mono')
|
||||
if dir:
|
||||
return dir
|
||||
return None
|
||||
def find_mono_root_dir(bits):
|
||||
root_dir = _find_mono_in_reg(r'SOFTWARE\Mono', bits)
|
||||
if root_dir is not None:
|
||||
return root_dir
|
||||
root_dir = _find_mono_in_reg_old(r'SOFTWARE\Novell\Mono', bits)
|
||||
if root_dir is not None:
|
||||
return root_dir
|
||||
return ''
|
||||
|
||||
|
||||
def find_msbuild_tools_path_reg():
|
||||
import subprocess
|
||||
|
||||
vswhere = os.getenv('PROGRAMFILES(X86)')
|
||||
if not vswhere:
|
||||
vswhere = os.getenv('PROGRAMFILES')
|
||||
vswhere += r'\Microsoft Visual Studio\Installer\vswhere.exe'
|
||||
|
||||
vswhere_args = ['-latest', '-requires', 'Microsoft.Component.MSBuild']
|
||||
|
||||
try:
|
||||
with _reg_open_key(winreg.HKEY_LOCAL_MACHINE, r'SOFTWARE\Microsoft\MSBuild\ToolsVersions\4.0') as hKey:
|
||||
lines = subprocess.check_output([vswhere] + vswhere_args).splitlines()
|
||||
|
||||
for line in lines:
|
||||
parts = line.split(':', 1)
|
||||
|
||||
if len(parts) < 2 or parts[0] != 'installationPath':
|
||||
continue
|
||||
|
||||
val = parts[1].strip()
|
||||
|
||||
if not val:
|
||||
raise ValueError('Value of `installationPath` entry is empty')
|
||||
|
||||
return os.path.join(val, "MSBuild\\15.0\\Bin")
|
||||
|
||||
raise ValueError('Cannot find `installationPath` entry')
|
||||
except ValueError as e:
|
||||
print('Error reading output from vswhere: ' + e.message)
|
||||
except WindowsError:
|
||||
pass # Fine, vswhere not found
|
||||
except subprocess.CalledProcessError, OSError:
|
||||
pass
|
||||
|
||||
# Try to find 14.0 in the Registry
|
||||
|
||||
try:
|
||||
subkey = r'SOFTWARE\Microsoft\MSBuild\ToolsVersions\14.0'
|
||||
with _reg_open_key(winreg.HKEY_LOCAL_MACHINE, subkey) as hKey:
|
||||
value, regtype = winreg.QueryValueEx(hKey, 'MSBuildToolsPath')
|
||||
return value
|
||||
except (WindowsError, EnvironmentError) as e:
|
||||
return None
|
||||
except WindowsError, OSError:
|
||||
return ''
|
||||
|
||||
return ''
|
||||
|
|
Loading…
Reference in a new issue