Repository: conan-io/conan
Pull request #16509 (2024-06-20 15:14:01)

fix Conan 1 lockfile options package_id
Changelog: Bugfix: Fix corruption of ``package_id`` computation with dependencies options when using lockfiles
Docs: Omit
Closes: https://github.com/conan-io/conan/issues/16534


jasal82: I reported the issue directly to Diego. If you want I can write an issue with symptoms and investigation so that it is documented.
jasal82: Related bug report is here https://github.com/conan-io/conan/issues/16534

Patch:
diff --git a/conan/tools/build/cross_building.py b/conan/tools/build/cross_building.py
index 9e86fae95..bb17d53f5 100644
--- a/conan/tools/build/cross_building.py
+++ b/conan/tools/build/cross_building.py
@@ -1,5 +1,8 @@
 
 def cross_building(conanfile=None, skip_x64_x86=False):
+    cross_build = conanfile.conf.get("tools.build.cross_building:cross_build", check_type=bool)
+    if cross_build is not None:
+        return cross_build
 
     build_os, build_arch, host_os, host_arch = get_cross_building_settings(conanfile)
 
diff --git a/conans/client/command.py b/conans/client/command.py
index 76d1eddd8..10fc9b864 100644
--- a/conans/client/command.py
+++ b/conans/client/command.py
@@ -571,6 +571,7 @@ class Command(object):
                                                      require_overrides=args.require_override)
 
             self._warn_revisions()
+            self._warn_conan_version()
 
         except ConanException as exc:
             info = exc.info
@@ -2192,8 +2193,11 @@ class Command(object):
             self._out.writeln("*"*width, front=Color.BRIGHT_RED)
 
     def _warn_conan_version(self):
-        self._out.warning("*** Conan 1 is legacy and on a deprecation path ***")
-        self._out.warning("*** Please upgrade to Conan 2 ***")
+        self._out.writeln("")
+        self._out.warning("*"*50)
+        self._out.warning("*** Conan 1 is legacy and on a deprecation path **")
+        self._out.warning("*********** Please upgrade to Conan 2 ************")
+        self._out.warning("*" * 50)
 
     def _warn_revisions(self):
         if self._conan.app and not self._conan.app.config.revisions_enabled:
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):
diff --git a/conans/model/options.py b/conans/model/options.py
index 8c2702380..2ea09e073 100644
--- a/conans/model/options.py
+++ b/conans/model/options.py
@@ -260,7 +260,8 @@ class OptionsValues(object):
             return False
         # It is possible that the entry in the dict is not defined
         for key, pkg_values in self._reqs_options.items():
-            other_values = other[key]
+            # We do a get so we don't artificially inject new keys in "other"
+            other_values = other._reqs_options.get(key, PackageOptionValues())
             if not pkg_values == other_values:
                 return False
         return True


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