From 5019d085fcf1db21417c4bba4da6aef51829222b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Rinc=C3=B3n=20Blanco?= Date: Wed, 8 Mar 2023 18:38:57 +0100 Subject: [PATCH] Nicer error in the compatibility plugin with custom compilers (#13328) * Nicer error when the compiler is not included in the supported_cppstd compilers * Return an empty list, but warn the user about missing compatibility, which is the best of both worlds * Add cppstd_compat test * Fix GenConanfile import * Fixup imports --- conan/tools/build/cppstd.py | 2 +- conans/client/graph/compatibility.py | 4 + .../extensions/test_cppstd_compat.py | 85 +++++++++++++++++++ 3 files changed, 90 insertions(+), 1 deletion(-) create mode 100644 conans/test/integration/extensions/test_cppstd_compat.py diff --git a/conan/tools/build/cppstd.py b/conan/tools/build/cppstd.py index 95aacec5e51..486de81da99 100644 --- a/conan/tools/build/cppstd.py +++ b/conan/tools/build/cppstd.py @@ -94,7 +94,7 @@ def default_cppstd(conanfile, compiler=None, compiler_version=None): def supported_cppstd(conanfile, compiler=None, compiler_version=None): """ - Get the a list of supported ``compiler.cppstd`` for the "conanfile.settings.compiler" and + Get a list of supported ``compiler.cppstd`` for the "conanfile.settings.compiler" and "conanfile.settings.compiler_version" or for the parameters "compiler" and "compiler_version" if specified. diff --git a/conans/client/graph/compatibility.py b/conans/client/graph/compatibility.py index 4f132048b85..2982fc1c279 100644 --- a/conans/client/graph/compatibility.py +++ b/conans/client/graph/compatibility.py @@ -24,6 +24,7 @@ def compatibility(conanfile): # This file was generated by Conan. Remove this comment if you edit this file or Conan # will destroy your changes. from conan.tools.build import supported_cppstd +from conan.errors import ConanException def cppstd_compat(conanfile): @@ -36,6 +37,9 @@ def cppstd_compat(conanfile): 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: diff --git a/conans/test/integration/extensions/test_cppstd_compat.py b/conans/test/integration/extensions/test_cppstd_compat.py new file mode 100644 index 00000000000..53f9f5d5743 --- /dev/null +++ b/conans/test/integration/extensions/test_cppstd_compat.py @@ -0,0 +1,85 @@ +import textwrap + +from conans.test.assets.genconanfile import GenConanfile +from conans.test.utils.tools import TestClient + + +def test_compatible_cppstd(): + c = TestClient() + conanfile = textwrap.dedent(""" + from conan import ConanFile + + class Pkg(ConanFile): + name = "pkg" + version = "0.1" + settings = "os", "compiler" + + def package_info(self): + self.output.info("PackageInfo!: Cppstd version: %s!" + % self.settings.compiler.cppstd) + """) + profile = textwrap.dedent(""" + [settings] + os = Linux + compiler=gcc + compiler.version=12 + compiler.libcxx=libstdc++ + """) + c.save({"conanfile.py": conanfile, + "myprofile": profile}) + # Create package with cppstd 17 + c.run("create . -pr=myprofile -s compiler.cppstd=17") + package_id = "95dcfeb51c04968b4ee960ee393cf2c1ebcf7782" + assert f"pkg/0.1: Package '{package_id}' created" in c.out + + # package can be used with a profile gcc cppstd20 falling back to 17 + c.save({"conanfile.py": GenConanfile().with_require("pkg/0.1")}) + c.run("install . -pr=myprofile -s compiler.cppstd=20") + assert f"Using compatible package '{package_id}'" + assert "pkg/0.1: PackageInfo!: Cppstd version: 17!" in c.out + c.assert_listed_binary({"pkg/0.1": (f"{package_id}", "Cache")}) + assert "pkg/0.1: Already installed!" in c.out + + +def test_compatible_cppstd_missing_compiler(): + c = TestClient() + settings_user = textwrap.dedent(""" + compiler: + mycompiler: + version: ["12"] + libcxx: ["libstdc++"] + cppstd: [15, 17, 20] + """) + conanfile = textwrap.dedent(""" + from conan import ConanFile + + class Pkg(ConanFile): + name = "pkg" + version = "0.1" + settings = "os", "compiler" + + def package_info(self): + self.output.info("PackageInfo!: Cppstd version: %s!" + % self.settings.compiler.cppstd) + """) + profile = textwrap.dedent(""" + [settings] + os = Linux + compiler=mycompiler + compiler.version=12 + compiler.libcxx=libstdc++ + """) + c.save({"conanfile.py": conanfile, + "myprofile": profile}) + c.save_home({"settings_user.yml": settings_user}) + # Create package with cppstd 17 + c.run("create . -pr=myprofile -s compiler.cppstd=17") + package_id = "51a90090adb1cbd330a64b4c3b3b32af809af4f9" + assert f"pkg/0.1: Package '{package_id}' created" in c.out + + # package can't be used with cppstd 20 and fallback to 17, because mycompiler is not known + # to the default cppstd_compat function. Ensure that it does not break and warns the user + c.save({"conanfile.py": GenConanfile().with_require("pkg/0.1")}) + c.run("install . -pr=myprofile -s compiler.cppstd=20", assert_error=True) + assert "Missing binary: pkg/0.1:b4b07859713551e8aac612f8080888c58b4711ae" in c.out + assert 'pkg/0.1: WARN: No cppstd compatibility defined for compiler "mycompiler"' in c.out