deps: resolve :native against DEB_BUILD_ARCH in cross builds
CheckOpts had no build-arch concept: the build-side facts and :native qualifiers resolved against the host arch, so in a cross build (-a armhf on amd64) 'Build-Depends: foo:native' looked for an armhf package where dpkg-checkbuilddeps looks for an amd64 one. CheckOpts gains build_arch (DEB_BUILD_ARCH), used for :native and the dpkg status attribution; bracketed arch restrictions keep evaluating against the host arch.
This commit is contained in:
+7
-1
@@ -354,6 +354,10 @@ pub fn run_source_build(
|
||||
.get("DEB_HOST_ARCH")
|
||||
.cloned()
|
||||
.unwrap_or_else(|| crate::debian::arch::native().unwrap_or_default()),
|
||||
build_arch: arch_vars
|
||||
.get("DEB_BUILD_ARCH")
|
||||
.cloned()
|
||||
.unwrap_or_else(|| crate::debian::arch::native().unwrap_or_default()),
|
||||
build_profiles: profiles.clone(),
|
||||
..Default::default()
|
||||
};
|
||||
@@ -1599,8 +1603,10 @@ mod differential_tests {
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
let host_arch = crate::debian::arch::native().unwrap_or_else(|_| "amd64".into());
|
||||
let opts = crate::debian::deps::CheckOpts {
|
||||
host_arch: crate::debian::arch::native().unwrap_or_else(|_| "amd64".into()),
|
||||
host_arch: host_arch.clone(),
|
||||
build_arch: host_arch,
|
||||
build_profiles: profiles,
|
||||
ignore_arch,
|
||||
ignore_indep,
|
||||
|
||||
+77
-4
@@ -785,8 +785,15 @@ impl Facts {
|
||||
/// Options for [`check_build_depends`].
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct CheckOpts {
|
||||
/// Host architecture (defaults to the native architecture).
|
||||
/// Host architecture, i.e. `DEB_HOST_ARCH`: the architecture the
|
||||
/// packages are built FOR (defaults to the native architecture).
|
||||
/// Bracketed `foo [arch]` restrictions evaluate against it.
|
||||
pub host_arch: String,
|
||||
/// Build architecture, i.e. `DEB_BUILD_ARCH`: the architecture the
|
||||
/// build runs ON (defaults to the native architecture). `:native`
|
||||
/// dependency qualifiers and the dpkg status attribution of the
|
||||
/// build-side facts resolve against it.
|
||||
pub build_arch: String,
|
||||
/// Active build profiles.
|
||||
pub build_profiles: Vec<String>,
|
||||
/// Ignore `Build-Depends-Arch`/`Build-Conflicts-Arch` (`-A`).
|
||||
@@ -804,6 +811,7 @@ impl Default for CheckOpts {
|
||||
fn default() -> Self {
|
||||
CheckOpts {
|
||||
host_arch: arch::native().unwrap_or_default(),
|
||||
build_arch: arch::native().unwrap_or_default(),
|
||||
build_profiles: Vec::new(),
|
||||
ignore_arch: false,
|
||||
ignore_indep: false,
|
||||
@@ -904,14 +912,14 @@ pub fn check_build_depends(control: &ControlInfo, opts: &CheckOpts) -> Result<Un
|
||||
let bc_value = bc_parts.join(", ");
|
||||
|
||||
let status_path = opts.admindir.join("status");
|
||||
let facts = Facts::load_status(&status_path, &opts.host_arch, &opts.host_arch)?;
|
||||
let facts = Facts::load_status(&status_path, &opts.host_arch, &opts.build_arch)?;
|
||||
|
||||
let mut report = UnmetReport::default();
|
||||
|
||||
if !bd_value.trim().is_empty() {
|
||||
let parse_opts = ParseOpts {
|
||||
host_arch: opts.host_arch.clone(),
|
||||
build_arch: opts.host_arch.clone(),
|
||||
build_arch: opts.build_arch.clone(),
|
||||
build_profiles: opts.build_profiles.clone(),
|
||||
reduce_restrictions: true,
|
||||
union: false,
|
||||
@@ -933,7 +941,7 @@ pub fn check_build_depends(control: &ControlInfo, opts: &CheckOpts) -> Result<Un
|
||||
if !bc_value.trim().is_empty() {
|
||||
let parse_opts = ParseOpts {
|
||||
host_arch: opts.host_arch.clone(),
|
||||
build_arch: opts.host_arch.clone(),
|
||||
build_arch: opts.build_arch.clone(),
|
||||
build_profiles: opts.build_profiles.clone(),
|
||||
reduce_restrictions: true,
|
||||
union: true,
|
||||
@@ -1363,4 +1371,69 @@ Architecture: amd64
|
||||
let report = check_build_depends(&control_conflict, &opts).unwrap();
|
||||
assert_eq!(report.message(), "unmet build conflicts: mypackage");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn check_build_depends_cross_native_qualifier() {
|
||||
let dir = tempfile::tempdir().unwrap();
|
||||
let admindir = dir.path();
|
||||
|
||||
// Cross build: armhf packages built ON an amd64 machine, so
|
||||
// DEB_HOST_ARCH=armhf but DEB_BUILD_ARCH=amd64.
|
||||
let opts = CheckOpts {
|
||||
host_arch: "armhf".to_string(),
|
||||
build_arch: "amd64".to_string(),
|
||||
admindir: admindir.to_path_buf(),
|
||||
..Default::default()
|
||||
};
|
||||
let control_for = |bd: &str| {
|
||||
ControlInfo::parse_content(&format!(
|
||||
"Source: t\nMaintainer: a <a@b.c>\nBuild-Depends: {bd}\n\nPackage: t\nArchitecture: any\nDescription: x\n y\n"
|
||||
))
|
||||
.unwrap()
|
||||
};
|
||||
|
||||
// foo is only installed for the build architecture, like a native
|
||||
// toolchain package pulled in on the build machine.
|
||||
std::fs::write(
|
||||
admindir.join("status"),
|
||||
"\
|
||||
Package: foo
|
||||
Status: install ok installed
|
||||
Version: 1.0
|
||||
Architecture: amd64
|
||||
",
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// `:native` resolves against the BUILD architecture: satisfied even
|
||||
// though the host architecture is armhf.
|
||||
let report = check_build_depends(&control_for("foo:native"), &opts).unwrap();
|
||||
assert!(report.is_ok());
|
||||
|
||||
// Bracketed architecture restrictions keep evaluating against the
|
||||
// HOST architecture: the amd64 instance cannot satisfy `foo [armhf]`.
|
||||
// (The applied restriction reduces away, per dpkg's reduce_arch.)
|
||||
let report = check_build_depends(&control_for("foo [armhf]"), &opts).unwrap();
|
||||
assert_eq!(report.message(), "unmet build dependencies: foo");
|
||||
|
||||
// Now foo is only installed for the host architecture.
|
||||
std::fs::write(
|
||||
admindir.join("status"),
|
||||
"\
|
||||
Package: foo
|
||||
Status: install ok installed
|
||||
Version: 1.0
|
||||
Architecture: armhf
|
||||
",
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// `:native` no longer matches: no amd64 instance is installed.
|
||||
let report = check_build_depends(&control_for("foo:native"), &opts).unwrap();
|
||||
assert_eq!(report.message(), "unmet build dependencies: foo:native");
|
||||
|
||||
// The host-arch restriction matches the armhf instance.
|
||||
let report = check_build_depends(&control_for("foo [armhf]"), &opts).unwrap();
|
||||
assert!(report.is_ok());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user