debian/arch: native architecture tables replacing dpkg-architecture
Embed dpkg's factual cputable/ostable/tupletable/abitable data and implement tuple/triplet/multiarch lookups, wildcard matching, arch restriction evaluation and the full DEB_BUILD_*/DEB_HOST_*/DEB_TARGET_* environment dump natively. build/env.rs::arch_env now delegates to the native implementation instead of shelling out to 'dpkg-architecture -f'. Differential gate (build/mod.rs): arch_env(Some(a)) must equal real 'dpkg-architecture -f -a a' key-for-key for every architecture listed by 'dpkg-architecture -L', plus the native case. Data tables carry upstream attribution comments; no dpkg code was transliterated.
This commit is contained in:
+6
-33
@@ -1,10 +1,9 @@
|
||||
//! Build environment setup: `SOURCE_DATE_EPOCH`, `DEB_BUILD_OPTIONS`,
|
||||
//! architecture variables (via `dpkg-architecture`) and the sanitized
|
||||
//! environment recorded in `.buildinfo` files.
|
||||
//! architecture variables (native `dpkg-architecture` equivalent) and the
|
||||
//! sanitized environment recorded in `.buildinfo` files.
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
use std::path::Path;
|
||||
use std::process::Command;
|
||||
|
||||
/// Number of parallel jobs to advertise in `DEB_BUILD_OPTIONS`.
|
||||
pub fn num_parallel() -> usize {
|
||||
@@ -41,41 +40,15 @@ pub fn build_env(
|
||||
env
|
||||
}
|
||||
|
||||
/// Import the full architecture variable set by running
|
||||
/// `dpkg-architecture -f [-a <host-arch>]` and parsing its `KEY=VALUE` dump.
|
||||
/// Import the full architecture variable set, computed natively by
|
||||
/// [`crate::debian::arch`] (the equivalent of `dpkg-architecture -f
|
||||
/// [-a <host-arch>]`).
|
||||
///
|
||||
/// This exports all `DEB_BUILD_*`, `DEB_HOST_*` and `DEB_TARGET_*` variables
|
||||
/// (`*_ARCH`, `*_OS`, `*_CPU`, `*_MULTIARCH`, `*_GNU_TYPE`, ...), exactly as
|
||||
/// `dpkg-buildpackage` does.
|
||||
pub fn arch_env(host_arch: Option<&str>) -> Result<BTreeMap<String, String>, String> {
|
||||
let mut cmd = Command::new("dpkg-architecture");
|
||||
cmd.arg("-f");
|
||||
if let Some(arch) = host_arch {
|
||||
cmd.args(["--host-arch", arch]);
|
||||
}
|
||||
|
||||
let output = cmd.output().map_err(|e| {
|
||||
format!(
|
||||
"failed to run 'dpkg-architecture': {}. Is 'dpkg-dev' installed?",
|
||||
e
|
||||
)
|
||||
})?;
|
||||
|
||||
if !output.status.success() {
|
||||
return Err(format!(
|
||||
"dpkg-architecture failed with status {}: {}",
|
||||
output.status,
|
||||
String::from_utf8_lossy(&output.stderr).trim()
|
||||
));
|
||||
}
|
||||
|
||||
let mut env = BTreeMap::new();
|
||||
for line in String::from_utf8_lossy(&output.stdout).lines() {
|
||||
if let Some((key, value)) = line.split_once('=') {
|
||||
env.insert(key.to_string(), value.to_string());
|
||||
}
|
||||
}
|
||||
Ok(env)
|
||||
crate::debian::arch::arch_env(host_arch)
|
||||
}
|
||||
|
||||
/// Read the current vendor name from `/etc/dpkg/origins/default`
|
||||
|
||||
@@ -859,6 +859,56 @@ mod differential_tests {
|
||||
differential_on_tree(&tree);
|
||||
}
|
||||
|
||||
/// Differential check of [`crate::debian::arch::arch_env`] against real
|
||||
/// `dpkg-architecture -f -a <arch>` for one architecture.
|
||||
fn diff_arch_env_one(arch: Option<&str>) {
|
||||
let mut cmd = Command::new("dpkg-architecture");
|
||||
cmd.arg("-f");
|
||||
if let Some(a) = arch {
|
||||
cmd.args(["-a", a]);
|
||||
}
|
||||
let output = cmd.output().expect("run dpkg-architecture (is dpkg-dev installed?)");
|
||||
assert!(
|
||||
output.status.success(),
|
||||
"dpkg-architecture -f {arch:?} failed: {}",
|
||||
String::from_utf8_lossy(&output.stderr)
|
||||
);
|
||||
let mut expected = BTreeMap::new();
|
||||
for line in String::from_utf8_lossy(&output.stdout).lines() {
|
||||
if let Some((key, value)) = line.split_once('=') {
|
||||
expected.insert(key.to_string(), value.to_string());
|
||||
}
|
||||
}
|
||||
|
||||
let ours = crate::debian::arch::arch_env(arch)
|
||||
.unwrap_or_else(|e| panic!("native arch_env({arch:?}) failed: {e}"));
|
||||
assert_eq!(ours, expected, "arch_env({arch:?}) differs from dpkg-architecture");
|
||||
}
|
||||
|
||||
/// Every architecture known to the local dpkg must produce an identical
|
||||
/// environment dump (`dpkg-architecture -L`).
|
||||
#[test]
|
||||
fn diff_arch_env_all_known_arches() {
|
||||
let output = Command::new("dpkg-architecture")
|
||||
.arg("-L")
|
||||
.output()
|
||||
.expect("run dpkg-architecture -L (is dpkg-dev installed?)");
|
||||
assert!(output.status.success());
|
||||
for arch in String::from_utf8_lossy(&output.stdout).lines() {
|
||||
let arch = arch.trim();
|
||||
if arch.is_empty() {
|
||||
continue;
|
||||
}
|
||||
diff_arch_env_one(Some(arch));
|
||||
}
|
||||
}
|
||||
|
||||
/// Native (no explicit host architecture) must match too.
|
||||
#[test]
|
||||
fn diff_arch_env_native() {
|
||||
diff_arch_env_one(None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn diff_native_minimal() {
|
||||
differential_case(&FixtureSpec::new("pkh-diff-a", "1.0-1", "unstable"));
|
||||
|
||||
Reference in New Issue
Block a user