build(core): fix Rust library path in SConscript
What changed, and why it matters
This commit is a build-system fix for the Trezor firmware. It changes how the Rust static library is added to the linker command in SCons scripts and corrects the relative path to the compiled Rust library. There is no indication in the commit that this fixes a security vulnerability; it appears to be a build correctness or path-fix change.
No security action required. Treat as a normal build-system maintenance commit. If desired, verify that firmware builds still produce identical/expected binaries and that the Rust library is correctly linked.
Security signals we found
No security-relevant keywords in commit title or message
No functional code changes to firmware logic
Build system path correction only
No changelog entry suggests routine build fix
Evidence from the diff
The patch modifies multiple SConscript files to add the Rust library target directly to the obj_program object list (obj_program += [rust]) instead of relying on env.Depends(program_elf, rust). It also updates core/site_scons/tools.py to make RUST_LIBDIR relative to build_dir, removes direct -L/-l linker flag injection, and adds env.AlwaysBuild(rust). These are build-system plumbing changes to ensure the Rust library is correctly located and linked. No runtime code behavior changes are visible in the diff.
Changed components
core/SConscript.bootloadercore/SConscript.bootloader_emucore/SConscript.firmwarecore/SConscript.kernelcore/SConscript.prodtestcore/SConscript.prodtest_emucore/SConscript.unixcore/site_scons/tools.pyInspect captured patch +17 / −23
diff --git a/core/SConscript.bootloader b/core/SConscript.bootloader
index 894dec8b..e9cc84b7 100644
--- a/core/SConscript.bootloader
+++ b/core/SConscript.bootloader
@@ -278,6 +278,7 @@ obj_program += env.Object(source=SOURCE_MOD_CRYPTO, CCFLAGS='$CCFLAGS -ftrivial-
obj_program += env.Object(source=SOURCE_BOOTLOADER)
obj_program += env.Object(source=SOURCE_NANOPB)
obj_program += env.Object(source=SOURCE_HAL)
+obj_program += [rust]
if 'boot_ucb' in FEATURES_AVAILABLE:
obj_program += env.Object(
@@ -299,7 +300,6 @@ program_elf = env.Command(
)
env.Depends(program_elf, linkerscript_gen)
-env.Depends(program_elf, rust)
SUFFIX = '_qa' if BOOTLOADER_QA else ''
diff --git a/core/SConscript.bootloader_emu b/core/SConscript.bootloader_emu
index f5b627f4..7a1466aa 100644
--- a/core/SConscript.bootloader_emu
+++ b/core/SConscript.bootloader_emu
@@ -266,6 +266,7 @@ obj_program += env.Object(source=SOURCE_MOD_CRYPTO, CCFLAGS='$CCFLAGS -ftrivial-
obj_program += env.Object(source=SOURCE_BOOTLOADER)
obj_program += env.Object(source=SOURCE_NANOPB)
obj_program += env.Object(source=SOURCE_UNIX)
+obj_program += [rust]
program_elf = env.Command(
target='bootloader.elf',
@@ -273,7 +274,5 @@ program_elf = env.Command(
action=
'$CC -o $TARGET $SOURCES $_LIBDIRFLAGS $_LIBFLAGS $LINKFLAGS')
-env.Depends(program_elf, rust)
-
if CMAKELISTS != 0:
env.Depends(program_elf, cmake_gen)
diff --git a/core/SConscript.firmware b/core/SConscript.firmware
index 3f1403b6..31fdffbc 100644
--- a/core/SConscript.firmware
+++ b/core/SConscript.firmware
@@ -904,6 +904,7 @@ rust = tools.add_rust_lib(
all_paths=ALLPATHS,
build_dir=str(Dir('.').abspath),
)
+obj_program += [rust]
env.Depends(rust, protobuf_blobs)
@@ -997,7 +998,6 @@ env.Depends(program_elf, linkerscript_gen)
if CMAKELISTS != 0:
env.Depends(program_elf, cmake_gen)
-env.Depends(program_elf, rust)
BINARY_NAME = f"build/firmware/firmware-{TREZOR_MODEL}"
if not EVERYTHING:
diff --git a/core/SConscript.kernel b/core/SConscript.kernel
index 4fb7f2ac..c7fca3d0 100644
--- a/core/SConscript.kernel
+++ b/core/SConscript.kernel
@@ -444,6 +444,7 @@ rust = tools.add_rust_lib(
all_paths=ALLPATHS,
build_dir=str(Dir('.').abspath),
)
+obj_program += [rust]
if "secmon_layout" in FEATURES_AVAILABLE:
@@ -460,7 +461,6 @@ program_elf = env.Command(
)
env.Depends(program_elf, linkerscript_gen)
-env.Depends(program_elf, rust)
if CMAKELISTS != 0:
env.Depends(program_elf, cmake_gen)
diff --git a/core/SConscript.prodtest b/core/SConscript.prodtest
index 3b2c2d54..c889cd81 100644
--- a/core/SConscript.prodtest
+++ b/core/SConscript.prodtest
@@ -338,6 +338,7 @@ rust = tools.add_rust_lib(
all_paths=ALLPATHS,
build_dir=str(Dir('.').abspath),
)
+obj_program += [rust]
if (vh := ARGUMENTS.get("VENDOR_HEADER", None)):
@@ -378,7 +379,6 @@ program_elf = env.Command(
)
env.Depends(program_elf, linkerscript_gen)
-env.Depends(program_elf, rust)
BINARY_NAME = f"build/prodtest/prodtest-{TREZOR_MODEL}"
BINARY_NAME += "-" + tools.get_version('embed/projects/prodtest/version.h')
diff --git a/core/SConscript.prodtest_emu b/core/SConscript.prodtest_emu
index d2f033ea..dca61f1b 100644
--- a/core/SConscript.prodtest_emu
+++ b/core/SConscript.prodtest_emu
@@ -302,6 +302,7 @@ obj_program += env.Object(source=SOURCE_MOD_CRYPTO, CCFLAGS='$CCFLAGS -ftrivial-
obj_program += env.Object(source=SOURCE_PRODTEST)
obj_program += env.Object(source=SOURCE_HAL)
obj_program += env.Object(source=SOURCE_MLDSA)
+obj_program += [rust]
program_elf = env.Command(
target='prodtest.elf',
@@ -309,7 +310,5 @@ program_elf = env.Command(
action=
'$CC -o $TARGET $SOURCES $_LIBDIRFLAGS $_LIBFLAGS $LINKFLAGS')
-env.Depends(program_elf, rust)
-
if CMAKELISTS != 0:
env.Depends(program_elf, cmake_gen)
diff --git a/core/SConscript.unix b/core/SConscript.unix
index 0925df59..b31d8da5 100644
--- a/core/SConscript.unix
+++ b/core/SConscript.unix
@@ -925,7 +925,7 @@ rust = tools.add_rust_lib(
all_paths=ALLPATHS,
build_dir=str(Dir('.').abspath),
)
-
+obj_program += [rust]
env.Depends(rust, protobuf_blobs)
env.Depends(rust, TRANSLATION_DATA)
@@ -938,4 +938,3 @@ program = env.Command(
if CMAKELISTS != 0:
env.Depends(program, cmake_gen)
-env.Depends(program, rust)
diff --git a/core/site_scons/tools.py b/core/site_scons/tools.py
index 1bf8be08..96aa4f16 100644
--- a/core/site_scons/tools.py
+++ b/core/site_scons/tools.py
@@ -151,21 +151,18 @@ def add_rust_lib(*, env, build, profile, features, all_paths, build_dir):
RUST_TARGET = env.get("ENV")["RUST_TARGET"]
# Determine the profile build flags.
- if profile == "release":
- profile = "--release"
- is_debug = False
- RUST_LIBDIR = f"build/{build}/rust/{RUST_TARGET}/release"
- else:
- profile = ""
- is_debug = True
- RUST_LIBDIR = f"build/{build}/rust/{RUST_TARGET}/debug"
+ is_debug = {"dev": True, "release": False}[profile]
+
+ # Don't prefix with `build_dir` - the paths below should be relative to it.
+ RUST_LIBDIR = f"rust/{RUST_TARGET}/{'debug' if is_debug else 'release'}"
RUST_LIBPATH = f"{RUST_LIBDIR}/lib{RUST_LIB}.a"
def cargo_build():
lib_features = []
lib_features.extend(features)
- cargo_opts = [
+ cargo_opts = [] if is_debug else ["--release"]
+ cargo_opts += [
f"--target={RUST_TARGET}",
f"--target-dir=../../build/{build}/rust",
"--no-default-features",
@@ -178,7 +175,7 @@ def add_rust_lib(*, env, build, profile, features, all_paths, build_dir):
"-Z build-std-features=panic_immediate_abort",
]
- build_cmd = f"cargo build {profile} " + " ".join(cargo_opts)
+ build_cmd = "cargo build " + " ".join(cargo_opts)
unstable_rustc_flags = [
# see https://nnethercote.github.io/perf-book/type-sizes.html#measuring-type-sizes for more details
@@ -200,13 +197,13 @@ def add_rust_lib(*, env, build, profile, features, all_paths, build_dir):
f"cd embed/rust; {build_cmd} > {build_dir}/rust-type-sizes.log"
)
+ # Target path should be relative to `build_dir`.
rust = env.Command(
target=RUST_LIBPATH,
source="",
action=cargo_build(),
)
-
- env.Append(LINKFLAGS=[f"-L{RUST_LIBDIR}"])
- env.Append(LINKFLAGS=[f"-l{RUST_LIB}"])
+ # TODO: run `cargo` only if needed
+ env.AlwaysBuild(rust)
return rust
Why this scored 12/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.