ctexplain: first functional check-in
https://github.com/bazelbuild/bazel/pull/11511 set up basic project structure. This PR adds minimum working functionality.
Specifically, you can run it with a build command and it reports basic stats on the build's graph.
Example:
```
$ bazel-bin/tools/ctexplain/ctexplain -b "//testapp:foo"
Collecting configured targets for //testapp:foo... done in 0.62 s.
Configurations: 3
Targets: 79
Configured targets: 92 (+16.5% vs. targets)
Targets with multiple configs: 13
```
Notes:
* Changed import structure to prefer module imports over function, class imports (style guide recommendation)
* Set up structure for injecting arbitrary analyses. Each analysis consumes the build's set of configured targets and can output whatever it wants.
* Implemented one basic analysis
* Structured code to make it easy to fork output formatters (e.g. for machine-readable output). But tried not to add speculative inheritance / boilerplate too soon
Context: [Measuring Configuration Overhead](https://docs.google.com/document/d/10ZxO2wZdKJATnYBqAm22xT1k5r4Vp6QX96TkqSUIhs0/edit).
Work towards #10613
Closes #11829.
PiperOrigin-RevId: 328325094
diff --git a/tools/ctexplain/types.py b/tools/ctexplain/types.py
index 2ac480f..c47ab9f 100644
--- a/tools/ctexplain/types.py
+++ b/tools/ctexplain/types.py
@@ -26,16 +26,20 @@
@dataclass(frozen=True)
class Configuration():
"""Stores a build configuration as a collection of fragments and options."""
- # BuildConfiguration.Fragments in this configuration, as base names without
- # packages. For example: ["PlatformConfiguration", ...].
- fragments: Tuple[str, ...]
+ # Mapping of each BuildConfiguration.Fragment in this configuration to the
+ # FragmentOptions it requires.
+ #
+ # All names are qualified up to the base file name, without package prefixes.
+ # For example, foo.bar.BazConfiguration appears as "BazConfiguration".
+ # foo.bar.BazConfiguration$Options appears as "BazeConfiguration$Options".
+ fragments: Mapping[str, Tuple[str, ...]]
# Mapping of FragmentOptions to option key/value pairs. For example:
# {"CoreOptions": {"action_env": "[]", "cpu": "x86", ...}, ...}.
#
# Option values are stored as strings of whatever "bazel config" outputs.
#
# Note that Fragment and FragmentOptions aren't the same thing.
- options: [Mapping[str, Mapping[str, str]]]
+ options: Mapping[str, Mapping[str, str]]
@dataclass(frozen=True)
@@ -49,7 +53,7 @@
config_hash: str
# Fragments required by this configured target and its transitive
# dependencies. Stored as base names without packages. For example:
- # "PlatformOptions".
+ # "PlatformOptions" or "FooConfiguration$Options".
transitive_fragments: Tuple[str, ...]