| # Copyright 2020 The Bazel Authors. All rights reserved. |
| # |
| # Licensed under the Apache License, Version 2.0 (the "License"); |
| # you may not use this file except in compliance with the License. |
| # You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| # See the License for the specific language governing permissions and |
| # limitations under the License. |
| """Analysis that summarizes basic graph info.""" |
| from typing import Tuple |
| |
| # Do not edit this line. Copybara replaces it with PY2 migration helper. |
| from dataclasses import dataclass |
| |
| from tools.ctexplain.types import ConfiguredTarget |
| # Do not edit this line. Copybara replaces it with PY2 migration helper..third_party.bazel.tools.ctexplain.util as util |
| |
| |
| @dataclass(frozen=True) |
| class _Summary(): |
| """Analysis result.""" |
| # Number of configurations in the build's configured target graph. |
| configurations: int |
| # Number of unique target labels. |
| targets: int |
| # Number of configured targets. |
| configured_targets: int |
| # Number of targets that produce multiple configured targets. This is more |
| # subtle than computing configured_targets - targets. For example, if |
| # targets=2 and configured_targets=4, that could mean both targets are |
| # configured twice. Or it could mean the first target is configured 3 times. |
| repeated_targets: int |
| |
| |
| def analyze(cts: Tuple[ConfiguredTarget, ...]) -> _Summary: |
| """Runs the analysis on a build's configured targets.""" |
| configurations = set() |
| targets = set() |
| label_count = {} |
| for ct in cts: |
| configurations.add(ct.config_hash) |
| targets.add(ct.label) |
| label_count[ct.label] = label_count.setdefault(ct.label, 0) + 1 |
| configured_targets = len(cts) |
| repeated_targets = sum([1 for count in label_count.values() if count > 1]) |
| |
| return _Summary( |
| len(configurations), len(targets), configured_targets, repeated_targets) |
| |
| |
| def report(result: _Summary) -> None: |
| """Reports analysis results to the user. |
| |
| We intentionally make this its own function to make it easy to support other |
| output formats (like machine-readable) if we ever want to do that. |
| |
| Args: |
| result: the analysis result |
| """ |
| ct_surplus = util.percent_diff(result.targets, result.configured_targets) |
| print(f""" |
| Configurations: {result.configurations} |
| Targets: {result.targets} |
| Configured targets: {result.configured_targets} ({ct_surplus} vs. targets) |
| Targets with multiple configs: {result.repeated_targets} |
| """) |