Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
46407375d0 | ||
|
|
ce19c5648b | ||
|
|
99c6f63cd4 | ||
|
|
4b52f8e9e9 |
@@ -6,7 +6,13 @@
|
||||
|
||||
## Installation
|
||||
|
||||
No distribution channel is published yet; build from source:
|
||||
From crates.io:
|
||||
|
||||
```
|
||||
cargo install pkh
|
||||
```
|
||||
|
||||
Or build from source (the same system packages are needed either way):
|
||||
|
||||
```
|
||||
sudo apt install pkg-config libssl-dev libgpg-error-dev libgpgme-dev
|
||||
|
||||
@@ -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 <!stage1>
|
||||
- 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 <!stage1>
|
||||
- series: [resolute, stonking]
|
||||
dependencies:
|
||||
inject:
|
||||
- libelf-dev:native
|
||||
- libdw-dev:native
|
||||
- libssl-dev:native
|
||||
|
||||
# Add more packages and their quirks as needed
|
||||
# example-package:
|
||||
|
||||
+7
-24
@@ -62,20 +62,6 @@ pub fn setup_environment(
|
||||
.map_err(|e| format!("Invalid UTF-8 in dpkg-architecture output: {e}"))?;
|
||||
parse_dpkg_architecture_output(&dpkg_architecture, env);
|
||||
|
||||
// In-tree tools locate their libraries with the *host* pkg-config during
|
||||
// cross builds (the kernel's tools/build feature checks derive their
|
||||
// cflags/ldflags from `pkg-config --cflags/--libs`), whose search path
|
||||
// only covers the build architecture's pkgconfig dirs. Point it at the
|
||||
// target's so `libtraceevent` & co resolve to target-arch libraries:
|
||||
// linux-riscv cross builds die in rtla's Makefile.config otherwise, even
|
||||
// with the target -dev packages installed.
|
||||
if let Some(multiarch) = env.get("DEB_HOST_MULTIARCH").cloned() {
|
||||
env.insert(
|
||||
"PKG_CONFIG_LIBDIR".to_string(),
|
||||
format!("/usr/lib/{multiarch}/pkgconfig:/usr/share/pkgconfig"),
|
||||
);
|
||||
}
|
||||
|
||||
env.insert("DEB_BUILD_PROFILES".to_string(), "cross".to_string());
|
||||
|
||||
Ok(())
|
||||
@@ -304,21 +290,18 @@ mod tests {
|
||||
assert!(cross_suites("noble", None, "not-a-distro").is_err());
|
||||
}
|
||||
|
||||
/// setup_environment exports the target multiarch pkg-config libdir:
|
||||
/// tools' feature checks run the *host* pkg-config, which must find the
|
||||
/// target's .pc files (rtla hard-errors on libtraceevent otherwise,
|
||||
/// failing linux-riscv cross builds despite the target -dev packages
|
||||
/// being installed).
|
||||
/// setup_environment exports the dpkg cross variables and the 'cross'
|
||||
/// build profile, and nothing beyond what dpkg-buildpackage exports:
|
||||
/// no pkg-config redirection (the environment is the package's to
|
||||
/// set, and target-arch pkgconfig paths would also poison the
|
||||
/// host-side tools of the same build).
|
||||
#[test]
|
||||
fn test_setup_environment_exports_cross_pkg_config_libdir() {
|
||||
fn test_setup_environment_exports_dpkg_cross_variables_only() {
|
||||
let mut env = HashMap::new();
|
||||
let ctx = Arc::new(Context::new(crate::context::ContextConfig::Local).unwrap());
|
||||
setup_environment(&mut env, "riscv64", ctx).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
env.get("PKG_CONFIG_LIBDIR").map(String::as_str),
|
||||
Some("/usr/lib/riscv64-linux-gnu/pkgconfig:/usr/share/pkgconfig")
|
||||
);
|
||||
assert!(!env.contains_key("PKG_CONFIG_LIBDIR"));
|
||||
assert_eq!(
|
||||
env.get("DEB_BUILD_PROFILES").map(String::as_str),
|
||||
Some("cross")
|
||||
|
||||
@@ -1154,6 +1154,39 @@ mod tests {
|
||||
assert_eq!(spec, "t:amd64");
|
||||
}
|
||||
|
||||
/// Cross parity with dpkg's checker and sbuild's apt-resolved dummy
|
||||
/// package: an unqualified Multi-Arch: same name resolves to the
|
||||
/// host-architecture variant even when a build-architecture candidate
|
||||
/// exists — the build-architecture side is only ever installed
|
||||
/// through an explicit `:native` declaration (or a pkh quirk
|
||||
/// injecting one), never alongside the host variant.
|
||||
#[test]
|
||||
fn install_spec_unqualified_same_package_never_dual_installs() {
|
||||
let host = "arm64";
|
||||
let build = "amd64";
|
||||
|
||||
let spec = install_spec_for(
|
||||
&rel("t"),
|
||||
&[cand("amd64", "same"), cand("arm64", "same")],
|
||||
build,
|
||||
host,
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(spec, "t:arm64");
|
||||
|
||||
// The build-architecture side comes from `:native` declarations:
|
||||
// the co-installable build-arch variant of the same source
|
||||
// package.
|
||||
let spec = install_spec_for(
|
||||
&rel("t:native"),
|
||||
&[cand("amd64", "same"), cand("arm64", "same")],
|
||||
build,
|
||||
host,
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(spec, "t:amd64");
|
||||
}
|
||||
|
||||
/// Qualified dependencies install exactly the variant their qualifier
|
||||
/// selects per dpkg semantics; virtual names (no candidates) pass
|
||||
/// through unqualified for apt to resolve a provider.
|
||||
|
||||
+48
-1
@@ -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 <!stage1>")
|
||||
);
|
||||
// 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 <!stage1>")]];
|
||||
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.
|
||||
|
||||
Reference in New Issue
Block a user