@@ -49,25 +49,36 @@ def check_elf_modules(elf_path: Path, env, module_lib_builders) -> set[str]:
4949 secho (f"WARNING: nm failed ({ e } ); skipping per-module validation" , fg = "yellow" , err = True )
5050 return {Path (b .build_dir ).name for b in module_lib_builders } # conservative pass
5151
52- # Build a filtered set of lines that have a nonzero address.
52+ # Collect source file Paths from placed symbols ( nonzero address only) .
5353 # nm --defined-only still includes debugging symbols (type 'N') such as the
5454 # per-CU markers GCC emits in .debug_info (e.g. "usermod_example_cpp_6734d48d").
5555 # These live at address 0x00000000 in their debug section — not in any load
5656 # segment — so filtering them out leaves only genuinely placed symbols.
57- placed_lines = [
58- line for line in nm_output .splitlines ()
59- if (parts := line .split (None , 1 )) and parts [0 ].lstrip ('0' )
60- ]
61- placed_output = "\n " .join (placed_lines )
57+ # nm -l appends a tab-separated "file:lineno" location to each symbol line.
58+ placed_paths : set [Path ] = set ()
59+ for line in nm_output .splitlines ():
60+ parts = line .split (None , 1 )
61+ if not (parts and parts [0 ].lstrip ('0' )):
62+ continue # zero address — skip debug-section marker
63+ if '\t ' in line :
64+ loc = line .rsplit ('\t ' , 1 )[1 ]
65+ # Strip trailing :lineno (e.g. "/path/to/foo.cpp:42" → "/path/to/foo.cpp")
66+ file_part = loc .rsplit (':' , 1 )[0 ]
67+ placed_paths .add (Path (file_part ))
6268
6369 found = set ()
6470 for builder in module_lib_builders :
6571 # builder.src_dir is the library source directory (used by is_wled_module() too)
66- src_dir = str (builder .src_dir ).rstrip ("/\\ " )
67- # Guard against prefix collisions (e.g. /path/to/mod vs /path/to/mod-extra)
68- # by requiring a path separator immediately after the directory name.
69- if re .search (re .escape (src_dir ) + r'[/\\]' , placed_output ):
70- found .add (Path (builder .build_dir ).name )
72+ src_dir = Path (str (builder .src_dir ))
73+ # Path.is_relative_to() / relative_to() handles OS-specific separators
74+ # correctly without any regex, avoiding Windows path escaping issues.
75+ for p in placed_paths :
76+ try :
77+ p .relative_to (src_dir )
78+ found .add (Path (builder .build_dir ).name )
79+ break
80+ except ValueError :
81+ pass
7182 return found
7283
7384
0 commit comments