Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 35 additions & 3 deletions conan/tools/microsoft/toolchain.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
"""
Expand All @@ -23,6 +24,9 @@ class MSBuildToolchain(object):
_config_toolchain_props = textwrap.dedent("""\
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
{% if toolset_version_full_path %}
<Import Project="{{toolset_version_full_path}}" />
{% endif %}
Comment on lines +27 to +29
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm assuming this essentially mirrors the MSBuild instructions here: https://devblogs.microsoft.com/cppblog/side-by-side-minor-version-msvc-toolsets-in-visual-studio-2019/

and that the usual caution applies w.r.t ensuring this happens before <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />??

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, mostly, but instead of doing the copy and referring to it by relative path to the project, it does exactly the same as CMake, defines the full path to the original location of the .props file.

and that the usual caution applies w.r.t ensuring this happens before ??

yes, exactly, in our templates and tests this always happens, but it is true that it is not explicitly documented. I think it is a good idea to add it to the docs explicitly.

<ItemDefinitionGroup>
<ClCompile>
<PreprocessorDefinitions>{{ defines }}%(PreprocessorDefinitions)</PreprocessorDefinitions>
Expand Down Expand Up @@ -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"))
Expand Down Expand Up @@ -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):
Expand Down Expand Up @@ -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")
13 changes: 13 additions & 0 deletions test/functional/toolchains/microsoft/test_msbuildtoolchain.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
4 changes: 3 additions & 1 deletion test/unittests/tools/microsoft/test_msbuild.py
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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]},
Expand Down Expand Up @@ -277,4 +279,4 @@ def test_msbuildtoolchain_changing_flags_via_attributes():
</ResourceCompile>"""
assert expected_cl_compile in toolchain
assert expected_link in toolchain
assert expected_resource_compile in toolchain
assert expected_resource_compile in toolchain
Loading