1use std::{env, ffi::OsStr, path::PathBuf};
2
3pub fn ffmpeg_include_dirs(env_metadata: bool) -> Vec<PathBuf> {
9 if let Some(dir) = path_from_env("FFMPEG_INCLUDE_DIR", env_metadata) {
10 if dir.is_dir() {
11 return vec![dir];
12 }
13 }
14
15 let lib = find_ffmpeg_lib()
16 .expect("Unable to find FFmpeg include dir. You can specify it explicitly by setting the FFMPEG_INCLUDE_DIR environment variable.");
17
18 lib.include_paths
19}
20
21pub fn ffmpeg_lib_dirs(env_metadata: bool) -> Vec<PathBuf> {
27 if let Some(dir) = path_from_env("FFMPEG_LIB_DIR", env_metadata) {
28 if dir.is_dir() {
29 return vec![dir];
30 }
31 }
32
33 let lib = find_ffmpeg_lib()
34 .expect("Unable to find FFmpeg lib dir. You can specify it explicitly by setting the FFMPEG_LIB_DIR environment variable.");
35
36 lib.link_paths
37}
38
39cfg_if::cfg_if! {
40 if #[cfg(any(target_os = "linux", target_os = "macos"))] {
41 use pkg_config::{Config, Library};
42
43 fn find_ffmpeg_lib() -> Option<Library> {
45 Config::new()
46 .cargo_metadata(false)
47 .probe("libavcodec")
48 .ok()
49 }
50 } else if #[cfg(target_os = "windows")] {
51 use vcpkg::{Config, Library};
52
53 fn find_ffmpeg_lib() -> Option<Library> {
55 Config::new()
56 .cargo_metadata(false)
57 .find_package("ffmpeg")
58 .ok()
59 }
60 } else {
61 struct Library {
63 include_paths: Vec<PathBuf>,
64 link_paths: Vec<PathBuf>,
65 }
66
67 fn find_ffmpeg_lib() -> Option<Library> {
69 None
70 }
71 }
72}
73
74fn path_from_env(name: &str, env_metadata: bool) -> Option<PathBuf> {
76 let target = normalized_target();
77
78 if env_metadata {
79 emit_env_metadata(name, target.as_deref());
80 }
81
82 if let Some(target) = target {
83 if let Some(path) = path_from_var(format!("{name}_{target}")) {
84 return Some(path);
85 }
86 }
87
88 if let Some(path) = path_from_var(name) {
89 return Some(path);
90 }
91
92 None
93}
94
95fn path_from_var<K>(key: K) -> Option<PathBuf>
97where
98 K: AsRef<OsStr>,
99{
100 Some(PathBuf::from(env::var_os(key)?))
101}
102
103fn emit_env_metadata(name: &str, target: Option<&str>) {
106 if let Some(target) = target {
107 println!("cargo:rerun-if-env-changed={name}_{target}");
108 }
109
110 println!("cargo:rerun-if-env-changed={name}");
111}
112
113fn normalized_target() -> Option<String> {
115 let target = env::var("TARGET").ok()?.to_uppercase().replace('-', "_");
116
117 Some(target)
118}