@@ -204,20 +204,21 @@ def generate_coverage(self, llvm_version="20"):
204204 if not llvm_profdata or not llvm_cov :
205205 raise Exception ("Could not find llvm-profdata or llvm-cov in PATH" )
206206
207- build_dir = self .work_dir .parent
207+ # Always use build directory for coverage
208+ build_dir = Path (self .__get_project_path ()) / "build"
208209 output_dir = build_dir / "coverage"
209210 output_dir .mkdir (exist_ok = True )
210211
211212 print (f"Looking for .profraw files in: { build_dir } " )
212213 print (f"Current working directory: { os .getcwd ()} " )
213214
214215 # Find all .profraw files
215- # First look in current directory (where tests are run)
216- cwd = Path . cwd ( )
217- profraw_files = list ( cwd . glob ( "*.profraw" ) )
218- # Also look in build directory if different
219- if cwd != build_dir :
220- profraw_files . extend ( list (build_dir .glob ("*.profraw" ) ))
216+ # First look in build directory
217+ profraw_files = list ( build_dir . glob ( "*.profraw" ) )
218+ # Also look in current directory (for backward compatibility )
219+ if not profraw_files :
220+ cwd = Path . cwd ()
221+ profraw_files = list (cwd .glob ("*.profraw" ))
221222 # Look recursively if still nothing found
222223 if not profraw_files :
223224 profraw_files = list (build_dir .glob ("**/*.profraw" ))
@@ -247,31 +248,39 @@ def generate_coverage(self, llvm_version="20"):
247248 objects = []
248249
249250 # Add all executables from bin directory
250- for f in self .work_dir .iterdir ():
251- if f .is_file () and os .access (f , os .X_OK ) and not f .suffix == ".txt" :
252- objects .append (str (f ))
251+ bin_dir = build_dir / "bin"
252+ if bin_dir .exists ():
253+ for f in bin_dir .iterdir ():
254+ if f .is_file () and os .access (f , os .X_OK ) and not f .suffix == ".txt" :
255+ objects .append (str (f ))
253256
254- # Add all static libraries from arch directory
257+ # Add all static libraries from arch directory (excluding third-party)
255258 arch_dir = build_dir / "arch"
256259 if arch_dir .exists ():
257260 for f in arch_dir .glob ("*.a" ):
258- objects .append (str (f ))
261+ # Skip third-party libraries
262+ if "gtest" not in f .name and "gmock" not in f .name and "tbb" not in f .name :
263+ objects .append (str (f ))
259264
260- # Add all shared libraries from lib directory
261- lib_dir = build_dir / "lib"
265+ # Add all shared libraries from lib directory (excluding third-party)
266+ lib_dir = build_dir / "lib"
262267 if lib_dir .exists ():
263268 for f in lib_dir .glob ("*.so" ):
264- objects .append (str (f ))
269+ # Skip third-party libraries
270+ if "tbb" not in f .name :
271+ objects .append (str (f ))
265272 for f in lib_dir .glob ("*.dylib" ):
266- objects .append (str (f ))
273+ # Skip third-party libraries
274+ if "tbb" not in f .name :
275+ objects .append (str (f ))
267276
268277 if not objects :
269278 raise Exception ("No executables or libraries found" )
270279
271280 print (f"Found { len (objects )} executables and libraries" )
272281
273282 # Get project root
274- project_root = build_dir . parent
283+ project_root = Path ( self . __get_project_path ())
275284
276285 # Generate LCOV report
277286 lcov_file = output_dir / "coverage.lcov"
@@ -306,27 +315,44 @@ def generate_coverage(self, llvm_version="20"):
306315
307316 # Generate HTML report
308317 html_dir = output_dir / "html"
309- cmd = (
310- [llvm_cov , "show" ]
311- + objects
312- + [
318+ html_dir .mkdir (exist_ok = True )
319+
320+ print ("Generating HTML coverage report..." )
321+
322+ # Generate HTML report with all objects at once
323+ # Use the first executable as the main binary and others as additional objects
324+ if objects :
325+ cmd = [
326+ llvm_cov , "show" ,
327+ objects [0 ], # Main binary
328+ ]
329+
330+ # Add other objects with -object flag
331+ for obj in objects [1 :]:
332+ cmd .extend (["-object" , obj ])
333+
334+ cmd .extend ([
313335 "--format=html" ,
314336 f"--output-dir={ html_dir } " ,
337+ "--show-line-counts-or-regions" ,
338+ "--show-instantiations" ,
315339 "--ignore-filename-regex=.*3rdparty/.*|/usr/.*|.*tasks/.*/tests/.*|"
316340 ".*modules/.*/tests/.*|.*tasks/common/runners/.*|"
317341 ".*modules/runners/.*|.*modules/util/include/perf_test_util.hpp|"
318342 ".*modules/util/include/func_test_util.hpp|.*modules/util/src/func_test_util.cpp" ,
319343 f"--instr-profile={ profdata_file } " ,
320- ]
321- )
344+ ])
322345
323- if self .verbose :
324- print ("Executing:" , " " .join (shlex .quote (part ) for part in cmd ))
325- result = subprocess .run (cmd )
326- if result .returncode != 0 :
327- raise Exception ("Failed to generate HTML coverage report" )
328-
329- print (f"Generated HTML report: { html_dir } /index.html" )
346+ if self .verbose :
347+ print ("Executing:" , " " .join (shlex .quote (part ) for part in cmd ))
348+
349+ result = subprocess .run (cmd , capture_output = True , text = True )
350+ if result .returncode != 0 :
351+ print (f"Warning: HTML generation returned non-zero: { result .stderr } " )
352+ else :
353+ print (f"Generated HTML report: { html_dir } /index.html" )
354+ else :
355+ print ("Error: No objects found for HTML generation" )
330356
331357 # Generate summary
332358 cmd = (
0 commit comments