diff --git a/data/quirks.yml b/data/quirks.yml index 6c989e9..4d94273 100644 --- a/data/quirks.yml +++ b/data/quirks.yml @@ -15,18 +15,38 @@ quirks: # against the host architecture, whose dependency closure conflicts with # the `:native` python3. Resolve it against the build architecture # until the control is fixed upstream. + # The resolute and stonking kernels declare the host-tool libraries + # unqualified (libelf-dev for resolve_btfids, libdw-dev for + # gendwarfksyms, libssl-dev for sign-file), unlike the Debian control, + # which carries the same names qualified `:native`. The dpkg cross + # rules resolve an unqualified Multi-Arch: same name against the host + # architecture only, so a cross build installs no build-architecture + # variants and the kernel's host-side tools cannot link. Inject the + # build-architecture variants until the control is fixed upstream. linux: deb: - series: [resolute] dependencies: replace: llvm-21-dev: llvm-21-dev:native + - series: [resolute, stonking] + dependencies: + inject: + - libelf-dev:native + - libdw-dev:native + - libssl-dev:native linux-riscv: deb: - series: [resolute] dependencies: replace: llvm-21-dev: llvm-21-dev:native + - series: [resolute, stonking] + dependencies: + inject: + - libelf-dev:native + - libdw-dev:native + - libssl-dev:native # Add more packages and their quirks as needed # example-package: diff --git a/src/quirks.rs b/src/quirks.rs index 769d162..36e0039 100644 --- a/src/quirks.rs +++ b/src/quirks.rs @@ -265,15 +265,62 @@ mod tests { fn linux_dependency_quirks_are_series_scoped() { for package in ["linux", "linux-riscv"] { let rules = get_deb_dependency_quirks(package, "resolute"); - assert_eq!(rules.len(), 1, "the resolute entry applies"); + assert_eq!(rules.len(), 2, "the resolute entries apply"); assert_eq!( rules[0].replace.get("llvm-21-dev").map(String::as_str), Some("llvm-21-dev:native ") ); + // Only the stonking entry exists there: the llvm-21-dev + // replacement above is a resolute-only packaging state. + let rules = get_deb_dependency_quirks(package, "stonking"); + assert_eq!(rules.len(), 1); + assert!(rules[0].replace.is_empty()); assert!(get_deb_dependency_quirks(package, "noble").is_empty()); } } + /// The kernels of the series whose control dropped the Debian-style + /// `:native` qualifiers on the host-tool libraries inject the + /// build-architecture variants: the dpkg cross rules resolve the + /// unqualified Multi-Arch: same names against the host architecture + /// only, leaving nothing for the kernel's host-side tools to link. + #[test] + fn linux_injects_native_host_tool_libraries_for_cross() { + for series in ["resolute", "stonking"] { + let mut clauses = vec![vec![parse("libelf-dev ")]]; + crate::quirks::apply_dependency_quirks("linux", series, &mut clauses, &opts()).unwrap(); + let injected: Vec<&PkgRelation> = clauses[1..] + .iter() + .flatten() + .filter(|rel| { + ["libelf-dev", "libdw-dev", "libssl-dev"].contains(&rel.package.as_str()) + }) + .collect(); + assert_eq!( + injected.len(), + 3, + "one :native clause per host-tool library" + ); + assert!( + injected + .iter() + .all(|rel| rel.arch_qualifier.as_deref() == Some("native")) + ); + // The declared dependency itself is untouched: the host + // (target) variant still installs for the checker. + assert_eq!(clauses[0][0].arch_qualifier, None); + } + } + + /// Other kernel series keep their declared dependencies untouched. + #[test] + fn noble_linux_dependencies_are_not_rewritten() { + let mut clauses = vec![vec![parse("libelf-dev")]]; + crate::quirks::apply_dependency_quirks("linux", "noble", &mut clauses, &opts()).unwrap(); + assert_eq!(clauses.len(), 1); + assert_eq!(clauses[0][0].arch_qualifier, None); + } + /// `replace` rewrites exactly the dependencies whose declared name /// matches, wholesale: the replacement carries its own qualifier and /// restrictions.