@@ -348,7 +348,10 @@ def classify_build_file(fname: str) -> str | None:
348348 return None
349349
350350
351- # System/stdlib function prefixes (skip for dependency tracking)
351+ # System/stdlib function prefixes (skip for dependency tracking). UNCHANGED from
352+ # the original: callees under these prefixes are NOT recorded as normal callees,
353+ # so the local dep-resolution / call-edge path behaves EXACTLY as before whether
354+ # or not cross-repo linking is enabled. (OFF behavior is byte-identical.)
352355SYSTEM_PREFIXES = (
353356 'std::' , 'boost::' , '__builtin' , '__' , 'operator' , 'printf' , 'fprintf' ,
354357 'sprintf' , 'snprintf' , 'scanf' , 'malloc' , 'calloc' , 'realloc' , 'free' ,
@@ -357,19 +360,30 @@ def classify_build_file(fname: str) -> str | None:
357360 'assert' , 'pthread_' , 'EXPECT_' , 'ASSERT_' , 'TEST' ,
358361)
359362
363+ # Base-library NAMESPACE prefixes that ARE cross-linkable (present in the global
364+ # symbol store built by scripts/crossrepo/build_global_symbol_index.py). A callee
365+ # under one of these is filtered OUT of the normal `callees` list (above) but is
366+ # captured SEPARATELY in FunctionDef.baselib_callees so the cross-repo linker can
367+ # resolve it WITHOUT changing the normal callee/call-edge behavior. We do NOT
368+ # include libc-style bare names here (memcpy/strlen/...) because those are not in
369+ # the A1 selection and would only add noise; only the namespaced base libs.
370+ CROSSLINKABLE_NS_PREFIXES = ('std::' , 'boost::' )
371+
360372
361373class FunctionDef :
362374 """A function definition with its source location and call references."""
363375 __slots__ = ['name' , 'qualified_name' , 'file' , 'line' , 'end_line' , 'text' ,
364376 'callees' , 'referenced_types' , 'dep_level' , 'is_definition' ,
365- 'ast_depth' , 'sibling_index' , 'ast_node_type' ]
377+ 'ast_depth' , 'sibling_index' , 'ast_node_type' ,
378+ 'baselib_callees' ]
366379
367380 def __init__ (self , name : str , qualified_name : str , file : str , line : int ,
368381 text : str , callees : list , is_definition : bool = True ,
369382 end_line : int = 0 , ast_depth : list [int ] | None = None ,
370383 sibling_index : list [int ] | None = None ,
371384 ast_node_type : list [int ] | None = None ,
372- referenced_types : list | None = None ):
385+ referenced_types : list | None = None ,
386+ baselib_callees : list | None = None ):
373387 self .name = name
374388 self .qualified_name = qualified_name
375389 self .file = file
@@ -382,6 +396,10 @@ def __init__(self, name: str, qualified_name: str, file: str, line: int,
382396 # SAME libclang parse as callees so it round-trips IPC and feeds the
383397 # offline type_refs/type_edges builders. Mirrors `callees`.
384398 self .referenced_types = list (referenced_types or [])
399+ # Cross-linkable base-lib callees (std::/boost::) dropped from `callees`
400+ # by the normal system-prefix filter, kept SEPARATELY for the optional
401+ # cross-repo linker. Empty/ignored unless --global-symbol-index is given.
402+ self .baselib_callees = list (baselib_callees or [])
385403 self .dep_level = 0
386404 self .is_definition = is_definition
387405 self .ast_depth = list (ast_depth or [])
@@ -399,6 +417,7 @@ def to_dict(self) -> dict:
399417 'sibling_index' : self .sibling_index ,
400418 'ast_node_type' : self .ast_node_type ,
401419 'referenced_types' : self .referenced_types ,
420+ 'baselib_callees' : self .baselib_callees ,
402421 }
403422
404423 @classmethod
@@ -537,6 +556,19 @@ def is_system_function(name: str | None) -> bool:
537556 return any (name .startswith (p ) for p in SYSTEM_PREFIXES )
538557
539558
559+ def is_crosslinkable_baselib (name : str | None ) -> bool :
560+ """True if ``name`` is a cross-linkable base-lib symbol (std::/boost::).
561+
562+ Such a callee is filtered out of the normal ``callees`` list (it matches
563+ SYSTEM_PREFIXES) but is captured separately so the cross-repo linker can
564+ resolve it against the global symbol index. This does NOT affect normal
565+ callee/call-edge behavior.
566+ """
567+ if not isinstance (name , str ) or not name :
568+ return False
569+ return any (name .startswith (p ) for p in CROSSLINKABLE_NS_PREFIXES )
570+
571+
540572_DROP_CLANG_ARG_PREFIXES = (
541573 "-fsanitize=" ,
542574 "-fno-sanitize=" ,
@@ -813,23 +845,39 @@ def _cursor_text_and_metadata(
813845 )
814846
815847
816- def extract_callees (cursor : Cursor ) -> list [str ]:
817- """Extract all function call references from a cursor's children."""
818- callees = set ()
848+ def extract_callees (cursor : Cursor ) -> tuple [list [str ], list [str ]]:
849+ """Extract function call references from a cursor's children.
850+
851+ Returns ``(callees, baselib_callees)``:
852+
853+ * ``callees`` — normal resolvable callees (UNCHANGED filter: system/stdlib
854+ prefixes dropped). Feeds local dep-resolution + call-edges exactly as
855+ before, so OFF behavior is byte-identical.
856+ * ``baselib_callees`` — callees that were dropped by the normal filter BUT
857+ are cross-linkable base-lib namespaces (std::/boost::). Captured here in the
858+ SAME walk so the cross-repo linker can resolve them against the global
859+ symbol index WITHOUT touching the normal callee path. Ignored entirely when
860+ cross-repo linking is disabled.
861+ """
862+ callees : set [str ] = set ()
863+ baselib_callees : set [str ] = set ()
819864
820865 def walk (node : Cursor ):
821866 if node .kind == CursorKind .CALL_EXPR :
822867 ref = node .referenced
823868 if ref and ref .spelling :
824869 # Get fully qualified name
825870 qname = get_qualified_name (ref )
826- if qname and not is_system_function (qname ):
827- callees .add (qname )
871+ if qname :
872+ if not is_system_function (qname ):
873+ callees .add (qname )
874+ elif is_crosslinkable_baselib (qname ):
875+ baselib_callees .add (qname )
828876 for child in node .get_children ():
829877 walk (child )
830878
831879 walk (cursor )
832- return list (callees )
880+ return list (callees ), list ( baselib_callees )
833881
834882
835883_REFERENCED_TYPE_DECL_KINDS = frozenset ({
@@ -1020,7 +1068,7 @@ def visit(cursor):
10201068 )
10211069 )
10221070 if text and len (text ) >= 20 :
1023- callees = extract_callees (cursor )
1071+ callees , baselib_callees = extract_callees (cursor )
10241072 referenced_types = extract_referenced_types (cursor )
10251073 qname = get_qualified_name (cursor )
10261074 functions .append (FunctionDef (
@@ -1036,6 +1084,7 @@ def visit(cursor):
10361084 sibling_index = func_sibling_index ,
10371085 ast_node_type = func_ast_node_type ,
10381086 referenced_types = referenced_types ,
1087+ baselib_callees = baselib_callees ,
10391088 ))
10401089 return
10411090
@@ -1380,6 +1429,29 @@ def collect_transitive_deps(
13801429 the base lib (depth-1 only), and we SKIP trivial/tiny inline bodies — that is
13811430 bounded by ``crosslink_budget`` + the builder's body-len floor.
13821431 """
1432+ crosslink_active = (
1433+ global_symbols is not None
1434+ and crosslink_visited is not None
1435+ and crosslink_budget is not None
1436+ )
1437+
1438+ def _try_crosslink (callee : str ) -> None :
1439+ # Depth-1 only: a pulled base-lib def is a LEAF; we never enqueue it, so
1440+ # its base-lib-internal callees are not followed. Bounds (count + token
1441+ # budget) are enforced by crosslink_budget. ONE clear path; a miss (not a
1442+ # selected base-lib symbol) is simply a no-op, never a fallback.
1443+ if callee in crosslink_visited :
1444+ return
1445+ if not crosslink_budget .has_room ():
1446+ return
1447+ hit = global_symbols .lookup (callee )
1448+ if hit is None :
1449+ return
1450+ if not crosslink_budget .can_afford (hit ["token_est" ]):
1451+ return
1452+ crosslink_visited .add (callee )
1453+ crosslink_budget .spend (hit ["token_est" ])
1454+
13831455 visited = {root_qname }
13841456 queue = deque ([(root_qname , 0 )])
13851457 deps = []
@@ -1398,25 +1470,16 @@ def collect_transitive_deps(
13981470 visited .add (callee )
13991471 deps .append (callee )
14001472 queue .append ((callee , depth + 1 ))
1401- elif (
1402- global_symbols is not None
1403- and crosslink_visited is not None
1404- and crosslink_budget is not None
1405- ):
1406- # Unresolved callee: try the cross-repo base-lib index. Depth-1
1407- # only — a pulled base-lib def is a LEAF here; we never enqueue it
1408- # so its base-lib-internal callees are not followed.
1409- if callee in crosslink_visited :
1410- continue
1411- if not crosslink_budget .has_room ():
1412- continue
1413- hit = global_symbols .lookup (callee )
1414- if hit is None :
1415- continue
1416- if not crosslink_budget .can_afford (hit ["token_est" ]):
1417- continue
1418- crosslink_visited .add (callee )
1419- crosslink_budget .spend (hit ["token_est" ])
1473+ elif crosslink_active :
1474+ # An unresolved callee (not local) MIGHT be a base-lib symbol
1475+ # (e.g. a vendored/forward-declared libc-style name). Try it.
1476+ _try_crosslink (callee )
1477+ # Base-lib-namespaced callees (std::/boost::) were filtered out of
1478+ # `callees` by the normal system-prefix filter and live here. They are
1479+ # the PRIMARY cross-link source. Only consulted when cross-linking is on.
1480+ if crosslink_active :
1481+ for callee in func .baselib_callees :
1482+ _try_crosslink (callee )
14201483
14211484 return deps
14221485
0 commit comments