Repository: conan-io/conan
Pull request #16732 (2024-07-26 09:11:56)

ISSUE-16731: "msvc" compatibility with "Visual Studio" is broken

In case cppstd is set in the Conan profile for "Visual Studio", it is badly migrated to "msvc". This change solves: https://github.com/conan-io/conan/issues/16731

Changelog: Bugfix: Fixed msvc / Visual Studio package cmpatibility in case cppstd is used in profiles
Docs: Omit

- [x] Refer to the issue that supports this Pull Request.
- [x] If the issue has missing info, explain the purpose/use case/pain/need that covers this Pull Request.
- [x] I've read the [Contributing guide](https://github.com/conan-io/conan/blob/develop2/.github/CONTRIBUTING.md).
- [x] I've followed the PEP8 style guides for Python code.
- [x] I've opened another PR in the Conan docs repo to the ``develop`` branch, documenting this one.


CLAassistant: [![CLA assistant check](https://cla-assistant.io/pull/badge/not_signed)](https://cla-assistant.io/conan-io/conan?pullRequest=16732) <br/>Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our [Contributor License Agreement](https://cla-assistant.io/conan-io/conan?pullRequest=16732) before we can accept your contribution.<br/><sub>You have signed the CLA already but the status is still pending? Let us [recheck](https://cla-assistant.io/check/conan-io/conan?pullRequest=16732) it.</sub>
memsharded: The CI is still failing with:
```
E           ------------------------ Command failed (unexpectedly): ------------------------
E           install pkg/0.1@ -pr=profile
E           ----------------------------------- Output: ------------------------------------
E           
E           WARN: **************************************************
E           WARN: *** Conan 1 is legacy and on a deprecation path **
E           WARN: *********** Please upgrade to Conan 2 ************
E           WARN: **************************************************
E           Configuration:
E           [settings]
E           arch=x86_64
E           build_type=Release
E           compiler=msvc
E           compiler.cppstd=14
E           compiler.runtime=dynamic
E           compiler.runtime_type=Release
E           compiler.version=191
E           os=Windows
E           [options]
E           [build_requires]
E           [env]
E           
E           Installing package: pkg/0.1
E           Requirements
E               pkg/0.1 from local cache - Cache
E           Packages
E               pkg/0.1:16041e00ee7792b16701a7a92918452f6b5a519b - Missing
E           
E           Cross-build from 'Linux:x86_64' to 'Windows:x86_64'
E           Installing (downloading, building) binaries...
E           ERROR: Missing binary: pkg/0.1:16041e00ee7792b16701a7a92918452f6b5a519b
E           
E           pkg/0.1: WARN: Can't find a 'pkg/0.1' package for the specified settings, options and dependencies:
E           - Settings: arch=x86_64, build_type=Release, compiler=msvc, compiler.cppstd=14, compiler.runtime=dynamic, compiler.runtime_type=Release, compiler.version=191, os=Windows
E           - Options: 
E           - Dependencies: 
E           - Requirements: 
E           - Package ID: 16041e00ee7792b16701a7a92918452f6b5a519b
E           
E           ERROR: Missing prebuilt package for 'pkg/0.1'
E           Use 'conan search pkg/0.1@ --table=table.html -r=remote' and open the table.html file to see available packages
E           Or try to build locally from sources with '--build=pkg'
E           
E           More Info at 'https://docs.conan.io/en/latest/faq/troubleshooting.html#error-missing-prebuilt-package'
```

in ``test_msvc_visual_incompatible`` test
harsszegi: @memsharded I'm completely lost on this :(

If I do:

conan create . pkg/0.1@ -s os=Windows -s compiler="Visual Studio" -s compiler.version=15 -s compiler.cppstd=**14** -s compiler.runtime=MD -s build_type=Release -s arch=x86_64

then a 

conan search pkg/0.1@ --table=table.html

cppstd is not set

however if I do a :

conan create . pkg/0.1@ -s os=Windows -s compiler="Visual Studio" -s compiler.version=15 -s compiler.cppstd=**17** -s compiler.runtime=MD -s build_type=Release -s arch=x86_64

then a

conan search pkg/0.1@ --table=table.html

cppstd becomes set.

I'm more then happy to change the test to this dark voodoo magic that is being done here, but could you explain what the heck is going on here and more important why?
Thanks,


memsharded: This is due to some automatic behavior in Conan 1: https://docs.conan.io/1/reference/conanfile/methods.html#self-info-default-std-matching-self-info-default-std-non-matching

It is basically making ``cppstd=None`` when it matches the default ``cppstd`` for the current compiler version. It was a way to allow the introduction of ``cppstd`` without breaking.
harsszegi: Ok, added this default-handling thingie to the conversion function (e.g. it erases cppstd if it matches the 'default')
harsszegi: > Looks good, thanks for your contribution.
> 
> Could you please check and sign the CLA, so it can be merged? Thanks!

The sad part is that I have signed it 3x, but still says pending :(
memsharded: > The sad part is that I have signed it 3x, but still says pending :( (my Github CLA page also lists conan-io there)

This might happen when the commits are signed with a different email address than the one used by Github, can you please check that?
harsszegi: > > The sad part is that I have signed it 3x, but still says pending :( (my Github CLA page also lists conan-io there)
> 
> This might happen when the commits are signed with a different email address than the one used by Github, can you please check that?

F@ck, thanks, I pushed with my corporate Github account instead of my private one :(

Patch:
diff --git a/conans/model/info.py b/conans/model/info.py
index 049dd8a94..0cee4a20f 100644
--- a/conans/model/info.py
+++ b/conans/model/info.py
@@ -591,8 +591,14 @@ class ConanInfo(object):
         version = compatible.settings.compiler.version
         runtime = compatible.settings.compiler.runtime
         runtime_type = compatible.settings.compiler.runtime_type
+        cppstd = compatible.settings.compiler.get_safe("cppstd")
 
         compatible.settings.compiler = "Visual Studio"
+
+        if cppstd is not None:
+            # Restore cppstd, as switching to 'Visual Studio' clears it
+            compatible.settings.compiler.cppstd = cppstd
+
         from conan.tools.microsoft.visual import msvc_version_to_vs_ide_version
         visual_version = msvc_version_to_vs_ide_version(version)
         compatible.settings.compiler.version = visual_version
@@ -600,6 +606,13 @@ class ConanInfo(object):
         if runtime_type == "Debug":
             runtime = "{}d".format(runtime)
         compatible.settings.compiler.runtime = runtime
+
+        # Some 'final adjustment'
+        # In case the cppstd is the 'default' for the compiler, it will actually be erased
+        default_cppstd = cppstd_default(compatible.settings)
+        if default_cppstd is not None and compatible.settings.compiler.get_safe("cppstd") == default_cppstd:
+            del compatible.settings.compiler.cppstd
+
         return compatible
 
     def apple_clang_compatible(self):


Test patch:
diff --git a/conans/test/integration/package_id/compatible_test.py b/conans/test/integration/package_id/compatible_test.py
index 305dba427..725b72373 100644
--- a/conans/test/integration/package_id/compatible_test.py
+++ b/conans/test/integration/package_id/compatible_test.py
@@ -604,25 +604,45 @@ class CompatibleIDsTest(unittest.TestCase):
 def test_msvc_visual_incompatible():
     conanfile = GenConanfile().with_settings("os", "compiler", "build_type", "arch")
     client = TestClient()
-    profile = textwrap.dedent("""
+    # First we need to make sure to test that a 'non-default' cppstd is actually preserved
+    # and we can match that
+    profile1 = textwrap.dedent("""
         [settings]
         os=Windows
         compiler=msvc
         compiler.version=191
         compiler.runtime=dynamic
-        compiler.cppstd=14
+        compiler.cppstd=17
         build_type=Release
         arch=x86_64
         """)
     client.save({"conanfile.py": conanfile,
-                 "profile": profile})
+                 "profile1": profile1})
     client.run('create . pkg/0.1@ -s os=Windows -s compiler="Visual Studio" -s compiler.version=15 '
+               '-s compiler.cppstd=17 -s compiler.runtime=MD -s build_type=Release -s arch=x86_64')
+    client.run("install pkg/0.1@ -pr=profile1")
+    assert "Using compatible package" in client.out
+
+    # Now we need to test the 'default' cppstd case, in this case, this will be lost in the package id
+    profile2 = textwrap.dedent("""
+        [settings]
+        os=Windows
+        compiler=msvc
+        compiler.version=191
+        compiler.runtime=dynamic
+        compiler.cppstd=14
+        build_type=Release
+        arch=x86_64
+        """)
+    client.save({"profile2": profile2})
+    client.run('create . pkg/0.2@ -s os=Windows -s compiler="Visual Studio" -s compiler.version=15 '
                '-s compiler.runtime=MD -s build_type=Release -s arch=x86_64')
-    client.run("install pkg/0.1@ -pr=profile")
+    client.run("install pkg/0.2@ -pr=profile2")
     assert "Using compatible package" in client.out
+
     new_config = "core.package_id:msvc_visual_incompatible=1"
     save(client.cache.new_config_path, new_config)
-    client.run("install pkg/0.1@ -pr=profile", assert_error=True)
+    client.run("install pkg/0.1@ -pr=profile1", assert_error=True)
     assert "ERROR: Missing prebuilt package for 'pkg/0.1'" in client.out