Navigation Menu

Skip to content

Commit

Permalink
- call compilervars.sh within CMake helper (Intel C++)
Browse files Browse the repository at this point in the history
Signed-off-by: SSE4 <tomskside@gmail.com>
  • Loading branch information
SSE4 committed May 7, 2020
1 parent d1869e1 commit 3b1d72f
Show file tree
Hide file tree
Showing 6 changed files with 212 additions and 13 deletions.
18 changes: 11 additions & 7 deletions conans/client/build/cmake.py
Expand Up @@ -215,13 +215,17 @@ def _run(self, command):
the_os = self._settings.get_safe("os")
is_clangcl = the_os == "Windows" and compiler == "clang"
is_msvc = compiler == "Visual Studio"
if ((is_msvc or is_clangcl) and platform.system() == "Windows" and
self.generator in ["Ninja", "NMake Makefiles", "NMake Makefiles JOM"]):
vcvars_dict = tools.vcvars_dict(self._settings, force=True, filter_known_paths=False,
output=self._conanfile.output)
with _environment_add(vcvars_dict, post=self._append_vcvars):
self._conanfile.run(command)
else:
is_intel = compiler == "intel"
context = tools.no_op()
if self.generator in ["Ninja", "NMake Makefiles", "NMake Makefiles JOM", "Unix Makefiles"]:
if (is_msvc or is_clangcl) and platform.system() == "Windows":
vcvars_dict = tools.vcvars_dict(self._settings, force=True, filter_known_paths=False,
output=self._conanfile.output)
context = _environment_add(vcvars_dict, post=self._append_vcvars)
elif is_intel:
compilervars_dict = tools.compilervars_dict(self._settings, force=True)
context = _environment_add(compilervars_dict, post=self._append_vcvars)
with context:
self._conanfile.run(command)

def configure(self, args=None, defs=None, source_dir=None, build_dir=None,
Expand Down
2 changes: 2 additions & 0 deletions conans/client/tools/__init__.py
Expand Up @@ -7,6 +7,8 @@
# noinspection PyUnresolvedReferences
from .files import *
# noinspection PyUnresolvedReferences
from .intel import *
# noinspection PyUnresolvedReferences
from .net import *
# noinspection PyUnresolvedReferences
from .oss import *
Expand Down
44 changes: 44 additions & 0 deletions conans/client/tools/env.py
@@ -1,10 +1,12 @@
import os
import platform
import sys
from contextlib import contextmanager

from conans.client.run_environment import RunEnvironment
from conans.client.tools.files import _path_equals, which
from conans.errors import ConanException
from conans.util.runners import check_output_runner


@contextmanager
Expand Down Expand Up @@ -111,3 +113,45 @@ def remove_from_path(command):

with environment_append({"PATH": curpath}):
yield


def env_diff(cmd, only_diff):
known_path_lists = ("include", "lib", "libpath", "path")
if platform.system() == "Windows":
cmd += " && set"
else:
cmd += " && export"
ret = check_output_runner(cmd)
new_env = {}
for line in ret.splitlines():
line = line.strip()

if line == "\n" or not line:
continue
try:
name_var, value = line.split("=", 1)
name_var = str(name_var)
value = str(value)
new_value = value.split(os.pathsep) if name_var.lower() in known_path_lists else value
# Return only new vars & changed ones, but only with the changed elements if the var is
# a list
if only_diff:
old_value = os.environ.get(name_var)
if name_var.lower() == "path":
old_values_lower = [v.lower() for v in old_value.split(os.pathsep)]
# Clean all repeated entries, not append if the element was already there
new_env[name_var] = [v for v in new_value if v.lower() not in old_values_lower]
elif old_value and value.endswith(os.pathsep + old_value):
# The new value ends with separator and the old value, is a list,
# get only the new elements
new_env[name_var] = value[:-(len(old_value) + 1)].split(os.pathsep)
elif value != old_value:
# Only if the vcvars changed something, we return the variable,
# otherwise is not vcvars related
new_env[name_var] = new_value
else:
new_env[name_var] = new_value

except ValueError:
pass
return new_env
108 changes: 108 additions & 0 deletions conans/client/tools/intel.py
@@ -0,0 +1,108 @@
import os
import platform
from contextlib import contextmanager

from conans.client.tools.env import environment_append, env_diff
from conans.client.tools.win import is_win64, _system_registry_key, MSVS_YEAR
from conans.errors import ConanException
from conans.util.env_reader import get_env


# https://software.intel.com/en-us/articles/intel-compiler-and-composer-update-version-numbers-to-compiler-version-number-mapping
INTEL_YEAR = {"19.1": "2020",
"19": "2019",
"18": "2018",
"17": "2017",
"16": "2016",
"15": "2015"}


def intel_installation_path(version, arch):
installation_path = get_env("CONAN_INTEL_INSTALLATION_PATH")
if installation_path:
return installation_path

system = platform.system()
if system in ["Linux", "Darwin"]:
subdir = "mac" if system == "Darwin" else "linux"
year = INTEL_YEAR.get(version)
installation_path = os.path.join(os.sep, "opt", "intel",
"compilers_and_libraries_%s" % year, subdir)
elif system == "Windows":
if arch == "x86":
intel_arch = "IA32"
elif arch == "x86_64":
intel_arch = "EM64T"
else:
raise ConanException("don't know how to find Intel compiler on %s" % arch)
if is_win64():
base = r"SOFTWARE\WOW6432Node\Intel\Suites\{version}".format(version=version)
else:
base = r"SOFTWARE\Intel\Suites\{version}".format(version=version)
from six.moves import winreg # @UnresolvedImport
path = base + r"\Defaults\C++\{arch}".format(arch=intel_arch)
subkey = _system_registry_key(winreg.HKEY_LOCAL_MACHINE, path, "SubKey")
if not subkey:
raise ConanException("unable to find Intel C++ compiler installation")
path = base + r"\{subkey}\C++".format(subkey=subkey)
installation_path = _system_registry_key(winreg.HKEY_LOCAL_MACHINE, path, "LatestDir")
if not installation_path:
raise ConanException("unable to find Intel C++ compiler installation")
else:
raise ConanException("don't know how to find Intel compiler on %s" % system)
return installation_path


def compilervars_command(settings, arch=None, compiler_version=None, force=False):
"""
https://software.intel.com/en-us/intel-system-studio-cplusplus-compiler-user-and-reference-guide-using-compilervars-file
:return:
"""
if "PSTLROOT" in os.environ and not force:
return "echo Conan:compilervars already set"
compiler_version = compiler_version or settings.get_safe("compiler.version")
arch = arch or settings.get_safe("arch")
system = platform.system()
cvars = "compilervars.bat" if system == "Window" else "compilervars.sh"
command = os.path.join(intel_installation_path(version=compiler_version, arch=arch), "bin", cvars)
command = '"%s"' % command
if system != "Windows":
command = ". " + command # dot is more portable than source
if arch == "x86_64":
command += " -arch intel64"
if system != "Windows":
command = "COMPILERVARS_ARCHITECTURE=intel64 " + command
elif arch == "x86":
command += " -arch ia32"
if system != "Windows":
command = "COMPILERVARS_ARCHITECTURE=ia32 " + command
else:
raise ConanException("don't know how to call %s for %s" % (cvars, arch))
if system == "Darwin":
command += " -platform mac"
command = "COMPILERVARS_PLATFORM=mac " + command
elif system == "Linux":
command += " -platform linux"
command = "COMPILERVARS_PLATFORM=linux " + command
elif system == "Windows":
command += " -platform windows"
else:
raise ConanException("don't know how to call %s for %s" % (cvars, system))
compiler_base = settings.get_safe("compiler.base")
if compiler_base == "Visual Studio":
base_version = settings.get_safe("compiler.base.version")
if base_version:
command += "vs%s" % MSVS_YEAR.get(base_version)
return command


def compilervars_dict(settings, arch=None, compiler_version=None, force=False, only_diff=True):
cmd = compilervars_command(settings, arch, compiler_version, force)
return env_diff(cmd, only_diff)


@contextmanager
def compilervars(*args, **kwargs):
new_env = compilervars_dict(*args, **kwargs)
with environment_append(new_env):
yield
25 changes: 19 additions & 6 deletions conans/client/tools/win.py
Expand Up @@ -57,6 +57,13 @@ def _system_registry_key(key, subkey, query):
winreg.CloseKey(hkey)


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


def _visual_compiler(output, version):
""""version have to be 8.0, or 9.0 or... anything .0"""
if platform.system().startswith("CYGWIN"):
Expand All @@ -74,14 +81,10 @@ def _visual_compiler(output, version):
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:
if is_win64():
key_name = r'SOFTWARE\Wow6432Node\Microsoft\VisualStudio\SxS\VC7'
else:
key_name = r'HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\SxS\VC7'
key_name = r'SOFTWARE\Microsoft\VisualStudio\SxS\VC7'

if _system_registry_key(winreg.HKEY_LOCAL_MACHINE, key_name, version):
installed_version = Version(version).major(fill=False)
Expand All @@ -96,6 +99,16 @@ def latest_vs_version_installed(output):
return latest_visual_studio_version_installed(output=output)


MSVS_YEAR = {"16": "2019",
"15": "2017",
"14": "2015",
"12": "2013",
"11": "2012",
"10": "2010",
"9": "2008",
"8": "2005"}


MSVS_DEFAULT_TOOLSETS = {"16": "v142",
"15": "v141",
"14": "v140",
Expand Down
28 changes: 28 additions & 0 deletions conans/test/unittests/client/build/cmake_test.py
Expand Up @@ -1348,6 +1348,34 @@ def test_vcvars_applied(self, generator, compiler, version):
cmake.build()
self.assertTrue(vcvars_mock.called, "vcvars weren't called")

@parameterized.expand([('Ninja',),
('NMake Makefiles',),
('NMake Makefiles JOM',),
('Unix Makefiles',),
])
def test_compilervars_applied(self, generator):
conanfile = ConanFileMock()
settings = Settings.loads(get_default_settings_yml())
settings.os = "Windows"
settings.compiler = "intel"
settings.arch = "x86_64"
settings.compiler.version = "19"
conanfile.settings = settings

cmake = CMake(conanfile, generator=generator)

with mock.patch("conans.client.tools.compilervars_dict") as cvars_mock:
cvars_mock.__enter__ = mock.MagicMock(return_value=(mock.MagicMock(), None))
cvars_mock.__exit__ = mock.MagicMock(return_value=None)
cmake.configure()
self.assertTrue(cvars_mock.called, "compilervars weren't called")

with mock.patch("conans.client.tools.compilervars_dict") as cvars_mock:
cvars_mock.__enter__ = mock.MagicMock(return_value=(mock.MagicMock(), None))
cvars_mock.__exit__ = mock.MagicMock(return_value=None)
cmake.build()
self.assertTrue(cvars_mock.called, "compilervars weren't called")

def test_cmake_program(self):
conanfile = ConanFileMock()
settings = Settings.loads(get_default_settings_yml())
Expand Down

0 comments on commit 3b1d72f

Please sign in to comment.