Repository: conan-io/conan
Pull request #12796 (2022-12-28 10:27:17)

fix gcc 12 cppstd
Changelog: Fix: Deprecate ``c++2a`` for gcc 12, replace with ``c++20``
Docs: Omit

Close https://github.com/conan-io/conan/issues/12794



Patch:
diff --git a/conan/tools/_compilers.py b/conan/tools/_compilers.py
index a4f6f9da2..fb976a469 100644
--- a/conan/tools/_compilers.py
+++ b/conan/tools/_compilers.py
@@ -398,6 +398,10 @@ def _cppstd_gcc(gcc_version, cppstd):
         v23 = "c++2b"
         vgnu23 = "gnu++2b"
 
+    if Version(gcc_version) >= "12":
+        v20 = "c++20"
+        vgnu20 = "gnu++20"
+
     flag = {"98": v98, "gnu98": vgnu98,
             "11": v11, "gnu11": vgnu11,
             "14": v14, "gnu14": vgnu14,
diff --git a/conan/tools/cmake/cmakedeps/cmakedeps.py b/conan/tools/cmake/cmakedeps/cmakedeps.py
index 1a873729a..47647a715 100644
--- a/conan/tools/cmake/cmakedeps/cmakedeps.py
+++ b/conan/tools/cmake/cmakedeps/cmakedeps.py
@@ -17,6 +17,7 @@ class CMakeDeps(object):
 
     def __init__(self, conanfile):
         self._conanfile = conanfile
+        self._conanfile.must_use_new_helpers = True  # TODO: Remove 2.0
         self.arch = self._conanfile.settings.get_safe("arch")
         self.configuration = str(self._conanfile.settings.build_type)
 
diff --git a/conan/tools/cmake/toolchain/toolchain.py b/conan/tools/cmake/toolchain/toolchain.py
index cd54a9a87..2a0e181f8 100644
--- a/conan/tools/cmake/toolchain/toolchain.py
+++ b/conan/tools/cmake/toolchain/toolchain.py
@@ -118,6 +118,7 @@ class CMakeToolchain(object):
 
     def __init__(self, conanfile, generator=None):
         self._conanfile = conanfile
+        self._conanfile.must_use_new_helpers = True  # TODO: Remove 2.0
         self.generator = self._get_generator(generator)
         self.variables = Variables()
         # This doesn't support multi-config, they go to the same configPreset common in multi-config
diff --git a/conan/tools/microsoft/msbuilddeps.py b/conan/tools/microsoft/msbuilddeps.py
index 2053d38a0..8e0ab92dc 100644
--- a/conan/tools/microsoft/msbuilddeps.py
+++ b/conan/tools/microsoft/msbuilddeps.py
@@ -90,6 +90,7 @@ class MSBuildDeps(object):
 
     def __init__(self, conanfile):
         self._conanfile = conanfile
+        self._conanfile.must_use_new_helpers = True  # TODO: Remove 2.0
         self.configuration = conanfile.settings.build_type
         # TODO: This platform is not exactly the same as ``msbuild_arch``, because it differs
         # in x86=>Win32
diff --git a/conan/tools/microsoft/toolchain.py b/conan/tools/microsoft/toolchain.py
index 2b9c4686b..b98f6be45 100644
--- a/conan/tools/microsoft/toolchain.py
+++ b/conan/tools/microsoft/toolchain.py
@@ -45,6 +45,7 @@ class MSBuildToolchain(object):
 
     def __init__(self, conanfile):
         self._conanfile = conanfile
+        self._conanfile.must_use_new_helpers = True  # TODO: Remove 2.0
         self.preprocessor_definitions = {}
         self.compile_options = {}
         self.cxxflags = []
diff --git a/conans/client/build/cmake.py b/conans/client/build/cmake.py
index acaeffb3c..0006d8622 100644
--- a/conans/client/build/cmake.py
+++ b/conans/client/build/cmake.py
@@ -46,6 +46,9 @@ class CMake(object):
         :param cmake_program: Path to the custom cmake executable
         :param generator_platform: Generator platform name or none to autodetect (-A cmake option)
         """
+        if getattr(conanfile, "must_use_new_helpers", None):
+            raise ConanException("Using the wrong 'CMake' helper. To use CMakeDeps, CMakeToolchain "
+                                 "you should use 'from conan.tools.cmake import CMake'")
         self._append_vcvars = append_vcvars
         self._conanfile = conanfile
         self._settings = conanfile.settings
diff --git a/conans/client/build/msbuild.py b/conans/client/build/msbuild.py
index da88f0703..778b81a76 100644
--- a/conans/client/build/msbuild.py
+++ b/conans/client/build/msbuild.py
@@ -22,6 +22,10 @@ class MSBuild(object):
 
     def __init__(self, conanfile):
         if isinstance(conanfile, ConanFile):
+            if getattr(conanfile, "must_use_new_helpers", None):
+                raise ConanException(
+                    "Using the wrong 'MSBuild' helper. To use MSBuildDeps, MSBuildToolchain "
+                    "you should use 'from conan.tools.microsoft import MSBuild'")
             self._conanfile = conanfile
             self._settings = self._conanfile.settings
             self._output = self._conanfile.output


Test patch:
diff --git a/conans/test/functional/toolchains/cmake/cmakedeps/test_apple_frameworks.py b/conans/test/functional/toolchains/cmake/cmakedeps/test_apple_frameworks.py
index 33cb47b03..7dbc10bbf 100644
--- a/conans/test/functional/toolchains/cmake/cmakedeps/test_apple_frameworks.py
+++ b/conans/test/functional/toolchains/cmake/cmakedeps/test_apple_frameworks.py
@@ -348,7 +348,8 @@ def test_apple_own_framework_cmake_find_package_multi():
 @pytest.mark.skipif(platform.system() != "Darwin", reason="Only OSX")
 def test_component_uses_apple_framework():
     conanfile_py = textwrap.dedent("""
-from conans import ConanFile, CMake, tools
+from conans import ConanFile, tools
+from conan.tools.cmake import CMake
 
 
 class HelloConan(ConanFile):
@@ -406,7 +407,8 @@ install(TARGETS ${PROJECT_NAME}
         """)
     test_conanfile_py = textwrap.dedent("""
 import os
-from conans import ConanFile, CMake, tools
+from conans import ConanFile, tools
+from conan.tools.cmake import CMake
 
 class TestPackageConan(ConanFile):
     settings = "os", "compiler", "build_type", "arch"
diff --git a/conans/test/functional/toolchains/cmake/cmakedeps/test_cmakedeps_build_modules.py b/conans/test/functional/toolchains/cmake/cmakedeps/test_cmakedeps_build_modules.py
index 3566bfade..ae6a392b3 100644
--- a/conans/test/functional/toolchains/cmake/cmakedeps/test_cmakedeps_build_modules.py
+++ b/conans/test/functional/toolchains/cmake/cmakedeps/test_cmakedeps_build_modules.py
@@ -34,7 +34,8 @@ def test_build_modules_alias_target():
     client.run("create .")
 
     consumer = textwrap.dedent("""
-        from conans import ConanFile, CMake
+        from conans import ConanFile
+        from conan.tools.cmake import CMake
 
         class Conan(ConanFile):
             name = "consumer"
@@ -103,7 +104,8 @@ def test_build_modules_components_is_not_possible():
     client.run("create .")
 
     consumer = textwrap.dedent("""
-        from conans import ConanFile, CMake
+        from conans import ConanFile
+        from conan.tools.cmake import CMake
 
         class Conan(ConanFile):
             name = "consumer"
diff --git a/conans/test/integration/toolchains/test_not_mix_legacy.py b/conans/test/integration/toolchains/test_not_mix_legacy.py
new file mode 100644
index 000000000..c0fb38fec
--- /dev/null
+++ b/conans/test/integration/toolchains/test_not_mix_legacy.py
@@ -0,0 +1,79 @@
+import textwrap
+
+from conans.test.utils.tools import TestClient
+
+
+def test_not_mix_legacy_cmake():
+    c = TestClient()
+    conanfile = textwrap.dedent("""
+        from conan import ConanFile
+        from conans import CMake
+        class Pkg(ConanFile):
+            name = "pkg"
+            version = "0.1"
+            settings = "build_type"
+            generators = "CMakeDeps"
+            def build(self):
+                CMake(self)
+            """)
+    c.save({"conanfile.py": conanfile})
+    c.run("create .", assert_error=True)
+    assert "Using the wrong 'CMake' helper" in c.out
+
+
+def test_not_mix_legacy_cmake_generate():
+    c = TestClient()
+    conanfile = textwrap.dedent("""
+        from conan import ConanFile
+        from conans import CMake
+        from conan.tools.cmake import CMakeDeps
+        class Pkg(ConanFile):
+            name = "pkg"
+            version = "0.1"
+            settings = "build_type"
+            def generate(self):
+                CMakeDeps(self)
+            def build(self):
+                CMake(self)
+            """)
+    c.save({"conanfile.py": conanfile})
+    c.run("create .", assert_error=True)
+    assert "Using the wrong 'CMake' helper" in c.out
+
+
+def test_not_mix_legacy_msbuild():
+    c = TestClient()
+    conanfile = textwrap.dedent("""
+        from conan import ConanFile
+        from conans import MSBuild
+        class Pkg(ConanFile):
+            name = "pkg"
+            version = "0.1"
+            settings = "build_type", "arch"
+            generators = "MSBuildDeps"
+            def build(self):
+                MSBuild(self)
+            """)
+    c.save({"conanfile.py": conanfile})
+    c.run("create .", assert_error=True)
+    assert "Using the wrong 'MSBuild' helper" in c.out
+
+
+def test_not_mix_legacy_msbuild_generate():
+    c = TestClient()
+    conanfile = textwrap.dedent("""
+        from conan import ConanFile
+        from conans import MSBuild
+        from conan.tools.microsoft import MSBuildDeps
+        class Pkg(ConanFile):
+            name = "pkg"
+            version = "0.1"
+            settings = "build_type", "arch"
+            def generate(self):
+                MSBuildDeps(self)
+            def build(self):
+                MSBuild(self)
+            """)
+    c.save({"conanfile.py": conanfile})
+    c.run("create .", assert_error=True)
+    assert "Using the wrong 'MSBuild' helper" in c.out
diff --git a/conans/test/unittests/tools/gnu/autotoolschain_test.py b/conans/test/unittests/tools/gnu/autotoolschain_test.py
index 8141dc8c8..93b7d31ec 100644
--- a/conans/test/unittests/tools/gnu/autotoolschain_test.py
+++ b/conans/test/unittests/tools/gnu/autotoolschain_test.py
@@ -25,6 +25,23 @@ def test_get_gnu_triplet_for_cross_building():
     assert autotoolschain._build == "i686-solaris"
 
 
+def test_get_toolchain_cppstd():
+    settings = MockSettings({"build_type": "Release",
+                             "compiler": "gcc",
+                             "compiler.version": "10",
+                             "compiler.cppstd": "20",
+                             "os": "Linux",
+                             "arch": "x86_64"})
+    conanfile = ConanFileMock()
+    conanfile.settings = settings
+    conanfile.settings_build = settings
+    autotoolschain = AutotoolsToolchain(conanfile)
+    assert autotoolschain.cppstd == "-std=c++2a"
+    settings.values["compiler.version"] = "12"
+    autotoolschain = AutotoolsToolchain(conanfile)
+    assert autotoolschain.cppstd == "-std=c++20"
+
+
 @pytest.mark.parametrize("runtime, runtime_type, expected",
                          [("static", "Debug", "MTd"),
                           ("static", "Release", "MT"),