summaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
Diffstat (limited to 'modules')
-rw-r--r--modules/mono/SCsub139
-rw-r--r--modules/mono/config.py80
-rw-r--r--modules/mono/editor/GodotSharpTools/Build/BuildSystem.cs73
-rw-r--r--modules/mono/editor/godotsharp_builds.cpp61
-rw-r--r--modules/mono/editor/godotsharp_builds.h7
-rw-r--r--modules/mono/mono_reg_utils.py92
6 files changed, 339 insertions, 113 deletions
diff --git a/modules/mono/SCsub b/modules/mono/SCsub
index caf4fdb3ca..13212636e3 100644
--- a/modules/mono/SCsub
+++ b/modules/mono/SCsub
@@ -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):
+ import subprocess
+ import mono_reg_utils as monoreg
+ from shutil import copyfile
+
+ framework_path_override = ''
+
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')
+ 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 = 'msbuild'
+ 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)
- output_path = os.path.abspath(os.path.join(str(target[0]), os.pardir))
+ 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' ]
-
- 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')
+ try:
+ subprocess.check_call(msbuild_args, env=msbuild_env)
+ except subprocess.CalledProcessError:
+ raise RuntimeError('GodotSharpTools build failed')
+
+ 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'
diff --git a/modules/mono/config.py b/modules/mono/config.py
index 0833d30ce1..44eef45f76 100644
--- a/modules/mono/config.py
+++ b/modules/mono/config.py
@@ -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 os.path.isdir('bin'):
- os.mkdir('bin')
- elif os.path.exists(mono_dll_dst):
- copy_mono_dll = False
+ if not mono_dll_name:
+ raise RuntimeError('Could not find mono shared library in: ' + mono_bin_path)
- 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')
diff --git a/modules/mono/editor/GodotSharpTools/Build/BuildSystem.cs b/modules/mono/editor/GodotSharpTools/Build/BuildSystem.cs
index 5544233eb7..bdbef82aad 100644
--- a/modules/mono/editor/GodotSharpTools/Build/BuildSystem.cs
+++ b/modules/mono/editor/GodotSharpTools/Build/BuildSystem.cs
@@ -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,24 +13,38 @@ 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 ret = godot_icall_BuildInstance_get_MSBuildPath();
+ string path;
+ string frameworkPathOverride;
- if (ret == null)
- throw new FileNotFoundException("Cannot find the MSBuild executable.");
+ public string MSBuildPath
+ {
+ get { return path; }
+ }
- return ret;
+ 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;
private string config;
@@ -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();
+
+ List<string> customPropertiesList = new List<string>();
+
+ if (customProperties != null)
+ customPropertiesList.AddRange(customProperties);
- ProcessStartInfo startInfo = new ProcessStartInfo(MSBuildPath, compilerArgs);
+ 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();
+
+ List<string> customPropertiesList = new List<string>();
+
+ if (customProperties != null)
+ customPropertiesList.AddRange(customProperties);
+
+ if (msbuildInfo.FrameworkPathOverride.Length > 0)
+ customPropertiesList.Add("FrameworkPathOverride=" + msbuildInfo.FrameworkPathOverride);
- ProcessStartInfo startInfo = new ProcessStartInfo("msbuild", compilerArgs);
+ 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;
diff --git a/modules/mono/editor/godotsharp_builds.cpp b/modules/mono/editor/godotsharp_builds.cpp
index d3808769fb..c3b9c140e4 100644
--- a/modules/mono/editor/godotsharp_builds.cpp
+++ b/modules/mono/editor/godotsharp_builds.cpp
@@ -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() {
diff --git a/modules/mono/editor/godotsharp_builds.h b/modules/mono/editor/godotsharp_builds.h
index 6d5fa3b44a..3486f9f3e9 100644
--- a/modules/mono/editor/godotsharp_builds.h
+++ b/modules/mono/editor/godotsharp_builds.h
@@ -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; }
diff --git a/modules/mono/mono_reg_utils.py b/modules/mono/mono_reg_utils.py
index e9988625f5..22c4aeaf4c 100644
--- a/modules/mono/mono_reg_utils.py
+++ b/modules/mono/mono_reg_utils.py
@@ -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 ''