11import os
2+ import sys
23from building import *
4+ from SCons .Subst import quote_spaces
35
46cwd = GetCurrentDir ()
57
68sys .path .append (os .path .join (cwd , '../tools' ))
79from build_support import (
810 detect_rust_target ,
911 make_rustflags ,
12+ make_cargo_build_std_args ,
1013 collect_features ,
1114 verify_rust_toolchain ,
1215 ensure_rust_target_installed ,
1316 cargo_build_staticlib ,
17+ get_staticlib_link_name ,
1418 clean_rust_build ,
1519)
1620def _has (sym : str ) -> bool :
@@ -20,10 +24,28 @@ def _has(sym: str) -> bool:
2024 return bool (GetDepend (sym ))
2125
2226
23- # Source files – MSH command glue
24- src = ['rust_cmd.c' ]
27+ group = []
28+ if not _has ('RT_RUST_CORE' ) and not GetOption ('clean' ):
29+ Return ('group' )
30+
31+
32+ def get_staticlib_link_name_from_artifact (lib_path ):
33+ """Derive the link name from the actual staticlib artifact file name."""
34+ artifact_name = os .path .basename (os .fspath (lib_path ))
35+ if artifact_name .startswith ("lib" ) and artifact_name .endswith (".a" ):
36+ return artifact_name [3 :- 2 ]
37+ return None
38+
39+
40+ # Source files – MSH command glue.
41+ # rust_cmd.c references rust_init(), which is only provided by the Rust core
42+ # static library. It must only enter the build when that library is actually
43+ # produced; otherwise the C link stage fails with 'undefined reference to
44+ # rust_init' instead of failing/skipping cleanly at the Rust build step.
2545LIBS = []
2646LIBPATH = []
47+ LINKFLAGS = ""
48+ include_rust_cmd = False
2749
2850if GetOption ('clean' ):
2951 # Register Rust artifacts for cleaning
@@ -33,39 +55,65 @@ if GetOption('clean'):
3355 Clean ('.' , rust_build_dir )
3456 else :
3557 print ('No rust build artifacts to clean' )
58+ # Keep rust_cmd.c in the group during clean so its object is cleaned too.
59+ include_rust_cmd = True
3660else :
3761 if verify_rust_toolchain ():
3862 import rtconfig
63+ rust_build_dir = clean_rust_build (Dir ('#' ).abspath )
3964
4065 target = detect_rust_target (_has , rtconfig )
4166 if not target :
4267 print ('Error: Unable to detect Rust target; please check configuration' )
68+ sys .exit (1 )
4369 else :
4470 print (f'Detected Rust target: { target } ' )
4571
4672 # Optional hint if target missing
47- ensure_rust_target_installed (target )
48-
49- # Build mode and features
50- debug = bool (_has ('RUST_DEBUG_BUILD' ))
51- features = collect_features (_has )
73+ if not ensure_rust_target_installed (target ):
74+ print ('Error: Rust target is not installed; Rust library build failed' )
75+ sys .exit (1 )
76+ else :
77+ # Build mode and features
78+ debug = bool (_has ('RUST_DEBUG_BUILD' ))
79+ features = collect_features (_has )
5280
53- rustflags = make_rustflags (rtconfig , target )
54- rust_lib = cargo_build_staticlib (
55- rust_dir = cwd , target = target , features = features , debug = debug , rustflags = rustflags
56- )
81+ rustflags = make_rustflags (rtconfig , target )
82+ cargo_extra_args = make_cargo_build_std_args (rtconfig , target )
83+ rust_lib = cargo_build_staticlib (
84+ rust_dir = cwd , target = target , features = features , debug = debug , rustflags = rustflags , build_root = rust_build_dir , cargo_extra_args = cargo_extra_args
85+ )
5786
58- if rust_lib :
59- LIBS = ['rt_rust' ]
60- LIBPATH = [os .path .dirname (rust_lib )]
61- print ('Rust library linked successfully' )
62- else :
63- print ('Warning: Failed to build Rust library' )
87+ if rust_lib :
88+ # Derive the link name from the actual artifact so it always
89+ # matches the file that was built. Only fall back to
90+ # re-parsing Cargo.toml when the artifact name does not
91+ # follow the lib<name>.a convention.
92+ link_lib_name = get_staticlib_link_name_from_artifact (rust_lib )
93+ if not link_lib_name :
94+ link_lib_name = get_staticlib_link_name (cwd )
95+ LIBS = [link_lib_name ]
96+ LIBPATH = [os .path .dirname (rust_lib )]
97+ if rtconfig .PLATFORM == 'armclang' :
98+ if not (os .path .isfile (rust_lib ) and os .path .getsize (rust_lib ) > 0 ):
99+ print (f'Error: ArmClang Rust core link requires a non-empty archive, but got: { rust_lib } ' )
100+ sys .exit (1 )
101+ LINKFLAGS = " " + quote_spaces (os .fspath (rust_lib ))
102+ LIBS = []
103+ LIBPATH = []
104+ include_rust_cmd = True
105+ print ('Rust library linked successfully' )
106+ else :
107+ print ('Error: Failed to build Rust library' )
108+ sys .exit (1 )
64109 else :
65- print ('Warning : Rust toolchain not found' )
110+ print ('Error : Rust toolchain not found' )
66111 print ('Please install Rust from https://rustup.rs' )
112+ sys .exit (1 )
67113
68- # Define component group for SCons
69- group = DefineGroup ('rust' , src , depend = ['RT_USING_RUST' ], LIBS = LIBS , LIBPATH = LIBPATH )
114+ # Only define the component group (with rust_cmd.c) when the Rust core static
115+ # library was actually produced, so its rust_init() reference always resolves.
116+ if include_rust_cmd :
117+ group = DefineGroup ('rust' , ['rust_cmd.c' ], depend = ['RT_USING_RUST' , 'RT_RUST_CORE' ], LIBS = LIBS , LIBPATH = LIBPATH , LINKFLAGS = LINKFLAGS )
70118
71119Return ('group' )
0 commit comments