From caf137e10ab495a34be4d68d530566badbba0a84 Mon Sep 17 00:00:00 2001 From: Uilian Ries Date: Wed, 21 Feb 2024 16:49:36 +0100 Subject: [PATCH] [feature] Export cppstd_flag as public tool (#15710) * Use ConanFile for cppstd_flag Signed-off-by: Uilian Ries * expose cppstd_flag Signed-off-by: Uilian Ries * lazy import to break cyclic import Signed-off-by: Uilian Ries * centralize to_cppstd_flag Signed-off-by: Uilian Ries * Update method description Signed-off-by: Uilian Ries * improve method documentation Signed-off-by: Uilian Ries * Revert "centralize to_cppstd_flag" This reverts commit a98b28996cdbcff1ecedcc2b188a0c1adcd3bb31. --------- Signed-off-by: Uilian Ries --- conan/tools/apple/xcodetoolchain.py | 2 +- conan/tools/build/__init__.py | 1 + conan/tools/build/flags.py | 23 +++++++++++++++---- conan/tools/gnu/autotoolstoolchain.py | 2 +- conan/tools/google/toolchain.py | 2 +- conan/tools/microsoft/nmaketoolchain.py | 2 +- .../client/build/cpp_std_flags_test.py | 9 ++++---- .../unittests/tools/intel/test_intel_cc.py | 5 ++-- 8 files changed, 31 insertions(+), 15 deletions(-) diff --git a/conan/tools/apple/xcodetoolchain.py b/conan/tools/apple/xcodetoolchain.py index 65d9e70e409..5af04498a64 100644 --- a/conan/tools/apple/xcodetoolchain.py +++ b/conan/tools/apple/xcodetoolchain.py @@ -57,7 +57,7 @@ def generate(self): @property def _cppstd(self): from conan.tools.build.flags import cppstd_flag - cppstd = cppstd_flag(self._conanfile.settings) + cppstd = cppstd_flag(self._conanfile) if cppstd.startswith("-std="): return cppstd[5:] return cppstd diff --git a/conan/tools/build/__init__.py b/conan/tools/build/__init__.py index 7e611492906..9c77a3f4d5a 100644 --- a/conan/tools/build/__init__.py +++ b/conan/tools/build/__init__.py @@ -3,6 +3,7 @@ import sys from shlex import quote +from conan.tools.build.flags import cppstd_flag from conan.tools.build.cppstd import check_max_cppstd, check_min_cppstd, \ valid_max_cppstd, valid_min_cppstd, default_cppstd, supported_cppstd from conan.tools.build.cpu import build_jobs diff --git a/conan/tools/build/flags.py b/conan/tools/build/flags.py index e17dc34a46f..7dbb1e06b2f 100644 --- a/conan/tools/build/flags.py +++ b/conan/tools/build/flags.py @@ -1,4 +1,3 @@ -from conan.tools.apple.apple import _to_apple_arch from conans.model.version import Version @@ -7,6 +6,7 @@ def architecture_flag(settings): returns flags specific to the target architecture and compiler Used by CMakeToolchain and AutotoolsToolchain """ + from conan.tools.apple.apple import _to_apple_arch compiler = settings.get_safe("compiler") arch = settings.get_safe("arch") the_os = settings.get_safe("os") @@ -165,10 +165,23 @@ def build_type_flags(settings): return [] -def cppstd_flag(settings): - compiler = settings.get_safe("compiler") - compiler_version = settings.get_safe("compiler.version") - cppstd = settings.get_safe("compiler.cppstd") +def cppstd_flag(conanfile) -> str: + """ + Returns flags specific to the C++ standard based on the ``conanfile.settings.compiler``, + ``conanfile.settings.compiler.version`` and ``conanfile.settings.compiler.cppstd``. + + It also considers when using GNU extension in ``settings.compiler.cppstd``, reflecting it in the + compiler flag. Currently, it supports GCC, Clang, AppleClang, MSVC, Intel, MCST-LCC. + + In case there is no ``settings.compiler`` or ``settings.cppstd`` in the profile, the result will + be an **empty string**. + + :param conanfile: The current recipe object. Always use ``self``. + :return: ``str`` with the standard C++ flag used by the compiler. e.g. "-std=c++11", "/std:c++latest" + """ + 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: return "" diff --git a/conan/tools/gnu/autotoolstoolchain.py b/conan/tools/gnu/autotoolstoolchain.py index e5b48cbf0c0..71ec02001be 100644 --- a/conan/tools/gnu/autotoolstoolchain.py +++ b/conan/tools/gnu/autotoolstoolchain.py @@ -44,7 +44,7 @@ def __init__(self, conanfile, namespace=None, prefix="/"): self.build_type_flags = build_type_flags(self._conanfile.settings) self.build_type_link_flags = build_type_link_flags(self._conanfile.settings) - self.cppstd = cppstd_flag(self._conanfile.settings) + self.cppstd = cppstd_flag(self._conanfile) self.arch_flag = architecture_flag(self._conanfile.settings) self.libcxx, self.gcc_cxx11_abi = libcxx_flags(self._conanfile) self.fpic = self._conanfile.options.get_safe("fPIC") diff --git a/conan/tools/google/toolchain.py b/conan/tools/google/toolchain.py index 112ce14a70c..17a7470ce51 100644 --- a/conan/tools/google/toolchain.py +++ b/conan/tools/google/toolchain.py @@ -76,7 +76,7 @@ def __init__(self, conanfile): #: String used to add --dynamic_mode=["fully"|"off"]. Depends on self.options.shared value. self.dynamic_mode = "fully" if shared else "off" #: String used to add --cppstd=[FLAG]. Depends on your settings. - self.cppstd = cppstd_flag(self._conanfile.settings) + self.cppstd = cppstd_flag(self._conanfile) #: List of flags used to add --copt=flag1 ... --copt=flagN self.copt = [] #: List of flags used to add --conlyopt=flag1 ... --conlyopt=flagN diff --git a/conan/tools/microsoft/nmaketoolchain.py b/conan/tools/microsoft/nmaketoolchain.py index 848a6934e2f..b46ba9cc300 100644 --- a/conan/tools/microsoft/nmaketoolchain.py +++ b/conan/tools/microsoft/nmaketoolchain.py @@ -54,7 +54,7 @@ def _cl(self): cflags.extend(self.extra_cflags) cxxflags = [] - cppstd = cppstd_flag(self._conanfile.settings) + cppstd = cppstd_flag(self._conanfile) if cppstd: cxxflags.append(cppstd) cxxflags.extend(self._conanfile.conf.get("tools.build:cxxflags", default=[], check_type=list)) diff --git a/conans/test/unittests/client/build/cpp_std_flags_test.py b/conans/test/unittests/client/build/cpp_std_flags_test.py index d03020afdd2..f9b6cc373bf 100644 --- a/conans/test/unittests/client/build/cpp_std_flags_test.py +++ b/conans/test/unittests/client/build/cpp_std_flags_test.py @@ -1,16 +1,17 @@ import unittest from conan.internal.api.detect_api import default_cppstd -from conan.tools.build.flags import cppstd_flag +from conan.tools.build import cppstd_flag from conans.model.version import Version -from conans.test.utils.mocks import MockSettings +from conans.test.utils.mocks import MockSettings, ConanFileMock def _make_cppstd_flag(compiler, compiler_version, cppstd=None): - settings = MockSettings({"compiler": compiler, + conanfile = ConanFileMock() + conanfile.settings = MockSettings({"compiler": compiler, "compiler.version": compiler_version, "compiler.cppstd": cppstd}) - return cppstd_flag(settings) + return cppstd_flag(conanfile) def _make_cppstd_default(compiler, compiler_version): diff --git a/conans/test/unittests/tools/intel/test_intel_cc.py b/conans/test/unittests/tools/intel/test_intel_cc.py index 556d7f4098e..bd38aee2290 100644 --- a/conans/test/unittests/tools/intel/test_intel_cc.py +++ b/conans/test/unittests/tools/intel/test_intel_cc.py @@ -46,7 +46,8 @@ def test_architecture_flag_if_intel_cc(os_, arch, expected): ("gnu23", "gnu++2b"), ]) def test_cppstd_flag_if_intel_cc(cppstd, flag): - settings = MockSettings({ + conanfile = ConanFileMock() + conanfile.settings = MockSettings({ "compiler": "intel-cc", "compiler.version": "2021.3", "compiler.mode": "classic", @@ -54,7 +55,7 @@ def test_cppstd_flag_if_intel_cc(cppstd, flag): "os": "Linux", "compiler.cppstd": cppstd }) - assert cppstd_flag(settings) == "-std=%s" % flag + assert cppstd_flag(conanfile) == "-std=%s" % flag @pytest.mark.parametrize("mode", ["icx", "dpcpp"])