Repository: conan-io/conan
Pull request #17831 (2025-02-21 18:19:20)

new CMakeConfigDeps
Changelog: Make available in conanfiles the new incubating ``CMakeConfigDeps`` generator, still under the incubating "conf" feature flag.
Docs: https://github.com/conan-io/docs/pull/XXXX





Patch:
diff --git a/conan/internal/api/install/generators.py b/conan/internal/api/install/generators.py
index 61c0d7b85..fe553891f 100644
--- a/conan/internal/api/install/generators.py
+++ b/conan/internal/api/install/generators.py
@@ -11,6 +11,7 @@ from conans.util.files import save, mkdir, chdir
 
 _generators = {"CMakeToolchain": "conan.tools.cmake",
                "CMakeDeps": "conan.tools.cmake",
+               "CMakeConfigDeps": "conan.tools.cmake",
                "MesonToolchain": "conan.tools.meson",
                "MSBuildDeps": "conan.tools.microsoft",
                "MSBuildToolchain": "conan.tools.microsoft",
diff --git a/conan/tools/cmake/__init__.py b/conan/tools/cmake/__init__.py
index e57f14a65..d6a1c431f 100644
--- a/conan/tools/cmake/__init__.py
+++ b/conan/tools/cmake/__init__.py
@@ -1,14 +1,31 @@
+from conan.errors import ConanException
 from conan.tools.cmake.toolchain.toolchain import CMakeToolchain
 from conan.tools.cmake.cmake import CMake
 from conan.tools.cmake.layout import cmake_layout
 
 
 def CMakeDeps(conanfile):  # noqa
-    if conanfile.conf.get("tools.cmake.cmakedeps:new", choices=["will_break_next"]):
+    if conanfile.conf.get("tools.cmake.cmakedeps:new",
+                          choices=["will_break_next", "recipe_will_break"]) == "will_break_next":
         from conan.tools.cmake.cmakedeps2.cmakedeps import CMakeDeps2
-        conanfile.output.warning("Using the new CMakeDeps generator, behind the "
+        conanfile.output.warning("Using the new CMakeConfigDeps generator, behind the "
                                  "'tools.cmake.cmakedeps:new' gate conf. This conf will change "
                                  "next release, breaking, so use it only for testing and dev")
         return CMakeDeps2(conanfile)
     from conan.tools.cmake.cmakedeps.cmakedeps import CMakeDeps as _CMakeDeps
     return _CMakeDeps(conanfile)
+
+
+
+def CMakeConfigDeps(conanfile):  # noqa
+    if conanfile.conf.get("tools.cmake.cmakedeps:new",
+                          choices=["will_break_next", "recipe_will_break"]):
+        from conan.tools.cmake.cmakedeps2.cmakedeps import CMakeDeps2
+        conanfile.output.warning("Using the new CMakeConfigDeps generator, behind the "
+                                 "'tools.cmake.cmakedeps:new' gate conf. This conf will change "
+                                 "next release, breaking, so use it only for testing and dev")
+        return CMakeDeps2(conanfile)
+    else:
+        raise ConanException("CMakeConfigDeps is being used in conanfile, but the conf "
+                             "'tools.cmake.cmakedeps:new' is not enabled. This is an incubating"
+                             "feature, please define it to enable CMakeConfigDeps usage")


Test patch:
diff --git a/test/integration/toolchains/cmake/cmakedeps2/__init__.py b/test/integration/toolchains/cmake/cmakedeps2/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/test/integration/toolchains/cmake/cmakedeps2/test_cmakedeps.py b/test/integration/toolchains/cmake/cmakedeps2/test_cmakedeps.py
index 4b6001749..83420d6d6 100644
--- a/test/integration/toolchains/cmake/cmakedeps2/test_cmakedeps.py
+++ b/test/integration/toolchains/cmake/cmakedeps2/test_cmakedeps.py
@@ -1,6 +1,7 @@
 import re
 import textwrap
 
+from conan.test.assets.genconanfile import GenConanfile
 from conan.test.utils.tools import TestClient
 
 new_value = "will_break_next"
@@ -90,3 +91,64 @@ def test_cmakedeps_transitive_paths():
     assert not re.search(r"list\(PREPEND CMAKE_PROGRAM_PATH /bina\"", cmake_paths)
     assert re.search(r"list\(PREPEND CMAKE_LIBRARY_PATH \".*/libb.*/p/libb\" \".*/liba.*/p/liba\"\)", cmake_paths)
     assert re.search(r"list\(PREPEND CMAKE_INCLUDE_PATH \".*/libb.*/p/includeb\" \".*/liba.*/p/includea\"\)", cmake_paths)
+
+
+def test_cmakeconfigdeps_recipe():
+    c = TestClient()
+    conanfile = textwrap.dedent("""
+        from conan.tools.cmake import CMakeConfigDeps
+        from conan import ConanFile
+        class TestConan(ConanFile):
+            settings = "build_type"
+            requires = "dep/0.1"
+            def generate(self):
+                deps = CMakeConfigDeps(self)
+                deps.generate()
+    """)
+    c.save({"dep/conanfile.py": GenConanfile("dep", "0.1"),
+            "app/conanfile.py": conanfile})
+    c.run("create dep")
+    c.run("install app", assert_error=True)
+    assert "CMakeConfigDeps is being used in conanfile, but the conf " \
+           "'tools.cmake.cmakedeps:new' is not enabled" in c.out
+    c.run("install app -c tools.cmake.cmakedeps:new=will_break_next")
+    # will not fail, still warn
+    assert "WARN: Using the new CMakeConfigDeps generator" in c.out
+    # The only-recipe also not fails
+    c.run("install app -c tools.cmake.cmakedeps:new=recipe_will_break")
+    # will not fail
+    assert "WARN: Using the new CMakeConfigDeps generator" in c.out
+
+    # attribute generator
+    conanfile = textwrap.dedent("""
+        from conan.tools.cmake import CMakeConfigDeps
+        from conan import ConanFile
+        class TestConan(ConanFile):
+            settings = "build_type"
+            requires = "dep/0.1"
+            generators = "CMakeConfigDeps"
+        """)
+    c.save({"app/conanfile.py": conanfile}, clean_first=True)
+    c.run("install app", assert_error=True)
+    assert "CMakeConfigDeps is being used in conanfile, but the conf " \
+           "'tools.cmake.cmakedeps:new' is not enabled" in c.out
+    c.run("install app -c tools.cmake.cmakedeps:new=will_break_next")
+    assert "WARN: Using the new CMakeConfigDeps generator" in c.out
+    c.run("install app -c tools.cmake.cmakedeps:new=recipe_will_break")
+    assert "WARN: Using the new CMakeConfigDeps generator" in c.out
+
+    # conanfile.txt
+    conanfile = textwrap.dedent("""
+        [requires]
+        dep/0.1
+        [generators]
+        CMakeConfigDeps
+        """)
+    c.save({"app/conanfile.txt": conanfile}, clean_first=True)
+    c.run("install app", assert_error=True)
+    assert "CMakeConfigDeps is being used in conanfile, but the conf " \
+           "'tools.cmake.cmakedeps:new' is not enabled" in c.out
+    c.run("install app -c tools.cmake.cmakedeps:new=will_break_next")
+    assert "WARN: Using the new CMakeConfigDeps generator" in c.out
+    c.run("install app -c tools.cmake.cmakedeps:new=recipe_will_break")
+    assert "WARN: Using the new CMakeConfigDeps generator" in c.out