Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix for msvc toolset version overflow #15588

Merged
13 changes: 9 additions & 4 deletions conan/internal/api/detect_api.py
Expand Up @@ -382,9 +382,14 @@ def detect_default_compiler():
return None, None, None

if platform.system() == "Windows":
compiler, version, compiler_exe = detect_msvc_compiler()
if compiler:
return compiler, version, compiler_exe
ide_version = _detect_vs_ide_version()
version = {"17": "193", "16": "192", "15": "191"}.get(str(ide_version)) # Map to compiler
if ide_version == "17":
update = detect_msvc_update(version) # FIXME weird passing here the 193 compiler version
if update and int(update) >= 10:
version = "194"
if version:
return 'msvc', Version(version), None

if platform.system() == "SunOS":
sun_cc, sun_cc_version, compiler_exe = detect_suncc_compiler()
Expand All @@ -407,7 +412,7 @@ def detect_default_compiler():


def default_msvc_ide_version(version):
version = {"193": "17", "192": "16", "191": "15"}.get(str(version))
version = {"194": "17", "193": "17", "192": "16", "191": "15"}.get(str(version))
if version:
return Version(version)

Expand Down
7 changes: 5 additions & 2 deletions conan/tools/microsoft/visual.py
Expand Up @@ -59,7 +59,8 @@ def msvc_version_to_vs_ide_version(version):
'190': '14',
'191': '15',
'192': '16',
'193': '17'}
'193': '17',
'194': '17'} # Note both 193 and 194 belong to VS 17 2022
return _visuals[str(version)]


Expand All @@ -75,7 +76,8 @@ def msvc_version_to_toolset_version(version):
'190': 'v140',
'191': 'v141',
'192': 'v142',
"193": 'v143'}
"193": 'v143',
"194": 'v143'}
return toolsets.get(str(version))


Expand Down Expand Up @@ -140,6 +142,7 @@ def generate(self, scope="build"):
compiler_update = conanfile.settings.get_safe("compiler.update", "")
# The equivalent of compiler 19.26 is toolset 14.26
vcvars_ver = "14.{}{}".format(compiler_version[-1], compiler_update)

vcvarsarch = _vcvars_arch(conanfile)

winsdk_version = conanfile.conf.get("tools.microsoft:winsdk_version", check_type=str)
Expand Down
4 changes: 2 additions & 2 deletions conans/client/conf/__init__.py
Expand Up @@ -94,14 +94,14 @@
"10", "10.1", "10.2", "10.3", "10.4", "10.5",
"11", "11.1", "11.2", "11.3", "11.4",
"12", "12.1", "12.2", "12.3",
"13", "13.1", "13.2",
"13", "13.1", "13.2",
"14", "14.1"]
libcxx: [libstdc++, libstdc++11]
threads: [null, posix, win32] # Windows MinGW
exception: [null, dwarf2, sjlj, seh] # Windows MinGW
cppstd: [null, 98, gnu98, 11, gnu11, 14, gnu14, 17, gnu17, 20, gnu20, 23, gnu23]
msvc:
version: [170, 180, 190, 191, 192, 193]
version: [170, 180, 190, 191, 192, 193, 194]
update: [null, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
memsharded marked this conversation as resolved.
Show resolved Hide resolved
runtime: [static, dynamic]
runtime_type: [Debug, Release]
Expand Down
2 changes: 1 addition & 1 deletion conans/client/conf/detect_vs.py
Expand Up @@ -12,7 +12,7 @@ def vs_installation_path(version):


def vs_detect_update(version):
version = {"193": "17", "192": "16", "191": "15"}.get(str(version))
version = {"194": "17", "193": "17", "192": "16", "191": "15"}.get(str(version))
full_version = _vs_installation_path(version)[1]
components = full_version.split(".")
if len(components) > 1:
Expand Down
43 changes: 31 additions & 12 deletions conans/client/graph/compatibility.py
Expand Up @@ -30,26 +30,45 @@ def compatibility(conanfile):
def cppstd_compat(conanfile):
# It will try to find packages with all the cppstd versions
extension_properties = getattr(conanfile, "extension_properties", {})
if extension_properties.get("compatibility_cppstd") is False:
return []
compiler = conanfile.settings.get_safe("compiler")
compiler_version = conanfile.settings.get_safe("compiler.version")
cppstd = conanfile.settings.get_safe("compiler.cppstd")
if not compiler or not compiler_version or not cppstd:
if not compiler or not compiler_version:
return []
base = dict(conanfile.settings.values_list)
cppstd_possible_values = supported_cppstd(conanfile)
if cppstd_possible_values is None:
conanfile.output.warning(f'No cppstd compatibility defined for compiler "{compiler}"')
return []
ret = []
for _cppstd in cppstd_possible_values:
if _cppstd is None or _cppstd == cppstd:
factors = [] # List of list, each sublist is a potential combination
if cppstd is not None and extension_properties.get("compatibility_cppstd") is not False:
cppstd_possible_values = supported_cppstd(conanfile)
if cppstd_possible_values is None:
conanfile.output.warning(f'No cppstd compatibility defined for compiler "{compiler}"')
else:
factors.append([{"compiler.cppstd": v} for v in cppstd_possible_values if v != cppstd])

if compiler == "msvc":
msvc_fallback = {"194": "193"}.get(compiler_version)
if msvc_fallback:
factors.append([{"compiler.version": msvc_fallback}])

conanfile.output.info(f"FACTORS {factors}")
combinations = []
for factor in factors:
if not combinations:
combinations = factor
continue
new_combinations = []
for comb in combinations:
for f in factor:
comb = comb.copy()
comb.update(f)
new_combinations.append(comb)
combinations = new_combinations

conanfile.output.info(f"COMbINATIONS {combinations}")
Copy link
Contributor

Choose a reason for hiding this comment

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

COMbINATIONS typo here, but maybe consider having both FACTORS and COMBINATIONS not being all caps? Also found it a little confusing, from a user perspective I dont know what factors or combinations are.

ret = []
for comb in combinations:
configuration = base.copy()
configuration["compiler.cppstd"] = _cppstd
configuration.update(comb)
ret.append({"settings": [(k, v) for k, v in configuration.items()]})

return ret
"""

Expand Down
21 changes: 21 additions & 0 deletions conans/test/integration/package_id/test_cache_compatibles.py
Expand Up @@ -377,6 +377,27 @@ def test_unnecessary_builds(self):
c.run("install --requires=app/0.1 --build=missing")
assert re.search(r"Skipped binaries(\s*)tool/0.1", c.out)

def test_msvc_194_fallback(self):
c = TestClient()
save(c.cache.default_profile_path, "")
c.save({"conanfile.py": GenConanfile("mylib", "1.0").with_settings("os", "arch",
"compiler", "build_type"),
"profile_build": "[settings]\nos=Windows\narch=x86_64"})

c.run("create . -s os=Windows -s arch=x86_64 -s build_type=Release "
"-s compiler=msvc "
"-s compiler.version=193 -s compiler.cppstd=17 "
"-s compiler.runtime=dynamic -pr:b=profile_build")
package_id1 = c.created_package_id("mylib/1.0")

# Try to install with cppstd 14, it will find cppstd 17 as compatible
c.run("install --requires=mylib/1.0@ -s os=Windows -s arch=x86_64 -s build_type=Release "
"-s compiler=msvc "
"-s compiler.version=194 -s compiler.cppstd=14 "
"-s compiler.runtime=dynamic -pr:b=profile_build")
assert "mylib/1.0: Main binary package 'e340edd75790e7156c595edebd3d98b10a2e091e' missing."\
f"Using compatible package '{package_id1}'"


class TestErrorsCompatibility:
""" when the plugin fails, we want a clear message and a helpful trace
Expand Down
10 changes: 9 additions & 1 deletion conans/test/unittests/tools/cmake/test_cmaketoolchain.py
Expand Up @@ -194,7 +194,7 @@ def test_osx_deployment_target(conanfile_apple):
def conanfile_msvc():
c = ConanFile(None)
c.settings = Settings({"os": ["Windows"],
"compiler": {"msvc": {"version": ["193"], "cppstd": ["20"],
"compiler": {"msvc": {"version": ["193", "194"], "cppstd": ["20"],
"update": [None, 8, 9]}},
"build_type": ["Release"],
"arch": ["x86"]})
Expand Down Expand Up @@ -226,6 +226,14 @@ def test_toolset_update_version(conanfile_msvc):
assert 'set(CMAKE_GENERATOR_TOOLSET "v143,version=14.38" CACHE STRING "" FORCE)' in toolchain.content


def test_toolset_update_version_overflow(conanfile_msvc):
# https://github.com/conan-io/conan/issues/15583
conanfile_msvc.settings.compiler.version = "194"
conanfile_msvc.settings.compiler.update = "8"
toolchain = CMakeToolchain(conanfile_msvc)
assert 'set(CMAKE_GENERATOR_TOOLSET "v143,version=14.48" CACHE STRING "" FORCE)' in toolchain.content


def test_toolset_x64(conanfile_msvc):
# https://github.com/conan-io/conan/issues/11144
conanfile_msvc.conf.define("tools.cmake.cmaketoolchain:toolset_arch", "x64")
Expand Down
1 change: 1 addition & 0 deletions conans/test/unittests/tools/microsoft/test_msvs_toolset.py
Expand Up @@ -15,6 +15,7 @@ def test_invalid_compiler():


@pytest.mark.parametrize("compiler_version,expected_toolset", [
("194", "v143"),
("193", "v143"),
("192", "v142"),
("191", "v141"),
Expand Down