Skip to content

Commit 333ed43

Browse files
authored
misc: dynamic linking code refactor (#141)
1 parent fff75b4 commit 333ed43

File tree

1 file changed

+53
-52
lines changed

1 file changed

+53
-52
lines changed

build.rs

Lines changed: 53 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,31 @@ impl callbacks::ParseCallbacks for FilterCargoCallbacks {
187187
}
188188
}
189189

190+
#[derive(Clone, Copy)]
191+
enum FFmpegLinkMode {
192+
Static,
193+
Dynamic,
194+
}
195+
196+
impl From<String> for FFmpegLinkMode {
197+
fn from(value: String) -> Self {
198+
match &*value {
199+
"static" => FFmpegLinkMode::Static,
200+
"dynamic" => FFmpegLinkMode::Dynamic,
201+
_ => panic!("Invalid FFMPEG_LINK_MODE value, expected [static,dynamic]"),
202+
}
203+
}
204+
}
205+
206+
impl std::fmt::Display for FFmpegLinkMode {
207+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
208+
match self {
209+
FFmpegLinkMode::Static => write!(f, "static"),
210+
FFmpegLinkMode::Dynamic => write!(f, "dylib"),
211+
}
212+
}
213+
}
214+
190215
fn use_prebuilt_binding(from: &Path, to: &Path) {
191216
fs::copy(from, to).expect("Prebuilt binding file failed to be copied.");
192217
}
@@ -242,31 +267,24 @@ fn generate_bindings(ffmpeg_include_dir: &Path, headers: &[PathBuf]) -> Bindings
242267
.expect("Binding generation failed.")
243268
}
244269

245-
fn linking_with_libs_dir(library_names: &[&str], ffmpeg_libs_dir: &Path, mode: FfmpegLinkMode) {
270+
fn linking_with_libs_dir(library_names: &[&str], ffmpeg_libs_dir: &Path, mode: FFmpegLinkMode) {
246271
println!("cargo:rustc-link-search=native={ffmpeg_libs_dir}");
247272
for library_name in library_names {
248-
println!(
249-
"cargo:rustc-link-lib={}={library_name}",
250-
match mode {
251-
FfmpegLinkMode::Dynamic => "dylib",
252-
FfmpegLinkMode::Static => "static",
253-
}
254-
);
273+
println!("cargo:rustc-link-lib={mode}={library_name}");
255274
}
256275
}
257276

258-
#[derive(Clone, Copy)]
259-
enum FfmpegLinkMode {
260-
Static,
261-
Dynamic,
277+
fn linking_with_single_lib(library_name: &str, ffmpeg_lib_dir: &Path, mode: FFmpegLinkMode) {
278+
println!("cargo:rustc-link-search=native={ffmpeg_lib_dir}");
279+
println!("cargo:rustc-link-lib={mode}={library_name}");
262280
}
263281

264282
#[allow(dead_code)]
265283
pub struct EnvVars {
266284
docs_rs: Option<String>,
267285
out_dir: Option<PathBuf>,
268286
ffmpeg_include_dir: Option<PathBuf>,
269-
ffmpeg_link_mode: Option<FfmpegLinkMode>,
287+
ffmpeg_link_mode: Option<FFmpegLinkMode>,
270288
ffmpeg_dll_path: Option<PathBuf>,
271289
ffmpeg_pkg_config_path: Option<PathBuf>,
272290
ffmpeg_libs_dir: Option<PathBuf>,
@@ -291,12 +309,7 @@ impl EnvVars {
291309
ffmpeg_pkg_config_path: env::var("FFMPEG_PKG_CONFIG_PATH").ok().map(remove_verbatim),
292310
ffmpeg_libs_dir: env::var("FFMPEG_LIBS_DIR").ok().map(remove_verbatim),
293311
ffmpeg_binding_path: env::var("FFMPEG_BINDING_PATH").ok().map(remove_verbatim),
294-
ffmpeg_link_mode: match env::var("FFMPEG_LINK_MODE").ok().as_deref() {
295-
Some("static") => Some(FfmpegLinkMode::Static),
296-
Some("dynamic") => Some(FfmpegLinkMode::Dynamic),
297-
Some(r) => panic!("invalid FFMPEG_LINK_MODE value {r}, expected [static,dynamic]"),
298-
None => None,
299-
},
312+
ffmpeg_link_mode: env::var("FFMPEG_LINK_MODE").ok().map(Into::into),
300313
}
301314
}
302315
}
@@ -379,41 +392,29 @@ mod vcpkg_linking {
379392
}
380393
}
381394

382-
fn dynamic_linking(mut env_vars: EnvVars) {
395+
fn dynamic_linking(env_vars: EnvVars) {
383396
let ffmpeg_dll_path = env_vars.ffmpeg_dll_path.as_ref().unwrap();
384397
if ffmpeg_dll_path.is_dir() {
385-
if env_vars.ffmpeg_libs_dir.is_none() {
386-
env_vars.ffmpeg_libs_dir = Some(ffmpeg_dll_path.clone());
387-
}
388-
if env_vars.ffmpeg_link_mode.is_none() {
389-
env_vars.ffmpeg_link_mode = Some(FfmpegLinkMode::Dynamic);
390-
}
391-
392-
return linking(env_vars);
398+
linking_with_libs_dir(&*LIBS, ffmpeg_dll_path, FFmpegLinkMode::Dynamic);
399+
} else {
400+
let (lib_name, ffmpeg_dll_dir) = (
401+
ffmpeg_dll_path
402+
.file_stem()
403+
.map(|stem| {
404+
if cfg!(target_os = "windows") {
405+
stem
406+
} else {
407+
stem.trim_start_matches("lib")
408+
}
409+
})
410+
.unwrap()
411+
.to_string(),
412+
ffmpeg_dll_path.parent().unwrap().to_path_buf(),
413+
);
414+
linking_with_single_lib(&lib_name, &ffmpeg_dll_dir, FFmpegLinkMode::Dynamic);
393415
}
394416

395417
let output_binding_path = &env_vars.out_dir.as_ref().unwrap().join("binding.rs");
396-
397-
// Extract dll name and the dir the dll is in.
398-
let (ffmpeg_dll_name, ffmpeg_dll_dir) = {
399-
let mut ffmpeg_dll_path = PathBuf::from(ffmpeg_dll_path);
400-
// Without extension.
401-
let ffmpeg_dll_filename = ffmpeg_dll_path.file_stem().unwrap();
402-
let ffmpeg_dll_name = if cfg!(target_os = "windows") {
403-
ffmpeg_dll_filename
404-
} else {
405-
ffmpeg_dll_filename.trim_start_matches("lib")
406-
}
407-
.to_string();
408-
// Remove file name.
409-
ffmpeg_dll_path.pop();
410-
let ffmpeg_dll_path = ffmpeg_dll_path.to_string();
411-
(ffmpeg_dll_name, ffmpeg_dll_path)
412-
};
413-
414-
println!("cargo:rustc-link-lib=dylib={}", ffmpeg_dll_name);
415-
println!("cargo:rustc-link-search=native={}", ffmpeg_dll_dir);
416-
417418
if let Some(ffmpeg_binding_path) = env_vars.ffmpeg_binding_path.as_ref() {
418419
use_prebuilt_binding(ffmpeg_binding_path, output_binding_path);
419420
} else if let Some(ffmpeg_include_dir) = env_vars.ffmpeg_include_dir.as_ref() {
@@ -466,7 +467,7 @@ fn linking(env_vars: EnvVars) {
466467
linking_with_libs_dir(
467468
&*LIBS,
468469
ffmpeg_libs_dir,
469-
env_vars.ffmpeg_link_mode.unwrap_or(FfmpegLinkMode::Static),
470+
env_vars.ffmpeg_link_mode.unwrap_or(FFmpegLinkMode::Static),
470471
);
471472
if let Some(ffmpeg_binding_path) = env_vars.ffmpeg_binding_path.as_ref() {
472473
use_prebuilt_binding(ffmpeg_binding_path, output_binding_path);
@@ -528,7 +529,7 @@ Enable `link_vcpkg_ffmpeg` feature if you want to link ffmpeg libraries installe
528529
linking_with_libs_dir(
529530
&*LIBS,
530531
ffmpeg_libs_dir,
531-
env_vars.ffmpeg_link_mode.unwrap_or(FfmpegLinkMode::Static),
532+
env_vars.ffmpeg_link_mode.unwrap_or(FFmpegLinkMode::Static),
532533
);
533534
if let Some(ffmpeg_binding_path) = env_vars.ffmpeg_binding_path.as_ref() {
534535
use_prebuilt_binding(ffmpeg_binding_path, output_binding_path);
@@ -574,7 +575,7 @@ fn main() {
574575
} else if env_vars.ffmpeg_dll_path.is_some() {
575576
dynamic_linking(env_vars);
576577
} else {
577-
// fallback to static linking
578+
// fallback to normal linking
578579
linking(env_vars);
579580
}
580581
}

0 commit comments

Comments
 (0)