fast_shlibdeps/
lib.rs

1pub mod dpkg;
2pub mod elf;
3pub mod search;
4
5use std::collections::HashSet;
6
7use anyhow::Result;
8
9use crate::{
10    dpkg::{find_packages_for_paths, get_package_versions},
11    elf::get_file_dependencies,
12    search::get_ld_cache,
13};
14
15/// Analyze shared library dependencies for the given files and return formatted dependency strings
16pub fn analyze_dependencies(
17    paths: impl Iterator<Item = impl AsRef<std::path::Path>>,
18) -> Result<Vec<String>> {
19    let mut libraries = HashSet::new();
20
21    for path in paths {
22        let deps = get_file_dependencies(path.as_ref())?;
23        libraries.extend(deps);
24    }
25
26    let ld_cache = get_ld_cache()?;
27    let library_paths = libraries
28        .iter()
29        .flat_map(|l| ld_cache.get(l))
30        .map(|s| s.as_str())
31        .collect::<HashSet<&str>>();
32
33    let path_to_package = find_packages_for_paths(library_paths.iter())?;
34    let packages: HashSet<&str> = library_paths
35        .iter()
36        .filter_map(|path| path_to_package.get(*path))
37        .map(|s| s.as_str())
38        .collect();
39
40    let package_versions = get_package_versions(packages.iter())?;
41    let deps = packages
42        .iter()
43        .map(|p| {
44            if let Some(version) = package_versions.get(*p) {
45                format!("{p} (>={version})")
46            } else {
47                p.to_string()
48            }
49        })
50        .collect::<Vec<String>>();
51
52    Ok(deps)
53}
54
55/// Get the formatted dependency string for the given paths
56pub fn get_dependency_string(
57    paths: impl Iterator<Item = impl AsRef<std::path::Path>>,
58) -> Result<String> {
59    let deps = analyze_dependencies(paths)?;
60    Ok(deps.join(", "))
61}