Revert "deb: run the rootless build step under fakeroot, sharing the state"
This reverts commit 5f36a54db42e0e5b8f5243dded89f68cd93fa689. Fakeroot's IPC degrades under kernel-scale parallel builds: a linux-riscv build with make -j plus LTO floods the faked daemon and libfakeroot prints 'internal error: payload not recognized' per mangled message, with the ownership database losing entries. The benefit the wrap bought is vacuous anyway: the .deb is assembled in the binary step's own fakeroot session, which records files unknown to its database as root-owned — verified with a sysroot package whose build chown fails: the produced .deb still carries root/root. A rules chown failing for the unprivileged build user stays expected and harmless; the visible noise is collapsed at the classifier level instead (next commit). The bare build step also matches modern dpkg semantics: with Rules-Requires-Root: binary-targets (pkh's default export), dpkg-buildpackage itself runs the build targets unprivileged and fakes root only for the binary targets.
This commit is contained in:
+12
-45
@@ -250,14 +250,6 @@ fn rules_command<'a>(
|
||||
}
|
||||
}
|
||||
|
||||
/// The fakeroot state file shared by the rules steps of a rootless
|
||||
/// build, in the upload directory next to the staged tree: outside the
|
||||
/// package tree, so it pollutes neither the sources nor the collected
|
||||
/// artifacts.
|
||||
fn fakeroot_state_file(upload_dir: &str) -> PathBuf {
|
||||
Path::new(upload_dir).join(".pkh-fakeroot.state")
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub async fn build(
|
||||
package: &str,
|
||||
@@ -688,10 +680,16 @@ pub async fn build(
|
||||
.unwrap_or_else(|| "binary-targets".to_string());
|
||||
env.insert("DEB_RULES_REQUIRES_ROOT".to_string(), rules_requires_root);
|
||||
|
||||
// Rootless builds: the rules (fakeroot-wrapped, see below) run as an
|
||||
// unprivileged user owning the staged tree. Everything before this
|
||||
// point - dependency installation, quilt patch application, staging
|
||||
// cleanup - legitimately needs the context's root and stays with it.
|
||||
// Rootless builds: the rules run as an unprivileged user owning the
|
||||
// staged tree. Everything before this point - dependency installation,
|
||||
// quilt patch application, staging cleanup - legitimately needs the
|
||||
// context's root and stays with it. The build step runs BARE (no
|
||||
// fakeroot): fakeroot's IPC degrades under kernel-scale parallel
|
||||
// builds ('libfakeroot internal error: payload not recognized' per
|
||||
// LTO/make -j process flood), and a rules chown that fails for the
|
||||
// build user is cosmetic — the .deb is assembled in the binary step's
|
||||
// own fakeroot session, where files unknown to its database are
|
||||
// recorded as root-owned anyway.
|
||||
let rule_ids = match build_user {
|
||||
Some(_) => {
|
||||
let workroot = Path::new(package_dir_str)
|
||||
@@ -704,34 +702,12 @@ pub async fn build(
|
||||
None => None,
|
||||
};
|
||||
|
||||
// Rootless: the rules run under fakeroot with one session state
|
||||
// shared between the build and binary steps, the way
|
||||
// dpkg-buildpackage -rfakeroot wraps every rules target. An
|
||||
// ownership change made during the build (a sysroot chown) then
|
||||
// succeeds — faked — and carries into the .deb, instead of failing
|
||||
// per file with EPERM spam. With the context's own user the build
|
||||
// step runs bare; the binary step keeps its unconditional wrap.
|
||||
let fakeroot_state = fakeroot_state_file(upload_dir);
|
||||
if rule_ids.is_some() {
|
||||
// A state left by an interrupted previous attempt must not
|
||||
// seed this session.
|
||||
let _ = ctx.command("rm").arg("-f").arg(&fakeroot_state).status();
|
||||
}
|
||||
let mut rules = match rule_ids.as_ref() {
|
||||
Some(_) => {
|
||||
let mut cmd = rules_command(&ctx, rule_ids.as_ref(), "fakeroot");
|
||||
cmd.arg("-s").arg(&fakeroot_state).arg("debian/rules");
|
||||
cmd
|
||||
}
|
||||
None => rules_command(&ctx, None, "debian/rules"),
|
||||
};
|
||||
|
||||
// Run the build step
|
||||
log::debug!("Building (debian/rules build) package...");
|
||||
enter_phase(view, Phase::Building, profiler);
|
||||
let started = Instant::now();
|
||||
let status = cap(
|
||||
rules
|
||||
rules_command(&ctx, rule_ids.as_ref(), "debian/rules")
|
||||
.current_dir(package_dir_str)
|
||||
.envs(env.clone())
|
||||
.arg("build"),
|
||||
@@ -760,17 +736,8 @@ pub async fn build(
|
||||
// Run the 'binary' step to produce deb
|
||||
enter_phase(view, Phase::ProducingBinaries, profiler);
|
||||
let started = Instant::now();
|
||||
let mut rules = rules_command(&ctx, rule_ids.as_ref(), "fakeroot");
|
||||
if rule_ids.is_some() {
|
||||
// Pick up the ownership changes the build step recorded.
|
||||
rules
|
||||
.arg("-i")
|
||||
.arg(&fakeroot_state)
|
||||
.arg("-s")
|
||||
.arg(&fakeroot_state);
|
||||
}
|
||||
let status = cap(
|
||||
rules
|
||||
rules_command(&ctx, rule_ids.as_ref(), "fakeroot")
|
||||
.current_dir(package_dir_str)
|
||||
.envs(env.clone())
|
||||
.arg("debian/rules")
|
||||
|
||||
Reference in New Issue
Block a user