From 029388d26f908109294289f35ad78733aa3552bf Mon Sep 17 00:00:00 2001 From: Tibor Harsszegi Date: Mon, 2 Dec 2024 12:35:36 +0100 Subject: [PATCH] Issue with 'automatic' compatible packages and custom package ids (#16772) * Issue with 'automatic' compatible packages and custom package ids In case the recipe uses its own package_id() and compatible packages are generated automatically (e.g. Visual Studio vs msvc), then the compatible packages will use wrong 'base' info set for the compatible package id generation. In case the recipe's own package_id() erases a few options / settings, the compatible packages will not know about it, as those are generated prior the recipe's package_id() is being called. The change makes sure that first the recipe's package_id() is called, then the compatible packages are generated, so that they pick up the updated info set. * test that crashes * Making sure msvc_compatible handling partially set compiler settings In case a custom package_id() erased some of the compiler settings for 'msvc', a 'Visual Studio' equivalent should be created that also doesn't have the (possibly) erased elements. --------- Co-authored-by: memsharded --- conans/client/graph/graph_binaries.py | 17 ++++++++----- conans/model/info.py | 15 +++++++----- .../integration/package_id/compatible_test.py | 24 +++++++++++++++++++ 3 files changed, 44 insertions(+), 12 deletions(-) diff --git a/conans/client/graph/graph_binaries.py b/conans/client/graph/graph_binaries.py index 8f5a925e33d..fa5a9542f20 100644 --- a/conans/client/graph/graph_binaries.py +++ b/conans/client/graph/graph_binaries.py @@ -394,6 +394,17 @@ def _compute_package_id(self, node, default_package_id_mode, default_python_requ default_python_requires_id_mode= default_python_requires_id_mode) conanfile.original_info = conanfile.info.clone() + + # Call the package id before any compatibility, as the other way around + # compatibile packages will be cloned from a wrong info set. How? + # If the package id erases a few options / settings and it is done AFTER + # compatibility, the compatible packages will still look for packages + # containing those - later erased - options, settings + with conanfile_exception_formatter(str(conanfile), "package_id"): + with conan_v2_property(conanfile, 'cpp_info', + "'self.cpp_info' access in package_id() method is deprecated"): + conanfile.package_id() + if not self._cache.new_config["core.package_id:msvc_visual_incompatible"]: msvc_compatible = conanfile.info.msvc_compatible() if msvc_compatible: @@ -403,12 +414,6 @@ def _compute_package_id(self, node, default_package_id_mode, default_python_requ if apple_clang_compatible: conanfile.compatible_packages.append(apple_clang_compatible) - # Once we are done, call package_id() to narrow and change possible values - with conanfile_exception_formatter(str(conanfile), "package_id"): - with conan_v2_property(conanfile, 'cpp_info', - "'self.cpp_info' access in package_id() method is deprecated"): - conanfile.package_id() - if hasattr(conanfile, "validate") and callable(conanfile.validate): with conanfile_exception_formatter(str(conanfile), "validate"): try: diff --git a/conans/model/info.py b/conans/model/info.py index 0cee4a20ff4..798964708b8 100644 --- a/conans/model/info.py +++ b/conans/model/info.py @@ -600,12 +600,15 @@ def msvc_compatible(self): 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 - runtime = "MT" if runtime == "static" else "MD" - if runtime_type == "Debug": - runtime = "{}d".format(runtime) - compatible.settings.compiler.runtime = runtime + if version is not None: + visual_version = msvc_version_to_vs_ide_version(version) + compatible.settings.compiler.version = visual_version + + if runtime is not None and runtime_type is not None: + runtime = "MT" if runtime == "static" else "MD" + 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 diff --git a/conans/test/integration/package_id/compatible_test.py b/conans/test/integration/package_id/compatible_test.py index 725b723739c..51f361b62d9 100644 --- a/conans/test/integration/package_id/compatible_test.py +++ b/conans/test/integration/package_id/compatible_test.py @@ -771,3 +771,27 @@ def package_info(self): client.run("install . -o pkg/*:optimized=3") assert "pkg/0.1@user/stable: Already installed!" in client.out assert f"pkg/0.1@user/stable:{package_id} - Cache" in client.out + + +def test_crash(): + client = TestClient() + conanfile = textwrap.dedent(""" + from conans import ConanFile + + class Pkg(ConanFile): + settings = "os", "compiler" + def package_id(self): + del self.info.settings.compiler.version + """) + profile = textwrap.dedent(""" + [settings] + os = Windows + compiler=msvc + compiler.version=192 + compiler.runtime=dynamic + compiler.cppstd=14 + build_type=Release + """) + client.save({"conanfile.py": conanfile, + "myprofile": profile}) + client.run("create . pkg/0.1@ -pr=myprofile")