Navigation Menu

Skip to content

Commit

Permalink
- allow vcvars for clang-cl (#3574)
Browse files Browse the repository at this point in the history
* - allow vcvars for clang-cl

Signed-off-by: SSE4 <tomskside@gmail.com>

* - move _visual_compiler_last from detect.py into win.py, renaming to the latest_visual_studio_version_installed

Signed-off-by: SSE4 <tomskside@gmail.com>

* - look from the latest to oldest

Signed-off-by: SSE4 <tomskside@gmail.com>

* - add negative test case

Signed-off-by: SSE4 <tomskside@gmail.com>

* - handle latest_visual_studio_version_installed returns None

Signed-off-by: SSE4 <tomskside@gmail.com>

* - add system_registry_key context manager, ensure key is always closed

Signed-off-by: SSE4 <tomskside@gmail.com>

* - make system_registry_key private

Signed-off-by: SSE4 <tomskside@gmail.com>

* - return just Visual Studio version

Signed-off-by: SSE4 <tomskside@gmail.com>

* - simplify _system_registry_key

Signed-off-by: SSE4 <tomskside@gmail.com>

* - remove decorator

Signed-off-by: SSE4 <tomskside@gmail.com>

* try/catch for openKey and for QueryValue

* - set detected compiler tuple properly

Signed-off-by: SSE4 <tomskside@gmail.com>
  • Loading branch information
SSE4 authored and jgsogo committed Sep 27, 2018
1 parent 2b2058b commit 2b3e0e3
Show file tree
Hide file tree
Showing 3 changed files with 153 additions and 92 deletions.
77 changes: 3 additions & 74 deletions conans/client/conf/detect.py
Expand Up @@ -5,7 +5,7 @@

from conans.client.output import Color
from conans.model.version import Version
from conans.tools import vs_installation_path
from conans.client.tools import latest_visual_studio_version_installed


def _execute(command):
Expand Down Expand Up @@ -68,78 +68,6 @@ def _clang_compiler(output, compiler_exe="clang"):
except:
return None


def _visual_compiler_cygwin(output, version):
if os.path.isfile("/proc/registry/HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Windows/CurrentVersion/ProgramFilesDir (x86)"):
is_64bits = True
else:
is_64bits = False

if is_64bits:
key_name = r'HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\SxS\VC7'
else:
key_name = r'HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\SxS\VC7'

if not os.path.isfile("/proc/registry/" + key_name.replace('\\', '/') + "/" + version):
return None

installed_version = Version(version).major(fill=False)
compiler = "Visual Studio"
output.success("CYGWIN: Found %s %s" % (compiler, installed_version))
return compiler, installed_version


def _visual_compiler(output, version):
'version have to be 8.0, or 9.0 or... anything .0'
if platform.system().startswith("CYGWIN"):
return _visual_compiler_cygwin(output, version)

if version == "15":
vs_path = os.getenv('vs150comntools')
path = vs_path or vs_installation_path("15")
if path:
compiler = "Visual Studio"
output.success("Found %s %s" % (compiler, "15"))
return compiler, "15"
return None

version = "%s.0" % version
from six.moves import winreg # @UnresolvedImport
try:
hKey = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE,
r"SOFTWARE\Microsoft\Windows\CurrentVersion")
winreg.QueryValueEx(hKey, "ProgramFilesDir (x86)")
is_64bits = True
except EnvironmentError:
is_64bits = False
finally:
winreg.CloseKey(hKey)

if is_64bits:
key_name = r'SOFTWARE\Wow6432Node\Microsoft\VisualStudio\SxS\VC7'
else:
key_name = r'HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\SxS\VC7'

try:
key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, key_name)
winreg.QueryValueEx(key, version)

installed_version = Version(version).major(fill=False)
compiler = "Visual Studio"
output.success("Found %s %s" % (compiler, installed_version))
return compiler, installed_version
except EnvironmentError:
return None


def _visual_compiler_last(output):
last_version = None
for version in ["8", "9", "10", "11", "12", "14", "15"]:
vs = _visual_compiler(output, version)
last_version = vs or last_version
return last_version


def _sun_cc_compiler(output, compiler_exe="cc"):
try:
_, out = _execute('%s -V' % compiler_exe)
Expand Down Expand Up @@ -174,7 +102,8 @@ def _get_default_compiler(output):
return None

if detected_os() == "Windows":
vs = _visual_compiler_last(output)
version = latest_visual_studio_version_installed(output)
vs = ('Visual Studio', version) if version else None
gcc = _gcc_compiler(output)
clang = _clang_compiler(output)
if platform.system() == "SunOS":
Expand Down
119 changes: 101 additions & 18 deletions conans/client/tools/win.py
Expand Up @@ -14,10 +14,90 @@
from conans.util.env_reader import get_env
from conans.util.files import decode_text, save, mkdir_tmp
from conans.unicode import get_cwd
from conans.model.version import Version

_global_output = None


def _visual_compiler_cygwin(output, version):
if os.path.isfile("/proc/registry/HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Windows/CurrentVersion/ProgramFilesDir (x86)"):
is_64bits = True
else:
is_64bits = False

if is_64bits:
key_name = r'HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\SxS\VC7'
else:
key_name = r'HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\SxS\VC7'

if not os.path.isfile("/proc/registry/" + key_name.replace('\\', '/') + "/" + version):
return None

installed_version = Version(version).major(fill=False)
compiler = "Visual Studio"
output.success("CYGWIN: Found %s %s" % (compiler, installed_version))
return compiler, installed_version


def _system_registry_key(key, subkey, query):
from six.moves import winreg # @UnresolvedImport
try:
hkey = winreg.OpenKey(key, subkey)
except (OSError, WindowsError): # Raised by OpenKey/Ex if the function fails (py3, py2)
return None
else:
try:
value, _ = winreg.QueryValueEx(hkey, query)
return value
except EnvironmentError:
return None
finally:
winreg.CloseKey(hkey)


def _visual_compiler(output, version):
""""version have to be 8.0, or 9.0 or... anything .0"""
if platform.system().startswith("CYGWIN"):
return _visual_compiler_cygwin(output, version)

if version == "15":
vs_path = os.getenv('vs150comntools')
path = vs_path or vs_installation_path("15")
if path:
compiler = "Visual Studio"
output.success("Found %s %s" % (compiler, "15"))
return compiler, "15"
return None

version = "%s.0" % version

from six.moves import winreg # @UnresolvedImport
is_64bits = _system_registry_key(winreg.HKEY_LOCAL_MACHINE,
r"SOFTWARE\Microsoft\Windows\CurrentVersion",
"ProgramFilesDir (x86)") is not None

if is_64bits:
key_name = r'SOFTWARE\Wow6432Node\Microsoft\VisualStudio\SxS\VC7'
else:
key_name = r'HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\SxS\VC7'

if _system_registry_key(winreg.HKEY_LOCAL_MACHINE, key_name, version):
installed_version = Version(version).major(fill=False)
compiler = "Visual Studio"
output.success("Found %s %s" % (compiler, installed_version))
return compiler, installed_version

return None


def latest_visual_studio_version_installed(output):
for version in reversed(["8", "9", "10", "11", "12", "14", "15"]):
vs = _visual_compiler(output, version)
if vs:
return vs[1]
return None


@deprecation.deprecated(deprecated_in="1.2", removed_in="2.0",
details="Use the MSBuild() build helper instead")
def msvc_build_command(settings, sln_path, targets=None, upgrade_project=True, build_type=None,
Expand Down Expand Up @@ -214,30 +294,33 @@ def find_windows_10_sdk():
(winreg.HKEY_CURRENT_USER, r'SOFTWARE')
]
for key, subkey in hives:
try:
hkey = winreg.OpenKey(key, r'%s\Microsoft\Microsoft SDKs\Windows\v10.0' % subkey)
try:
installation_folder, _ = winreg.QueryValueEx(hkey, 'InstallationFolder')
if os.path.isdir(installation_folder):
include_dir = os.path.join(installation_folder, 'include')
for sdk_version in os.listdir(include_dir):
if os.path.isdir(os.path.join(include_dir, sdk_version)) and sdk_version.startswith('10.'):
windows_h = os.path.join(include_dir, sdk_version, 'um', 'Windows.h')
if os.path.isfile(windows_h):
return sdk_version
except EnvironmentError:
pass
finally:
winreg.CloseKey(hkey)
except (OSError, WindowsError): # Raised by OpenKey/Ex if the function fails (py3, py2).
pass
installation_folder = _system_registry_key(key, r'%s\Microsoft\Microsoft SDKs\Windows\v10.0' % subkey,
'InstallationFolder')
if installation_folder:
if os.path.isdir(installation_folder):
include_dir = os.path.join(installation_folder, 'include')
for sdk_version in os.listdir(include_dir):
if os.path.isdir(os.path.join(include_dir, sdk_version)) and sdk_version.startswith('10.'):
windows_h = os.path.join(include_dir, sdk_version, 'um', 'Windows.h')
if os.path.isfile(windows_h):
return sdk_version
return None


def vcvars_command(settings, arch=None, compiler_version=None, force=False, vcvars_ver=None,
winsdk_version=None):
arch_setting = arch or settings.get_safe("arch")
compiler_version = compiler_version or settings.get_safe("compiler.version")

compiler = settings.get_safe("compiler")
if compiler == 'Visual Studio':
compiler_version = compiler_version or settings.get_safe("compiler.version")
else:
# vcvars might be still needed for other compilers, e.g. clang-cl or Intel C++,
# as they might be using Microsoft STL and other tools (e.g. resource compiler, manifest tool, etc)
# in this case, use the latest Visual Studio available on the machine
last_version = latest_visual_studio_version_installed(output=_global_output)

compiler_version = compiler_version or last_version
os_setting = settings.get_safe("os")
if not compiler_version:
raise ConanException("compiler.version setting required for vcvars not defined")
Expand Down
49 changes: 49 additions & 0 deletions conans/test/util/vcvars_clangcl_test.py
@@ -0,0 +1,49 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4

import platform
import unittest
from nose.plugins.attrib import attr
from conans.model.settings import Settings
from conans.client.conf import default_settings_yml
from conans.errors import ConanException
from conans import tools
from mock import mock


@attr('visual_studio')
@unittest.skipUnless(platform.system() == "Windows", "Requires Windows")
class VCVarsClangClTest(unittest.TestCase):

def test_simple(self):
settings = Settings.loads(default_settings_yml)
settings.compiler = 'clang'
settings.compiler.version = '5.0'
settings.arch = 'x86'
settings.os = 'Windows'

command = tools.vcvars_command(settings)
self.assertIn('vcvarsall.bat', command)
self.assertIn('x86', command)

def test_no_version(self):
settings = Settings.loads(default_settings_yml)
settings.compiler = 'clang'
settings.arch = 'x86_64'
settings.os = 'Windows'

command = tools.vcvars_command(settings)
self.assertIn('vcvarsall.bat', command)
self.assertIn('amd64', command)

def test_no_msvc(self):
settings = Settings.loads(default_settings_yml)
settings.compiler = 'clang'
settings.arch = 'x86_64'
settings.os = 'Windows'

with mock.patch('conans.client.tools.win.latest_visual_studio_version_installed',
mock.MagicMock(return_value=None)):
with self.assertRaises(ConanException):
tools.vcvars_command(settings)

0 comments on commit 2b3e0e3

Please sign in to comment.