Skip to content

Commit e8d9c28

Browse files
committed
try setup dynamic linking
1 parent bdabfd9 commit e8d9c28

1 file changed

Lines changed: 40 additions & 14 deletions

File tree

build.rs

Lines changed: 40 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -242,18 +242,28 @@ fn generate_bindings(ffmpeg_include_dir: &Path, headers: &[PathBuf]) -> Bindings
242242
.expect("Binding generation failed.")
243243
}
244244

245-
fn static_linking_with_libs_dir(library_names: &[&str], ffmpeg_libs_dir: &Path) {
245+
fn linking_with_libs_dir(library_names: &[&str], ffmpeg_libs_dir: &Path, mode: FfmpegLinkMode) {
246246
println!("cargo:rustc-link-search=native={}", ffmpeg_libs_dir);
247247
for library_name in library_names {
248-
println!("cargo:rustc-link-lib=static={}", library_name);
248+
println!("cargo:rustc-link-lib={}={}", library_name, match mode {
249+
FfmpegLinkMode::Dynamic => "dylib",
250+
FfmpegLinkMode::Static => "static",
251+
});
249252
}
250253
}
251254

255+
#[derive(Clone, Copy)]
256+
enum FfmpegLinkMode {
257+
Static,
258+
Dynamic,
259+
}
260+
252261
#[allow(dead_code)]
253262
pub struct EnvVars {
254263
docs_rs: Option<String>,
255264
out_dir: Option<PathBuf>,
256265
ffmpeg_include_dir: Option<PathBuf>,
266+
ffmpeg_link_mode: Option<FfmpegLinkMode>,
257267
ffmpeg_dll_path: Option<PathBuf>,
258268
ffmpeg_pkg_config_path: Option<PathBuf>,
259269
ffmpeg_libs_dir: Option<PathBuf>,
@@ -277,6 +287,12 @@ impl EnvVars {
277287
ffmpeg_pkg_config_path: env::var("FFMPEG_PKG_CONFIG_PATH").ok().map(remove_verbatim),
278288
ffmpeg_libs_dir: env::var("FFMPEG_LIBS_DIR").ok().map(remove_verbatim),
279289
ffmpeg_binding_path: env::var("FFMPEG_BINDING_PATH").ok().map(remove_verbatim),
290+
ffmpeg_link_mode: match env::var("FFMPEG_LINK_MODE").ok().as_deref() {
291+
Some("static") => Some(FfmpegLinkMode::Static),
292+
Some("dynamic") => Some(FfmpegLinkMode::Dynamic),
293+
Some(r) => panic!("invalid FFMPEG_LINK_MODE value {r}, expected [static,dynamic]"),
294+
None => None,
295+
}
280296
}
281297
}
282298
}
@@ -359,8 +375,18 @@ mod vcpkg_linking {
359375
}
360376
}
361377

362-
fn dynamic_linking(env_vars: &EnvVars) {
378+
fn dynamic_linking(mut env_vars: EnvVars) {
363379
let ffmpeg_dll_path = env_vars.ffmpeg_dll_path.as_ref().unwrap();
380+
if ffmpeg_dll_path.is_dir() {
381+
if env_vars.ffmpeg_libs_dir.is_none() {
382+
env_vars.ffmpeg_libs_dir = Some(ffmpeg_dll_path.clone());
383+
}
384+
if env_vars.ffmpeg_link_mode.is_none() {
385+
env_vars.ffmpeg_link_mode = Some(FfmpegLinkMode::Dynamic);
386+
}
387+
388+
return linking(env_vars);
389+
}
364390

365391
let output_binding_path = &env_vars.out_dir.as_ref().unwrap().join("binding.rs");
366392

@@ -396,12 +422,12 @@ fn dynamic_linking(env_vars: &EnvVars) {
396422
}
397423
}
398424

399-
fn static_linking(env_vars: &EnvVars) {
425+
fn linking(env_vars: EnvVars) {
400426
let output_binding_path = &env_vars.out_dir.as_ref().unwrap().join("binding.rs");
401427

402428
#[cfg(not(target_os = "windows"))]
403429
{
404-
fn static_linking_with_pkg_config_and_bindgen(
430+
fn linking_with_pkg_config_and_bindgen(
405431
env_vars: &EnvVars,
406432
output_binding_path: &Path,
407433
) -> Result<(), pkg_config::Error> {
@@ -430,10 +456,10 @@ fn static_linking(env_vars: &EnvVars) {
430456
);
431457
}
432458
env::set_var("PKG_CONFIG_PATH", ffmpeg_pkg_config_path);
433-
static_linking_with_pkg_config_and_bindgen(env_vars, output_binding_path)
459+
linking_with_pkg_config_and_bindgen(&env_vars, output_binding_path)
434460
.expect("Static linking with pkg-config failed.");
435461
} else if let Some(ffmpeg_libs_dir) = env_vars.ffmpeg_libs_dir.as_ref() {
436-
static_linking_with_libs_dir(&*LIBS, ffmpeg_libs_dir);
462+
linking_with_libs_dir(&*LIBS, ffmpeg_libs_dir, env_vars.ffmpeg_link_mode.unwrap_or(FfmpegLinkMode::Static));
437463
if let Some(ffmpeg_binding_path) = env_vars.ffmpeg_binding_path.as_ref() {
438464
use_prebuilt_binding(ffmpeg_binding_path, output_binding_path);
439465
} else if let Some(ffmpeg_include_dir) = env_vars.ffmpeg_include_dir.as_ref() {
@@ -460,7 +486,7 @@ Enable `link_vcpkg_ffmpeg` feature if you want to link ffmpeg libraries installe
460486
#[cfg(feature = "link_system_ffmpeg")]
461487
if !success {
462488
if let Err(e) =
463-
static_linking_with_pkg_config_and_bindgen(env_vars, output_binding_path)
489+
linking_with_pkg_config_and_bindgen(env_vars, output_binding_path)
464490
{
465491
error.push('\n');
466492
error.push_str(&format!("Link system FFmpeg failed: {:?}", e));
@@ -490,7 +516,7 @@ Enable `link_vcpkg_ffmpeg` feature if you want to link ffmpeg libraries installe
490516
#[cfg(target_os = "windows")]
491517
{
492518
if let Some(ffmpeg_libs_dir) = env_vars.ffmpeg_libs_dir.as_ref() {
493-
static_linking_with_libs_dir(&*LIBS, ffmpeg_libs_dir);
519+
linking_with_libs_dir(&*LIBS, ffmpeg_libs_dir, env_vars.ffmpeg_link_mode);
494520
if let Some(ffmpeg_binding_path) = env_vars.ffmpeg_binding_path.as_ref() {
495521
use_prebuilt_binding(ffmpeg_binding_path, output_binding_path);
496522
} else if let Some(ffmpeg_include_dir) = env_vars.ffmpeg_include_dir.as_ref() {
@@ -502,7 +528,7 @@ Enable `link_vcpkg_ffmpeg` feature if you want to link ffmpeg libraries installe
502528
}
503529
} else {
504530
#[cfg(feature = "link_vcpkg_ffmpeg")]
505-
vcpkg_linking::linking_with_vcpkg_and_bindgen(env_vars, output_binding_path)
531+
vcpkg_linking::linking_with_vcpkg_and_bindgen(&zenv_vars, output_binding_path)
506532
.expect("Linking FFmpeg with vcpkg failed.");
507533
#[cfg(not(feature = "link_vcpkg_ffmpeg"))]
508534
panic!(
@@ -516,7 +542,7 @@ Enable `link_vcpkg_ffmpeg` feature if you want to link ffmpeg provided by vcpkg.
516542
}
517543
}
518544

519-
fn docs_rs_linking(env_vars: &EnvVars) {
545+
fn docs_rs_linking(env_vars: EnvVars) {
520546
// If it's a documentation generation from docs.rs, just copy the bindings
521547
// generated locally to `OUT_DIR`. We do this because the building
522548
// environment of docs.rs doesn't have an network connection, so we cannot
@@ -531,11 +557,11 @@ fn docs_rs_linking(env_vars: &EnvVars) {
531557
fn main() {
532558
let env_vars = EnvVars::init();
533559
if env_vars.docs_rs.is_some() {
534-
docs_rs_linking(&env_vars);
560+
docs_rs_linking(env_vars);
535561
} else if env_vars.ffmpeg_dll_path.is_some() {
536-
dynamic_linking(&env_vars);
562+
dynamic_linking(env_vars);
537563
} else {
538564
// fallback to static linking
539-
static_linking(&env_vars);
565+
linking(env_vars);
540566
}
541567
}

0 commit comments

Comments
 (0)