-
Notifications
You must be signed in to change notification settings - Fork 50
depends = "$auto" shouldn't recursively add dependencies #170
Comments
Interesting! Would you be able to implement this? There's also a request for better debug info. So maybe it'd be worth adding elf parser in Rust to handle all of this properly, without needing to spawn shell tools. |
Alright, I have had a look at fn extract_needed_libs<P: AsRef<std::path::Path>>(
binary_path: P,
) -> Result<std::collections::HashSet<String>, Box<dyn std::error::Error>> {
use xmas_elf::{
dynamic::Tag,
header,
sections::{sanity_check, SectionData, ShType},
ElfFile,
};
let mut libs = std::collections::HashSet::new();
// read binary to memory
use std::fs::File;
use std::io::Read;
let mut f = File::open(binary_path)?;
let mut buf = Vec::new();
assert!(f.read_to_end(&mut buf)? > 0);
let elf_file = ElfFile::new(&buf)?;
header::sanity_check(&elf_file)?;
let mut sect_iter = elf_file.section_iter();
// Skip the first (dummy) section
sect_iter.next();
// iterate over sections
for sect in sect_iter {
// skip things we do not care about
if sect.get_type() != Ok(ShType::Dynamic) {
continue;
}
sanity_check(sect, &elf_file)?;
// find entries for needed dynamic libs
if let Ok(SectionData::Dynamic64(dyns)) = sect.get_data(&elf_file) {
for d in dyns.iter() {
if let Ok(Tag::Needed) = d.get_tag() {
// lookup the string containing the name of the library
libs.insert(elf_file.get_dyn_string(d.get_val()? as u32)?.to_string());
}
}
}
// same procedure for 32bit
else if let Ok(SectionData::Dynamic32(dyns)) = sect.get_data(&elf_file) {
for d in dyns.iter() {
if let Ok(Tag::Needed) = d.get_tag() {
libs.insert(elf_file.get_dyn_string(d.get_val()? as u32)?.to_string());
}
}
}
}
Ok(libs)
} Something to note is that the libraries returned are just their names and not the resolved paths pointing to the actual location of these libraries on the system. So calling |
I just found an even better solution, there is: https://manpages.debian.org/testing/dpkg-dev/dpkg-shlibdeps.1.en.html which handles this correctly. |
Hey @H-M-H - would you mind elaborating on how to use the |
Automatic dependency detection, while useful to get started, sometimes pulls unnecessary transitive dependencies that sometimes impose too strict requirements on implementation details that may change unexpectedly. Let's curate the list of dependencies that cargo-deb generates so everything works as it should. This also fixes dependencies of cross compiled binaries not being detected correctly, probably because cargo-deb didn't know where to find the ldd binary of the cross-compilation toolchain. Related issue: mmstick/cargo-deb#170
|
Indeed, that Debian package path structure was confusing me, and I didn't have the time to read loads of documentation or source code to find out. Thanks. |
As of now not only direct dependencies are added but also dependencies of dependencies and so on. Consider the following example:
One of the direct dependencies is
libgobject-2.0.so.0
, which in turn depends directly on eitherlibffi.so.7
orlibffi.so.6
, depending on the system I build my binary with. Butlibffi
is not a direct dependency of my binary. That means my binary runs fine no matter iflibffi.so.7
orlibffi.so.6
is installed (as long aslibgobject
is available).So cargo-deb places some unnecessary constraints that reduce compatibility across distributions/versions. In my specific case a program that I built on Debian Stretch can not be installed on Ubuntu Focal because Ubuntu switched from
libffi.so.6
tolibffi.so.7
and the former is not available anymore (and not needed aslibgobject
points to the latter).The cause is that
ldd
is used to gather information on dependencies:cargo-deb/src/dependencies.rs
Line 11 in ac4b338
But
ldd
always resolves direct and indirect dependencies, that's why I propose to replaceldd
with something likeobjdump -p
orreadelf -d
.The text was updated successfully, but these errors were encountered: