Skip to content

Commit af02240

Browse files
yraparticlaude
authored andcommitted
[rocm-libraries] ROCm/rocm-libraries#6912 (commit c705da2)
[CK] Reduce per-file logging in cmake_dependency_analyzer (#6912) ## Motivation Current progress_callback function generates large volume of prints which creates noise in seeing actual CI failure logs. Only emit a progress line at the completion of each stage to avoid massive logs from the per-source-file extracting_dependencies callback. ## Technical Details Update the `progress` function to print only at the completion of each stage. https://github.com/ROCm/rocm-libraries/pull/6912/changes#diff-15971b83c7dfefb48fd788507a923017d93bbd9487ed6aeb414ad2c5e00be934R720 ## Test Plan to be tested in CI ## Test Result to be tested in CI ## Submission Checklist - [x ] Look over the contributing guidelines at https://github.com/ROCm/ROCm/blob/develop/CONTRIBUTING.md#pull-requests. Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent f3d8a12 commit af02240

1 file changed

Lines changed: 31 additions & 21 deletions

File tree

script/dependency-parser/src/cmake_dependency_analyzer.py

Lines changed: 31 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,10 @@
2222
import re
2323
import shlex
2424
import subprocess
25-
import sys
2625
import tempfile
2726
from collections import defaultdict
2827
from concurrent.futures import ProcessPoolExecutor, as_completed
29-
from pathlib import Path
30-
from typing import Dict, List, Optional, Set, Tuple
28+
from typing import Dict, List, Optional, Set
3129

3230

3331
class CompileCommandsParser:
@@ -55,7 +53,9 @@ def parse(self, extensions: Optional[List[str]] = None) -> List[Dict]:
5553
json.JSONDecodeError: If file contains invalid JSON
5654
"""
5755
if not os.path.exists(self.compile_commands_path):
58-
raise FileNotFoundError(f"compile_commands.json not found: {self.compile_commands_path}")
56+
raise FileNotFoundError(
57+
f"compile_commands.json not found: {self.compile_commands_path}"
58+
)
5959

6060
with open(self.compile_commands_path, "r") as f:
6161
commands = json.load(f)
@@ -92,7 +92,9 @@ def __init__(self, parallel_workers: int = 1, timeout: int = 30):
9292
self.timeout = timeout
9393
self._temp_dir = None
9494

95-
def convert_to_dependency_command(self, compile_command: str, deps_output_file: str) -> List[str]:
95+
def convert_to_dependency_command(
96+
self, compile_command: str, deps_output_file: str
97+
) -> List[str]:
9698
"""Convert a compile command to a dependency extraction command.
9799
98100
Replaces -c with -MM and removes -o output specification.
@@ -158,7 +160,7 @@ def parse_makefile_deps(self, deps_content: str) -> List[str]:
158160
return []
159161

160162
# Everything after the colon is dependencies
161-
deps_part = content[colon_pos + 1:]
163+
deps_part = content[colon_pos + 1 :]
162164

163165
# Split on whitespace and filter empty strings
164166
deps = [d.strip() for d in deps_part.split() if d.strip()]
@@ -180,7 +182,9 @@ def _get_deps_file(self, source_file: str) -> str:
180182
basename = os.path.basename(source_file)
181183
return os.path.join(self._temp_dir, f"{basename}.d")
182184

183-
def extract(self, directory: str, compile_command: str, source_file: str) -> List[str]:
185+
def extract(
186+
self, directory: str, compile_command: str, source_file: str
187+
) -> List[str]:
184188
"""Extract dependencies for a single source file.
185189
186190
Args:
@@ -203,7 +207,7 @@ def extract(self, directory: str, compile_command: str, source_file: str) -> Lis
203207
cwd=directory,
204208
capture_output=True,
205209
text=True,
206-
errors='replace',
210+
errors="replace",
207211
timeout=self.timeout,
208212
)
209213

@@ -212,7 +216,7 @@ def extract(self, directory: str, compile_command: str, source_file: str) -> Lis
212216

213217
# Parse the generated .d file
214218
if os.path.exists(deps_file):
215-
with open(deps_file, "r", errors='replace') as f:
219+
with open(deps_file, "r", errors="replace") as f:
216220
deps_content = f.read()
217221
return self.parse_makefile_deps(deps_content)
218222

@@ -335,7 +339,9 @@ def parse_object_to_source(self) -> Dict[str, str]:
335339

336340
# Pattern to match object compilation rules
337341
# Example: build test/test.cpp.o: CXX_COMPILER__target /src/test.cpp
338-
obj_pattern = re.compile(r"^build\s+([^:]+\.(?:cpp|cc|cu|hip)\.o):\s+\S+\s+(\S+)")
342+
obj_pattern = re.compile(
343+
r"^build\s+([^:]+\.(?:cpp|cc|cu|hip)\.o):\s+\S+\s+(\S+)"
344+
)
339345

340346
with open(self.ninja_file_path, "r") as f:
341347
for line in f:
@@ -371,7 +377,7 @@ def normalize_path(self, path: str) -> str:
371377
Normalized relative path
372378
"""
373379
if self.workspace_root and path.startswith(self.workspace_root):
374-
return path[len(self.workspace_root):]
380+
return path[len(self.workspace_root) :]
375381
return path
376382

377383
def is_project_file(self, file_path: str) -> bool:
@@ -567,7 +573,9 @@ def analyze(self, progress_callback=None):
567573
"""
568574
# Validate required paths
569575
if self.compile_commands_path is None:
570-
raise ValueError("compile_commands_path is required for analysis but was None")
576+
raise ValueError(
577+
"compile_commands_path is required for analysis but was None"
578+
)
571579
if self.ninja_path is None:
572580
raise ValueError("ninja_path is required for analysis but was None")
573581

@@ -588,7 +596,9 @@ def dep_progress(current, total):
588596
if progress_callback:
589597
progress_callback("extracting_dependencies", current, total)
590598

591-
source_to_deps = extractor.extract_batch(commands, progress_callback=dep_progress)
599+
source_to_deps = extractor.extract_batch(
600+
commands, progress_callback=dep_progress
601+
)
592602

593603
# Phase 3: Parse ninja target mappings
594604
if progress_callback:
@@ -707,10 +717,8 @@ def main():
707717
args = parser.parse_args()
708718

709719
def progress(phase, current, total):
710-
if not args.quiet:
711-
print(f"[{phase}] {current}/{total}", end="\r")
712-
if current == total:
713-
print()
720+
if not args.quiet and current == total:
721+
print(f"[{phase}] {current}/{total}")
714722

715723
analyzer = CMakeDependencyAnalyzer(
716724
compile_commands_path=args.compile_commands,
@@ -721,12 +729,12 @@ def progress(phase, current, total):
721729

722730
# Check if cache needs regeneration
723731
if not args.force and not analyzer.should_regenerate_cache(args.output):
724-
print(f"Cache is valid, skipping analysis. Use --force to regenerate.")
732+
print("Cache is valid, skipping analysis. Use --force to regenerate.")
725733
print(f"Using cached results from {args.output}")
726734
return
727735

728736
if not args.force and os.path.exists(args.output):
729-
print(f"Cache invalid or outdated, regenerating dependencies...")
737+
print("Cache invalid or outdated, regenerating dependencies...")
730738

731739
print(f"Analyzing dependencies from {args.compile_commands}...")
732740
analyzer.analyze(progress_callback=progress)
@@ -735,10 +743,12 @@ def progress(phase, current, total):
735743
analyzer.export_to_json(args.output)
736744

737745
stats = analyzer.calculate_statistics()
738-
print(f"\nResults:")
746+
print("\nResults:")
739747
print(f" Total files: {stats['total_files']}")
740748
print(f" Total executables: {stats['total_executables']}")
741-
print(f" Files with multiple executables: {stats['files_with_multiple_executables']}")
749+
print(
750+
f" Files with multiple executables: {stats['files_with_multiple_executables']}"
751+
)
742752

743753

744754
if __name__ == "__main__":

0 commit comments

Comments
 (0)