diff --git a/conan/tools/microsoft/toolchain.py b/conan/tools/microsoft/toolchain.py index ab92b3e28e2..30d9df71dae 100644 --- a/conan/tools/microsoft/toolchain.py +++ b/conan/tools/microsoft/toolchain.py @@ -5,15 +5,16 @@ from jinja2 import Template from conan.internal import check_duplicated_generator +from conan.internal.api.detect.detect_vs import vs_installation_path from conan.tools.build import build_jobs from conan.tools.intel.intel_cc import IntelCC from conan.tools.microsoft.visual import VCVars, msvs_toolset, msvc_runtime_flag, \ - msvc_platform_from_arch + msvc_platform_from_arch, vs_ide_version from conan.errors import ConanException from conan.internal.util.files import save, load -class MSBuildToolchain(object): +class MSBuildToolchain: """ MSBuildToolchain class generator """ @@ -23,6 +24,9 @@ class MSBuildToolchain(object): _config_toolchain_props = textwrap.dedent("""\ + {% if toolset_version_full_path %} + + {% endif %} {{ defines }}%(PreprocessorDefinitions) @@ -76,6 +80,7 @@ def __init__(self, conanfile): #: setting, else, it'll be based on ``msvc`` version. self.toolset = msvs_toolset(conanfile) self.properties = {} + self.toolset_version_full_path = _get_toolset_props(conanfile) def _name_condition(self, settings): platform = msvc_platform_from_arch(settings.get_safe("arch")) @@ -156,7 +161,8 @@ def format_macro(key, value): "compile_options": compile_options, "parallel": parallel, "properties": self.properties, - "winsdk_version": winsdk_version + "winsdk_version": winsdk_version, + "toolset_version_full_path": self.toolset_version_full_path } def _write_config_toolchain(self, config_filename): @@ -217,3 +223,29 @@ def _get_extra_flags(self): exelinkflags = self._conanfile.conf.get("tools.build:exelinkflags", default=[], check_type=list) defines = self._conanfile.conf.get("tools.build:defines", default=[], check_type=list) return cxxflags, cflags, defines, sharedlinkflags, exelinkflags + + +def _get_toolset_props(conanfile): + msvc_update = conanfile.conf.get("tools.microsoft:msvc_update") + compiler_update = msvc_update or conanfile.settings.get_safe("compiler.update") + if compiler_update is None: + return + + vs_version = vs_ide_version(conanfile) + if int(vs_version) <= 14: + return + vs_install_path = conanfile.conf.get("tools.microsoft.msbuild:installation_path") + vs_path = vs_install_path or vs_installation_path(vs_version) + if not vs_path or not os.path.isdir(vs_path): + return + + basebuild = os.path.normpath(os.path.join(vs_path, "VC/Auxiliary/Build")) + # The equivalent of compiler 19.26 is toolset 14.26 + compiler_version = str(conanfile.settings.compiler.version) + vcvars_ver = "14.{}{}".format(compiler_version[-1], compiler_update) + for folder in os.listdir(basebuild): + if not os.path.isdir(os.path.join(basebuild, folder)): + continue + if folder.startswith(vcvars_ver): + result = folder + return os.path.join(basebuild, result, f"Microsoft.VCToolsVersion.{result}.props") diff --git a/test/functional/toolchains/microsoft/test_msbuildtoolchain.py b/test/functional/toolchains/microsoft/test_msbuildtoolchain.py index 60b1d32893b..a3ee9168bd4 100644 --- a/test/functional/toolchains/microsoft/test_msbuildtoolchain.py +++ b/test/functional/toolchains/microsoft/test_msbuildtoolchain.py @@ -48,3 +48,16 @@ def test_msbuildtoolchain_winsdk_version(): # I have verified also opening VS IDE that the setting is correctly configured # because the test always run over vcvars that already activates it assert "amd64 - winsdk_version=10.0 - vcvars_ver=14.3" in client.out + + +@pytest.mark.skipif(platform.system() != "Windows", reason="Requires Windows") +def test_msbuildtoolchain_compiler_update(): + # It only works for update=8, because 19.38 is the compiler in Github actions! + client = TestClient(path_with_spaces=False) + client.run("new msbuild_lib -d name=hello -d version=0.1") + # conantoolchain.props is already imported in the msbuild_exe tempalte + client.run("create . -s arch=x86_64 -s compiler.version=193 -s compiler.update=8") + # I have verified also opening VS IDE that the setting is correctly configured + # because the test always run over vcvars that already activates it + assert "amd64 - winsdk_version=None - vcvars_ver=14.38" in client.out + assert "hello/0.1: _MSC_VER1938" in client.out diff --git a/test/unittests/tools/microsoft/test_msbuild.py b/test/unittests/tools/microsoft/test_msbuild.py index 777cc888736..57819abd124 100644 --- a/test/unittests/tools/microsoft/test_msbuild.py +++ b/test/unittests/tools/microsoft/test_msbuild.py @@ -54,6 +54,7 @@ def test_msbuild_toolset(): "os": ["Windows"], "arch": ["x86_64"]}) conanfile = ConanFile(None) + conanfile.conf = Conf() conanfile.settings = "os", "compiler", "build_type", "arch" conanfile.settings = settings conanfile.settings.build_type = "Release" @@ -77,6 +78,7 @@ def test_msbuild_toolset(): ]) def test_msbuild_toolset_for_intel_cc(mode, expected_toolset): conanfile = ConanFile() + conanfile.conf = Conf() conanfile.settings = "os", "compiler", "build_type", "arch" conanfile.settings = Settings({"build_type": ["Release"], "compiler": {"intel-cc": {"version": ["2021.3"], "mode": [mode]}, @@ -277,4 +279,4 @@ def test_msbuildtoolchain_changing_flags_via_attributes(): """ assert expected_cl_compile in toolchain assert expected_link in toolchain - assert expected_resource_compile in toolchain \ No newline at end of file + assert expected_resource_compile in toolchain