1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
use log::*; use std::ffi::OsString; use std::path::PathBuf; fn find_it_in(to_find: &str, path: PathBuf) -> Option<PathBuf> { debug!("Searching {:?} for {}", path, to_find); if path.is_dir() { match path.read_dir() { Ok(read_dir) => { let mut i = read_dir.into_iter(); while let Some(Ok(entry)) = i.next() { if let Some(f) = find_it_in(to_find, entry.path()) { return Some(f); } } } Err(e) => { warn!("Could not search for {} in {:?}: {:?}", to_find, path, e); } } } else if path.is_file() { if let Some(os_str) = path.file_name() { if os_str == to_find { return Some(path); } } } None } fn find_it(path: OsString, to_find: &str) -> Option<PathBuf> { std::env::split_paths(&path) .filter_map(|dir| find_it_in(to_find, dir)) .next() } fn locate_header_from_package( path: OsString, header_name: &str, package: Package, ) -> Option<PathBuf> { debug!( "Checking package {} @ {} for {}", package.name, package.version, header_name ); if let Ok(library) = pkg_config::Config::new() .atleast_version(&package.version) .probe(&package.name) { for include_path in library.include_paths { if let Some(f) = find_it_in(header_name, include_path) { return Some(f); } } } debug!("Could not find package, checking path"); if let Some(f) = find_it(path, header_name) { return Some(f); } None } pub struct Package { pub version: String, pub name: String, } pub fn locate_header(header_name: &str, package: Option<Package>) -> Option<PathBuf> { let path = std::env::var_os("PATH").expect("No path defined"); debug!("Locating header using path {:?}", path); locate_header_with_path(path, header_name, package) } pub fn locate_header_with_path( path: OsString, header_name: &str, package: Option<Package>, ) -> Option<PathBuf> { if let Some(p) = package { return locate_header_from_package(path, header_name, p); } else { return find_it(path, header_name); } } #[cfg(test)] mod tests { use super::*; #[test] fn locate_resource_header() { let _ = env_logger::try_init(); let cargo_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")); assert!(locate_header_with_path(cargo_dir.into_os_string(), "to_find.h", None).is_some()); } }