Repository: conan-io/conan
Pull request #18019 (2025-03-25 14:41:35)

Add configuration information for each package being built
Changelog: Feature: Add information about the configuration each package is building for
Changelog: Feature: Add `-vv` information for the configuration of each dependency in the graph
Docs: Omit




Patch:
diff --git a/conan/api/output.py b/conan/api/output.py
index 6989abc07..cf291ec98 100644
--- a/conan/api/output.py
+++ b/conan/api/output.py
@@ -207,9 +207,9 @@ class ConanOutput:
             self._write_message(msg, fg=Color.BLUE)
         return self
 
-    def debug(self, msg):
+    def debug(self, msg, fg=Color.MAGENTA, bg=None):
         if self._conan_output_level <= LEVEL_DEBUG:
-            self._write_message(msg, fg=Color.MAGENTA)
+            self._write_message(msg, fg=fg, bg=bg)
         return self
 
     def verbose(self, msg, fg=None, bg=None):
diff --git a/conan/cli/printers/graph.py b/conan/cli/printers/graph.py
index e0bd79e16..84c671f4a 100644
--- a/conan/cli/printers/graph.py
+++ b/conan/cli/printers/graph.py
@@ -1,4 +1,4 @@
-from conan.api.output import ConanOutput, Color, LEVEL_VERBOSE
+from conan.api.output import ConanOutput, Color, LEVEL_VERBOSE, LEVEL_DEBUG
 from conans.client.graph.graph import BINARY_INVALID, BINARY_MISSING, RECIPE_CONSUMER, \
     RECIPE_VIRTUAL, CONTEXT_BUILD, BINARY_SKIP, \
     BINARY_PLATFORM, BINARY_BUILD
@@ -115,13 +115,14 @@ def print_graph_packages(graph):
     for node in graph.nodes:
         if node.recipe in (RECIPE_CONSUMER, RECIPE_VIRTUAL):
             continue
+        node_info = node.conanfile.info
         if node.context == CONTEXT_BUILD:
-            existing = build_requires.setdefault(node.pref, [node.binary, node.binary_remote])
+            existing = build_requires.setdefault(node.pref, [node.binary, node.binary_remote, node_info])
         else:
             if node.test:
-                existing = test_requires.setdefault(node.pref, [node.binary, node.binary_remote])
+                existing = test_requires.setdefault(node.pref, [node.binary, node.binary_remote, node_info])
             else:
-                existing = requires.setdefault(node.pref, [node.binary, node.binary_remote])
+                existing = requires.setdefault(node.pref, [node.binary, node.binary_remote, node_info])
         # TO avoid showing as "skip" something that is used in other node of the graph
         if existing[0] == BINARY_SKIP:
             existing[0] = node.binary
@@ -130,7 +131,7 @@ def print_graph_packages(graph):
         if not reqs_to_print:
             return
         output.info(title, Color.BRIGHT_YELLOW)
-        for pref, (status, remote) in sorted(reqs_to_print.items(), key=repr):
+        for pref, (status, remote, info) in sorted(reqs_to_print.items(), key=repr):
             name = pref.repr_notime() if status != BINARY_PLATFORM else str(pref.ref)
             msg = f"{tab}{name} - "
             if status == BINARY_SKIP:
@@ -148,6 +149,10 @@ def print_graph_packages(graph):
                 if remote:
                     msg += f" ({remote.name})"
                 output.info(msg, Color.BRIGHT_CYAN)
+            if output.level_allowed(LEVEL_DEBUG):
+                compact_dumps = info.summarize_compact()
+                for line in compact_dumps:
+                    output.debug(f"{tab}{tab}{line}", Color.BRIGHT_GREEN)
 
     _format_requires("Requirements", requires)
     _format_requires("Test requirements", test_requires)
diff --git a/conan/internal/model/info.py b/conan/internal/model/info.py
index 2319ba777..231b52551 100644
--- a/conan/internal/model/info.py
+++ b/conan/internal/model/info.py
@@ -432,6 +432,20 @@ class ConanInfo:
         result.append("")  # Append endline so file ends with LF
         return '\n'.join(result)
 
+    def summarize_compact(self):
+        result = []
+        serialized = self.serialize()
+
+        for key, values in serialized.items():
+            if isinstance(values, dict):
+                result.append(f"{key}: " + " ".join(f"{k}={v}" for k, v in values.items()))
+            elif isinstance(values, type([])):
+                result.append(f"{key}: {' '.join(values)}")
+            elif values:
+                result.append(f"{key}: {' '.join(values)}")
+
+        return result
+
     def dump_diff(self, compatible):
         self_dump = self.dumps()
         compatible_dump = compatible.dumps()
diff --git a/conans/client/installer.py b/conans/client/installer.py
index d661ac53c..51197962e 100644
--- a/conans/client/installer.py
+++ b/conans/client/installer.py
@@ -2,7 +2,7 @@ import os
 import shutil
 from multiprocessing.pool import ThreadPool
 
-from conan.api.output import ConanOutput
+from conan.api.output import ConanOutput, Color
 from conan.internal.methods import run_build_method, run_package_method
 from conan.internal.api.install.generators import write_generators
 from conans.client.graph.graph import BINARY_BUILD, BINARY_CACHE, BINARY_DOWNLOAD, BINARY_EDITABLE, \
@@ -309,6 +309,9 @@ class BinaryInstaller:
             ConanOutput(scope=str(pref.ref))\
                 .highlight("Building from source")\
                 .info(f"Package {pref}")
+            compact_dumps = package.nodes[0].conanfile.info.summarize_compact()
+            for line in compact_dumps:
+                ConanOutput(scope=str(pref.ref)).info(line, fg=Color.BRIGHT_GREEN)
             package_layout = self._cache.create_build_pkg_layout(pref)
             self._handle_node_build(package, package_layout)
             # Just in case it was recomputed


Test patch:
diff --git a/test/integration/command/create_test.py b/test/integration/command/create_test.py
index 81d75486d..798230c7b 100644
--- a/test/integration/command/create_test.py
+++ b/test/integration/command/create_test.py
@@ -160,7 +160,7 @@ def test_create_package_requires():
     client.save({"conanfile.py": conanfile,
                  "test_package/conanfile.py": test_conanfile})
 
-    client.run("create . --name=pkg --version=0.1 --user=lasote --channel=testing")
+    client.run("create . --name=pkg --version=0.1 --user=lasote --channel=testing -vv")
 
     assert "pkg/0.1@lasote/testing (test package): build() " \
            "Requires: other/1.0@user/channel" in client.out
@@ -170,6 +170,10 @@ def test_create_package_requires():
     assert "pkg/0.1@lasote/testing (test package): build() cpp_info dep: dep" in client.out
     assert "pkg/0.1@lasote/testing (test package): build() cpp_info dep: pkg" in client.out
 
+    # Check that the additional info shows up when creating pkg
+    # Graph info, package creation, and test package graph info
+    assert client.out.count("requires: dep/0.1@user/channel") == 3
+
 
 def test_package_folder_build_error():
     """