diff --git a/conan/internal/api/detect_api.py b/conan/internal/api/detect_api.py index 5f2eabebdf6..e90894b297f 100644 --- a/conan/internal/api/detect_api.py +++ b/conan/internal/api/detect_api.py @@ -384,9 +384,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() @@ -409,7 +414,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) diff --git a/conan/tools/microsoft/visual.py b/conan/tools/microsoft/visual.py index 8c929e97926..1632e3b9585 100644 --- a/conan/tools/microsoft/visual.py +++ b/conan/tools/microsoft/visual.py @@ -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)] @@ -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)) @@ -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) diff --git a/conans/client/conf/__init__.py b/conans/client/conf/__init__.py index 15836051df9..129ceb76f42 100644 --- a/conans/client/conf/__init__.py +++ b/conans/client/conf/__init__.py @@ -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] runtime: [static, dynamic] runtime_type: [Debug, Release] diff --git a/conans/client/conf/detect_vs.py b/conans/client/conf/detect_vs.py index f0c48c7491c..4db783a8768 100644 --- a/conans/client/conf/detect_vs.py +++ b/conans/client/conf/detect_vs.py @@ -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: diff --git a/conans/client/graph/compatibility.py b/conans/client/graph/compatibility.py index c72c4377c0a..967ddc90efe 100644 --- a/conans/client/graph/compatibility.py +++ b/conans/client/graph/compatibility.py @@ -30,26 +30,43 @@ 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}]) + + 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 + + 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 """ diff --git a/conans/test/integration/package_id/test_cache_compatibles.py b/conans/test/integration/package_id/test_cache_compatibles.py index f98dd7fe628..702b11e6d90 100644 --- a/conans/test/integration/package_id/test_cache_compatibles.py +++ b/conans/test/integration/package_id/test_cache_compatibles.py @@ -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 diff --git a/conans/test/unittests/tools/cmake/test_cmaketoolchain.py b/conans/test/unittests/tools/cmake/test_cmaketoolchain.py index b08dc13b720..8bba79509f8 100644 --- a/conans/test/unittests/tools/cmake/test_cmaketoolchain.py +++ b/conans/test/unittests/tools/cmake/test_cmaketoolchain.py @@ -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"]}) @@ -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") diff --git a/conans/test/unittests/tools/microsoft/test_msvs_toolset.py b/conans/test/unittests/tools/microsoft/test_msvs_toolset.py index b5f8b1a5d41..14574127e26 100644 --- a/conans/test/unittests/tools/microsoft/test_msvs_toolset.py +++ b/conans/test/unittests/tools/microsoft/test_msvs_toolset.py @@ -15,6 +15,7 @@ def test_invalid_compiler(): @pytest.mark.parametrize("compiler_version,expected_toolset", [ + ("194", "v143"), ("193", "v143"), ("192", "v142"), ("191", "v141"),