Skip to content

nix: trim paths in nix build#3082

Open
justus-camp-microsoft wants to merge 1 commit intomicrosoft:mainfrom
justus-camp-microsoft:nix_rustflags
Open

nix: trim paths in nix build#3082
justus-camp-microsoft wants to merge 1 commit intomicrosoft:mainfrom
justus-camp-microsoft:nix_rustflags

Conversation

@justus-camp-microsoft
Copy link
Copy Markdown
Contributor

Our binary currently has machine-dependent paths in its output - to fix this rustc has a flag --remap-path-prefix, but unfortunately it requires a key-value mapping so we have to figure out the path at runtime to be replaced. A future rust version will have better support for trimming paths that should make this unnecessary (RFC here)

The RUSTFLAGS in our config.toml are duplicated here instead of trying to do some sort of merge/reading of the .toml file at runtime.

@justus-camp-microsoft justus-camp-microsoft requested review from a team as code owners March 20, 2026 19:12
Copilot AI review requested due to automatic review settings March 20, 2026 19:12
@jstarks
Copy link
Copy Markdown
Member

jstarks commented Mar 20, 2026

I thought if we set RUSTFLAGS then basically it overwrites basically every other way of settings rust flags (config.toml, etc.). Is that right? How are we dealing with that?

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds Nix-driven, per-target RUSTFLAGS plumbing to Flowey builds so binaries don’t embed machine-specific absolute paths (via --remap-path-prefix), while ensuring env vars survive nix-shell --pure execution.

Changes:

  • Define per-target RUSTFLAGS_* variables in shell.nix (mirroring .cargo/config.toml), including Cargo registry/git remaps.
  • Teach Flowey’s cross-build init/build steps to inject the right Nix-provided RUSTFLAGS and append a repo-path remap at build time.
  • Update the Nix shell command wrapper to pass env vars through nix-shell --pure using --keep, and update CI pipeline/workflows to run the new injection steps.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
shell.nix Adds composed per-target RUSTFLAGS_* env vars (incl. remap prefixes) for Nix shells.
flowey/flowey_lib_hvlite/src/init_cross_build.rs Reads per-target RUSTFLAGS_* from Nix shell env and injects as RUSTFLAGS for cargo invocations.
flowey/flowey_lib_hvlite/src/run_cargo_build.rs Appends a repo checkout --remap-path-prefix=<repo>= to RUSTFLAGS at build time.
flowey/flowey_core/src/shell.rs Updates nix-shell --pure wrapper to preserve env via --keep and sets env on the outer process.
ci-flowey/openvmm-pr.yaml Reorders/expands Flowey steps to inject cross env before relevant build steps.
.github/workflows/openvmm-pr-release.yaml Mirrors the pipeline step changes for GitHub PR release workflow runs.
.github/workflows/openvmm-ci.yaml Mirrors the pipeline step changes for GitHub CI workflow runs.

Comment on lines +243 to +250
if let Some(entry) = final_env.iter_mut().find(|(ek, _)| *ek == k) {
entry.1 = v;
} else {
final_env.push((k, v));
}
}
EnvChange::Remove(k) => {
final_env.retain(|(ek, _)| *ek != k);
Copy link

Copilot AI Mar 20, 2026

Choose a reason for hiding this comment

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

final_env.iter_mut().find(|(ek, _)| *ek == k) dereferences and moves an OsString out of a borrowed tuple (*ek), which won’t compile. Compare by reference instead (e.g., ek == &k / ek.as_os_str() == k.as_os_str()).

Suggested change
if let Some(entry) = final_env.iter_mut().find(|(ek, _)| *ek == k) {
entry.1 = v;
} else {
final_env.push((k, v));
}
}
EnvChange::Remove(k) => {
final_env.retain(|(ek, _)| *ek != k);
if let Some(entry) = final_env.iter_mut().find(|(ek, _)| ek == &k) {
entry.1 = v;
} else {
final_env.push((k, v));
}
}
EnvChange::Remove(k) => {
final_env.retain(|(ek, _)| ek != &k);

Copilot uses AI. Check for mistakes.
Comment on lines +200 to +202
let rustflags =
flowey::shell_cmd!(rt, "printenv {rustflags_env}").read()?;
injected_env.insert("RUSTFLAGS".to_string(), rustflags);
Copy link

Copilot AI Mar 20, 2026

Choose a reason for hiding this comment

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

nix_rustflags_env is enabled for any host platform detected as FlowPlatformLinuxDistro::Nix, but FlowPlatformLinuxDistro::Nix is also selected when $PATH contains /nix/store (e.g. NixOS outside a dev shell). In that case printenv RUSTFLAGS_X64 will fail if the shell.nix vars aren’t present, breaking cross env injection. Consider gating on IN_NIX_SHELL (or otherwise detecting the nix-shell wrapper), or making the printenv read best-effort (skip override if the env var isn’t set).

Suggested change
let rustflags =
flowey::shell_cmd!(rt, "printenv {rustflags_env}").read()?;
injected_env.insert("RUSTFLAGS".to_string(), rustflags);
match flowey::shell_cmd!(rt, "printenv {rustflags_env}").read() {
Ok(rustflags) => {
injected_env.insert("RUSTFLAGS".to_string(), rustflags);
}
Err(_) => {
// If the Nix-specific RUSTFLAGS env var is not set, skip
// overriding RUSTFLAGS instead of failing the step.
}
}

Copilot uses AI. Check for mistakes.
Comment on lines +385 to +387
rustflags.push_str(&format!(
" --remap-path-prefix={}=",
repo_path.display()
Copy link

Copilot AI Mar 20, 2026

Choose a reason for hiding this comment

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

The appended --remap-path-prefix={repo_path}= is inserted into RUSTFLAGS as a whitespace-delimited string. If the checkout path contains spaces, this will be split into multiple flags and break the build / remap behavior. Consider escaping spaces (or quoting the argument in a way Cargo’s RUSTFLAGS parser accepts) before appending.

Suggested change
rustflags.push_str(&format!(
" --remap-path-prefix={}=",
repo_path.display()
// Quote the path so that spaces do not split this into multiple flags
let mut path_str = repo_path.display().to_string();
path_str = path_str.replace('"', "\\\"");
rustflags.push_str(&format!(
" --remap-path-prefix=\"{}\"=",
path_str

Copilot uses AI. Check for mistakes.
Comment on lines +243 to +250
if let Some(entry) = final_env.iter_mut().find(|(ek, _)| *ek == k) {
entry.1 = v;
} else {
final_env.push((k, v));
}
}
EnvChange::Remove(k) => {
final_env.retain(|(ek, _)| *ek != k);
Copy link

Copilot AI Mar 20, 2026

Choose a reason for hiding this comment

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

final_env.retain(|(ek, _)| *ek != k) has the same issue as above: *ek attempts to move an OsString out of a borrow and won’t compile. Use a reference comparison (e.g., ek != &k) instead.

Suggested change
if let Some(entry) = final_env.iter_mut().find(|(ek, _)| *ek == k) {
entry.1 = v;
} else {
final_env.push((k, v));
}
}
EnvChange::Remove(k) => {
final_env.retain(|(ek, _)| *ek != k);
if let Some(entry) = final_env.iter_mut().find(|(ek, _)| ek == &k) {
entry.1 = v;
} else {
final_env.push((k, v));
}
}
EnvChange::Remove(k) => {
final_env.retain(|(ek, _)| ek != &k);

Copilot uses AI. Check for mistakes.
@smalis-msft
Copy link
Copy Markdown
Contributor

Yeah we definitely don't want to just lose rustflags from other sources, that'll break all sorts of local one-off flows people might need. Is there any sort of current timeline on the rustc PR for stabilization? Or is it at least implemented unstably (behind a -Z flag) that we could use with RUSTC_BOOTSTRAP?

@justus-camp-microsoft
Copy link
Copy Markdown
Contributor Author

Yeah we definitely don't want to just lose rustflags from other sources, that'll break all sorts of local one-off flows people might need. Is there any sort of current timeline on the rustc PR for stabilization? Or is it at least implemented unstably (behind a -Z flag) that we could use with RUSTC_BOOTSTRAP?

I had no idea RUSTC_BOOTSTRAP existed - that certainly makes this change way easier. I updated this PR to set the required environment variables that trigger path stripping for the Nix build. Thanks for the direction 😄

@justus-camp-microsoft justus-camp-microsoft changed the title flowey: support for nix-defined RUSTFLAGS nix: trim paths in nix build Mar 23, 2026
@smalis-msft
Copy link
Copy Markdown
Contributor

Yeah, using RUSTC_BOOTSTRAP isn't "good", but we do it elsewhere already, and it's easier than dealing with the potential flakiness of nightly.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated no new comments.


RUST_BACKTRACE = 1;
SOURCE_DATE_EPOCH = 12345;
# Need unstable features on the stable toolchain
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Let's list exactly which unstable features, so that hopefully someday we can remove bootstrap once they're stable

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.

4 participants