Skip to content

We have bindeps at home#2537

Open
mkeeter wants to merge 9 commits into
masterfrom
mkeeter/we-have-bindeps-at-home
Open

We have bindeps at home#2537
mkeeter wants to merge 9 commits into
masterfrom
mkeeter/we-have-bindeps-at-home

Conversation

@mkeeter
Copy link
Copy Markdown
Collaborator

@mkeeter mkeeter commented May 27, 2026

endoscope is specified as an artifact dependency of drv-lpc55-swd. This is a nightly-only feature, and is checked at (workspace) parse time. As we consider switching to a stable compiler, these two properties make it particularly annoying, because cargo xtask will fail due to its presence before we have a chance to inject any flags.

This PR implements minimal bindeps support in the Hubris build system. A task can declare a bindeps section; those dependencies are then build and specified as environment variables.

[[tasks.swd.bindeps]]
name = "endoscope"
target = "thumbv7em-none-eabihf"
features = ["soc_stm32h753"]
# That's it!  It's simple!

There's a little bit of plumbing required: we need a cargo_metadata::Metadata object to resolve manifest file from package name, so we build one and cache it in the PackageConfig. Workflows which do not construct a full PackageConfig need to build the Metadata object manually; this is a little annoying but not hard (and we are guided by the function's type signature).

@mkeeter mkeeter requested review from hawkw, jamesmunns and lzrd May 27, 2026 14:58
@mkeeter mkeeter requested review from cbiffle, flihp and labbott as code owners May 27, 2026 14:58
@mkeeter mkeeter force-pushed the mkeeter/we-have-bindeps-at-home branch from 0ca0afb to 210408f Compare May 27, 2026 15:07
@mkeeter
Copy link
Copy Markdown
Collaborator Author

mkeeter commented May 27, 2026

After doing some testing, this PR does not produce a binary-identical build. The endoscope README nods at the fact that artifacts build with cargo are smaller than those built as an artifact dependency; we're hitting that same case here (because we're now building with cargo).

I tested to confirm that the measurements upon SP reset are identical by flashing different oxide-rot-1/app-dev.toml images onto a Grapefruit with the same SP image.

master:

SpRot.log() => ()
             \/  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
0x00000000 | 01 00 00 00 00 fc 56 ec 91 8e c5 56 08 9e 42 21 | ......V....V..B!
0x00000010 | b6 6b ee 3c 2a 7b 4f d4 0b 9d 03 51 70 26 2b da | .k.<*{O....Qp&+.
0x00000020 | da c1 d0 61 ce 00 00 00 00 00 00 00 00 00 00 00 | ...a............
0x00000030 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ................

This branch:

SpRot.log() => ()
             \/  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
0x00000000 | 01 00 00 00 00 fc 56 ec 91 8e c5 56 08 9e 42 21 | ......V....V..B!
0x00000010 | b6 6b ee 3c 2a 7b 4f d4 0b 9d 03 51 70 26 2b da | .k.<*{O....Qp&+.
0x00000020 | da c1 d0 61 ce 00 00 00 00 00 00 00 00 00 00 00 | ...a............
0x00000030 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ................

@mkeeter mkeeter force-pushed the mkeeter/we-have-bindeps-at-home branch from 210408f to 5e91466 Compare May 27, 2026 17:47
@labbott
Copy link
Copy Markdown
Collaborator

labbott commented May 27, 2026

After doing some testing, this PR does not produce a binary-identical build. The endoscope README nods at the fact that artifacts build with cargo are smaller than those built as an artifact dependency; we're hitting that same case here (because we're now building with cargo).

I trust that it's doing the correct thing, do you have a sense of what the actual differences between the binaries are?

@mkeeter mkeeter force-pushed the mkeeter/we-have-bindeps-at-home branch 2 times, most recently from 9b8fe84 to 3fdafe9 Compare May 28, 2026 13:46
@mkeeter
Copy link
Copy Markdown
Collaborator Author

mkeeter commented May 28, 2026

I trust that it's doing the correct thing, do you have a sense of what the actual differences between the binaries are?

Found it: the bindeps-based build inherits RUSTFLAGS from the outer environment, so it's getting

format!(
    "-C link-arg=-z -C link-arg=common-page-size=0x20 \
     -C link-arg=-z -C link-arg=max-page-size=0x20 \
     -C llvm-args=--enable-machine-outliner=never \
     -Z emit-stack-sizes \
     -Z macro-backtrace \
     -C overflow-checks=y \
     -C metadata={} \
     {}
     ",
    cfg.link_script_hash, remap_path_prefix,
),

Running a build with stock cargo does not get these flags!

@lzrd @labbott Do either of you have strong opinions on whether I should make sure these flags are propagated?

@mkeeter mkeeter force-pushed the mkeeter/we-have-bindeps-at-home branch from 3fdafe9 to 7395954 Compare May 28, 2026 15:08
@labbott
Copy link
Copy Markdown
Collaborator

labbott commented May 28, 2026

@lzrd @labbott Do either of you have strong opinions on whether I should make sure these flags are propagated?

Okay so some context for the page-size

commit edc0553d44ad1956402c7a1542e0d9085a629a8b
Author: Cliff L. Biffle <cliff@oxide.computer>
Date:   Fri Jun 26 15:24:59 2020 -0700

    packager: force smaller "page size"
    
    The GNU tools, and the LLVM tools that mindlessly mimic them, came from
    demand paged systems with shared objects. As a result, our load headers
    are getting padded to the nearest "page boundary," which seems to
    default to 64kiB.
    
    This change forces that down to 32B, the MPU click size. This does not
    appear to be a thing you can do from a linker script, so we have to
    stuff it into the linker command line the hard way. :-(

and on machine-outliner and overflow-checks

commit 1e398bf02e011c3f4e1867a29a5ae537e7dc72da
Author: Cliff L. Biffle <code@cliffle.com>
Date:   Thu Jul 15 15:47:11 2021 -0700

    xtask: force overflow checks on in release builds
    
    Overflow checks are great except when they're turned off globally.
    
    This imposes a small cost in text size. I haven't checked for
    performance impact but I also don't super care -- correctness over
    performance. If it's slow, we should restructure the code to eliminate
    the checks.

I have mixed feelings here. We aren't using the MPU on with endoscope so the page sizes don't really matter. Not having overflows checks makes me nervous but we might be able to specify that in the target Cargo.toml? We should have reproducibility checks in hubris CI but it's worth checking that we still don't see any local paths sneaking in without remap_path_prefix

@mkeeter mkeeter force-pushed the mkeeter/we-have-bindeps-at-home branch from 7395954 to 31654a0 Compare May 29, 2026 15:18
@mkeeter mkeeter force-pushed the mkeeter/we-have-bindeps-at-home branch from c3ab604 to 0b5d584 Compare May 29, 2026 17:49
@mkeeter
Copy link
Copy Markdown
Collaborator Author

mkeeter commented May 29, 2026

I've deployed the standard set of RUSTFLAGS to the custom build, because I think that overflow checks are valuable, but it's still not exactly reproducible. After fighting with it for a day, I've tracked it down to flags being set slightly differently.

Here's the actual rustc invocations for cortex_m (a sample dependency) and endoscope (the actual executable).

Old (using an artifact dependency):

argv: --crate-name cortex_m --edition=2018 /Users/mjk/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/cortex-m-0.7.5/src/lib.rs --error-format=json --json=diagnostic-rendered-ansi,artifacts,future-incompat -Zallow-features=backtrace,emit_stack_sizes,error_generic_member_access,proc_macro_span,proc_macro_span_shrink,provide_any,used_with_arg --crate-type lib --emit=dep-info,metadata,link -C linker-plugin-lto -C debuginfo=2 -C debug-assertions=off --cfg feature="inline-asm" --check-cfg cfg(docsrs,test) --check-cfg cfg(feature, values("cm7", "cm7-r0p1", "inline-asm", "linker-plugin-lto", "serde", "std")) -C metadata=46b51a103b0f0506 -C extra-filename=-7d9fbe73826bc38a --out-dir /Users/mjk/oxide/hubris/target/thumbv7em-none-eabihf/release/deps --target thumbv7em-none-eabihf -L dependency=/Users/mjk/oxide/hubris/target/thumbv7em-none-eabihf/release/deps -L dependency=/Users/mjk/oxide/hubris/target/release/deps --extern bare_metal=/Users/mjk/oxide/hubris/target/thumbv7em-none-eabihf/release/deps/libbare_metal-aa7c3ff21d01d5a0.rmeta --extern bitfield=/Users/mjk/oxide/hubris/target/thumbv7em-none-eabihf/release/deps/libbitfield-1aba2bb3033af903.rmeta --extern embedded_hal=/Users/mjk/oxide/hubris/target/thumbv7em-none-eabihf/release/deps/libembedded_hal-b3551ddd33ac9de6.rmeta --extern volatile_register=/Users/mjk/oxide/hubris/target/thumbv7em-none-eabihf/release/deps/libvolatile_register-2709eb4c67ed7411.rmeta --cap-lints allow -C link-arg=-z -C link-arg=common-page-size=0x20 -C link-arg=-z -C link-arg=max-page-size=0x20 -C llvm-args=--enable-machine-outliner=never -Z emit-stack-sizes -Z macro-backtrace -C overflow-checks=y -C metadata=18179008993053602939 --remap-path-prefix=/Users/mjk/.cargo/git/checkouts=/git --remap-path-prefix=/Users/mjk/.cargo/registry/src/github.com-1ecc6299db9ec823=/crates.io --remap-path-prefix=/Users/mjk/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f=/crates.io --remap-path-prefix=/Users/mjk/.rustup/toolchains/nightly-2025-07-20-aarch64-apple-darwin/lib/rustlib/src/rust/library/core/src=/rustlib --remap-path-prefix=/Users/mjk/oxide/hubris=/hubris --remap-path-prefix=/Users/mjk/oxide/hubris/target/thumbv8m.main-none-eabihf/release/build=/hubris/build -L /Users/mjk/oxide/hubris/target/thumbv7em-none-eabihf/release/build/cortex-m-b27de3c90998f404/out -l static=cortex-m --cfg cortex_m --cfg armv7m --cfg armv7em --cfg has_fpu
...
argv: --crate-name endoscope --edition=2024 lib/endoscope/src/main.rs --error-format=json --json=diagnostic-rendered-ansi,artifacts,future-incompat -Zallow-features=backtrace,emit_stack_sizes,error_generic_member_access,proc_macro_span,proc_macro_span_shrink,provide_any,used_with_arg --crate-type bin --emit=dep-info,link -C opt-level=z -C lto -C codegen-units=1 -C debuginfo=2 --cfg feature="soc_stm32h753" --check-cfg cfg(docsrs,test) --check-cfg cfg(feature, values("soc_stm32h753")) -C metadata=ae3628408cf18508 -C extra-filename=-453b1b1564cdab4c --out-dir /Users/mjk/oxide/hubris/target/thumbv7em-none-eabihf/release/deps/artifact/endoscope-453b1b1564cdab4c/bin --target thumbv7em-none-eabihf -L dependency=/Users/mjk/oxide/hubris/target/thumbv7em-none-eabihf/release/deps -L dependency=/Users/mjk/oxide/hubris/target/release/deps --extern cortex_m=/Users/mjk/oxide/hubris/target/thumbv7em-none-eabihf/release/deps/libcortex_m-7d9fbe73826bc38a.rlib --extern cortex_m_rt=/Users/mjk/oxide/hubris/target/thumbv7em-none-eabihf/release/deps/libcortex_m_rt-9f24b2f301edf832.rlib --extern drv_stm32h7_startup=/Users/mjk/oxide/hubris/target/thumbv7em-none-eabihf/release/deps/libdrv_stm32h7_startup-8d73b40a2e81cca5.rlib --extern endoscope_abi=/Users/mjk/oxide/hubris/target/thumbv7em-none-eabihf/release/deps/libendoscope_abi-64c187d3a69647b8.rlib --extern panic_halt=/Users/mjk/oxide/hubris/target/thumbv7em-none-eabihf/release/deps/libpanic_halt-9ac4e10b3b891582.rlib --extern sha3=/Users/mjk/oxide/hubris/target/thumbv7em-none-eabihf/release/deps/libsha3-0d75cd20db82b056.rlib --extern stm32h7=/Users/mjk/oxide/hubris/target/thumbv7em-none-eabihf/release/deps/libstm32h7-005c9c0b004e2f49.rlib -C link-arg=-z -C link-arg=common-page-size=0x20 -C link-arg=-z -C link-arg=max-page-size=0x20 -C llvm-args=--enable-machine-outliner=never -Z emit-stack-sizes -Z macro-backtrace -C overflow-checks=y -C metadata=18179008993053602939 --remap-path-prefix=/Users/mjk/.cargo/git/checkouts=/git --remap-path-prefix=/Users/mjk/.cargo/registry/src/github.com-1ecc6299db9ec823=/crates.io --remap-path-prefix=/Users/mjk/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f=/crates.io --remap-path-prefix=/Users/mjk/.rustup/toolchains/nightly-2025-07-20-aarch64-apple-darwin/lib/rustlib/src/rust/library/core/src=/rustlib --remap-path-prefix=/Users/mjk/oxide/hubris=/hubris --remap-path-prefix=/Users/mjk/oxide/hubris/target/thumbv8m.main-none-eabihf/release/build=/hubris/build -L /Users/mjk/oxide/hubris/target/thumbv7em-none-eabihf/release/build/cortex-m-b27de3c90998f404/out -L /Users/mjk/oxide/hubris/target/thumbv7em-none-eabihf/release/build/cortex-m-rt-2248f062ab34d99f/out -L /Users/mjk/oxide/hubris/lib/endoscope/scripts -C link-arg=--verbose -C link-arg=-Tstm32h753.x

New (this PR, calling Cargo manually):

argv: --crate-name cortex_m --edition=2018 /Users/mjk/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/cortex-m-0.7.5/src/lib.rs --error-format=json --json=diagnostic-rendered-ansi,artifacts,future-incompat --diagnostic-width=129 --crate-type lib --emit=dep-info,metadata,link -C opt-level=z -C linker-plugin-lto -C codegen-units=1 -C debuginfo=2 --cfg feature="inline-asm" --check-cfg cfg(docsrs,test) --check-cfg cfg(feature, values("cm7", "cm7-r0p1", "inline-asm", "linker-plugin-lto", "serde", "std")) -C metadata=93557729e0e57c3c -C extra-filename=-4ea8d066a073efbe --out-dir /Users/mjk/oxide/hubris/target/bindeps/swd/thumbv7em-none-eabihf/release/deps --target thumbv7em-none-eabihf -L dependency=/Users/mjk/oxide/hubris/target/bindeps/swd/thumbv7em-none-eabihf/release/deps -L dependency=/Users/mjk/oxide/hubris/target/bindeps/swd/release/deps --extern bare_metal=/Users/mjk/oxide/hubris/target/bindeps/swd/thumbv7em-none-eabihf/release/deps/libbare_metal-c71b317f2b33711d.rmeta --extern bitfield=/Users/mjk/oxide/hubris/target/bindeps/swd/thumbv7em-none-eabihf/release/deps/libbitfield-8f316e03f17ce1f3.rmeta --extern embedded_hal=/Users/mjk/oxide/hubris/target/bindeps/swd/thumbv7em-none-eabihf/release/deps/libembedded_hal-a4a432cbd529cb03.rmeta --extern volatile_register=/Users/mjk/oxide/hubris/target/bindeps/swd/thumbv7em-none-eabihf/release/deps/libvolatile_register-e1bb98f13d172885.rmeta --cap-lints allow -C link-arg=-z -C link-arg=common-page-size=0x20 -C link-arg=-z -C link-arg=max-page-size=0x20 -C llvm-args=--enable-machine-outliner=never -Z emit-stack-sizes -Z macro-backtrace -C overflow-checks=y --remap-path-prefix=/Users/mjk/.cargo/git/checkouts=/git --remap-path-prefix=/Users/mjk/.cargo/registry/src/github.com-1ecc6299db9ec823=/crates.io --remap-path-prefix=/Users/mjk/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f=/crates.io --remap-path-prefix=/Users/mjk/.rustup/toolchains/nightly-2025-07-20-aarch64-apple-darwin/lib/rustlib/src/rust/library/core/src=/rustlib --remap-path-prefix=/Users/mjk/oxide/hubris=/hubris --remap-path-prefix=/Users/mjk/oxide/hubris/target/thumbv8m.main-none-eabihf/release/build=/hubris/build -C lto -L /Users/mjk/oxide/hubris/target/bindeps/swd/thumbv7em-none-eabihf/release/build/cortex-m-2d726b4bd6f9446d/out -l static=cortex-m --cfg cortex_m --cfg armv7m --cfg armv7em --cfg has_fpu
...
argv: --crate-name endoscope --edition=2024 lib/endoscope/src/main.rs --error-format=json --json=diagnostic-rendered-ansi,artifacts,future-incompat --diagnostic-width=129 --crate-type bin --emit=dep-info,link -C opt-level=z -C lto -C codegen-units=1 -C debuginfo=2 --cfg feature="soc_stm32h753" --check-cfg cfg(docsrs,test) --check-cfg cfg(feature, values("soc_stm32h753")) -C metadata=02537e9eff746c31 -C extra-filename=-f34a73097298262d --out-dir /Users/mjk/oxide/hubris/target/bindeps/swd/thumbv7em-none-eabihf/release/deps --target thumbv7em-none-eabihf -L dependency=/Users/mjk/oxide/hubris/target/bindeps/swd/thumbv7em-none-eabihf/release/deps -L dependency=/Users/mjk/oxide/hubris/target/bindeps/swd/release/deps --extern cortex_m=/Users/mjk/oxide/hubris/target/bindeps/swd/thumbv7em-none-eabihf/release/deps/libcortex_m-4ea8d066a073efbe.rlib --extern cortex_m_rt=/Users/mjk/oxide/hubris/target/bindeps/swd/thumbv7em-none-eabihf/release/deps/libcortex_m_rt-321e3a27d84387b2.rlib --extern drv_stm32h7_startup=/Users/mjk/oxide/hubris/target/bindeps/swd/thumbv7em-none-eabihf/release/deps/libdrv_stm32h7_startup-30e3ebf8d684bf45.rlib --extern endoscope_abi=/Users/mjk/oxide/hubris/target/bindeps/swd/thumbv7em-none-eabihf/release/deps/libendoscope_abi-5104fbeec2558855.rlib --extern panic_halt=/Users/mjk/oxide/hubris/target/bindeps/swd/thumbv7em-none-eabihf/release/deps/libpanic_halt-3639b75b80adeebb.rlib --extern sha3=/Users/mjk/oxide/hubris/target/bindeps/swd/thumbv7em-none-eabihf/release/deps/libsha3-74d460dbf3801767.rlib --extern stm32h7=/Users/mjk/oxide/hubris/target/bindeps/swd/thumbv7em-none-eabihf/release/deps/libstm32h7-cc83436b44b11619.rlib -C link-arg=-z -C link-arg=common-page-size=0x20 -C link-arg=-z -C link-arg=max-page-size=0x20 -C llvm-args=--enable-machine-outliner=never -Z emit-stack-sizes -Z macro-backtrace -C overflow-checks=y --remap-path-prefix=/Users/mjk/.cargo/git/checkouts=/git --remap-path-prefix=/Users/mjk/.cargo/registry/src/github.com-1ecc6299db9ec823=/crates.io --remap-path-prefix=/Users/mjk/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f=/crates.io --remap-path-prefix=/Users/mjk/.rustup/toolchains/nightly-2025-07-20-aarch64-apple-darwin/lib/rustlib/src/rust/library/core/src=/rustlib --remap-path-prefix=/Users/mjk/oxide/hubris=/hubris --remap-path-prefix=/Users/mjk/oxide/hubris/target/thumbv8m.main-none-eabihf/release/build=/hubris/build -C lto -L /Users/mjk/oxide/hubris/target/bindeps/swd/thumbv7em-none-eabihf/release/build/cortex-m-2d726b4bd6f9446d/out -L /Users/mjk/oxide/hubris/target/bindeps/swd/thumbv7em-none-eabihf/release/build/cortex-m-rt-d2dff4b03f8004a5/out -L /Users/mjk/oxide/hubris/lib/endoscope/scripts -C link-arg=--verbose -C link-arg=-Tstm32h753.x

I don't expect you to read all of this, but here's the important part: the new build gets -C opt-level=z and -C codegen-units=1 inserted at the beginning of the command for both dependencies and the final endoscope target. The old build only has those flags for the final endoscope target (but not for dependencies).

I believe these arguments are inherited from the crate-level Cargo.toml, and seem reasonable to ship. When manually invoking cargo, I still couldn't figure out how to exactly match the artifact dependency behavior (flags for final executable but not for libraries), but I'm okay giving up on perfect reproducibility now that we've got a reasonable idea what's going on.

Comment thread build/xtask/src/config.rs
out
}

fn common_build_config<'a>(
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These moved to being functions on PackageConfig, because we needed many of its member variables.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants