@@ -242,18 +242,31 @@ 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 ) {
246- println ! ( "cargo:rustc-link-search=native={}" , ffmpeg_libs_dir ) ;
245+ fn linking_with_libs_dir ( library_names : & [ & str ] , ffmpeg_libs_dir : & Path , mode : FfmpegLinkMode ) {
246+ 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 ! (
249+ "cargo:rustc-link-lib={}={library_name}" ,
250+ match mode {
251+ FfmpegLinkMode :: Dynamic => "dylib" ,
252+ FfmpegLinkMode :: Static => "static" ,
253+ }
254+ ) ;
249255 }
250256}
251257
258+ #[ derive( Clone , Copy ) ]
259+ enum FfmpegLinkMode {
260+ Static ,
261+ Dynamic ,
262+ }
263+
252264#[ allow( dead_code) ]
253265pub struct EnvVars {
254266 docs_rs : Option < String > ,
255267 out_dir : Option < PathBuf > ,
256268 ffmpeg_include_dir : Option < PathBuf > ,
269+ ffmpeg_link_mode : Option < FfmpegLinkMode > ,
257270 ffmpeg_dll_path : Option < PathBuf > ,
258271 ffmpeg_pkg_config_path : Option < PathBuf > ,
259272 ffmpeg_libs_dir : Option < PathBuf > ,
@@ -269,6 +282,7 @@ impl EnvVars {
269282 println ! ( "cargo:rerun-if-env-changed=FFMPEG_PKG_CONFIG_PATH" ) ;
270283 println ! ( "cargo:rerun-if-env-changed=FFMPEG_LIBS_DIR" ) ;
271284 println ! ( "cargo:rerun-if-env-changed=FFMPEG_BINDING_PATH" ) ;
285+ println ! ( "cargo:rerun-if-env-changed=FFMPEG_LINK_MODE" ) ;
272286 Self {
273287 docs_rs : env:: var ( "DOCS_RS" ) . ok ( ) ,
274288 out_dir : env:: var ( "OUT_DIR" ) . ok ( ) . map ( remove_verbatim) ,
@@ -277,6 +291,12 @@ impl EnvVars {
277291 ffmpeg_pkg_config_path : env:: var ( "FFMPEG_PKG_CONFIG_PATH" ) . ok ( ) . map ( remove_verbatim) ,
278292 ffmpeg_libs_dir : env:: var ( "FFMPEG_LIBS_DIR" ) . ok ( ) . map ( remove_verbatim) ,
279293 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+ } ,
280300 }
281301 }
282302}
@@ -359,8 +379,18 @@ mod vcpkg_linking {
359379 }
360380}
361381
362- fn dynamic_linking ( env_vars : & EnvVars ) {
382+ fn dynamic_linking ( mut env_vars : EnvVars ) {
363383 let ffmpeg_dll_path = env_vars. ffmpeg_dll_path . as_ref ( ) . unwrap ( ) ;
384+ 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) ;
393+ }
364394
365395 let output_binding_path = & env_vars. out_dir . as_ref ( ) . unwrap ( ) . join ( "binding.rs" ) ;
366396
@@ -396,12 +426,12 @@ fn dynamic_linking(env_vars: &EnvVars) {
396426 }
397427}
398428
399- fn static_linking ( env_vars : & EnvVars ) {
429+ fn linking ( env_vars : EnvVars ) {
400430 let output_binding_path = & env_vars. out_dir . as_ref ( ) . unwrap ( ) . join ( "binding.rs" ) ;
401431
402432 #[ cfg( not( target_os = "windows" ) ) ]
403433 {
404- fn static_linking_with_pkg_config_and_bindgen (
434+ fn linking_with_pkg_config_and_bindgen (
405435 env_vars : & EnvVars ,
406436 output_binding_path : & Path ,
407437 ) -> Result < ( ) , pkg_config:: Error > {
@@ -430,10 +460,14 @@ fn static_linking(env_vars: &EnvVars) {
430460 ) ;
431461 }
432462 env:: set_var ( "PKG_CONFIG_PATH" , ffmpeg_pkg_config_path) ;
433- static_linking_with_pkg_config_and_bindgen ( env_vars, output_binding_path)
463+ linking_with_pkg_config_and_bindgen ( & env_vars, output_binding_path)
434464 . expect ( "Static linking with pkg-config failed." ) ;
435465 } else if let Some ( ffmpeg_libs_dir) = env_vars. ffmpeg_libs_dir . as_ref ( ) {
436- static_linking_with_libs_dir ( & * LIBS , ffmpeg_libs_dir) ;
466+ linking_with_libs_dir (
467+ & * LIBS ,
468+ ffmpeg_libs_dir,
469+ env_vars. ffmpeg_link_mode . unwrap_or ( FfmpegLinkMode :: Static ) ,
470+ ) ;
437471 if let Some ( ffmpeg_binding_path) = env_vars. ffmpeg_binding_path . as_ref ( ) {
438472 use_prebuilt_binding ( ffmpeg_binding_path, output_binding_path) ;
439473 } else if let Some ( ffmpeg_include_dir) = env_vars. ffmpeg_include_dir . as_ref ( ) {
@@ -460,7 +494,7 @@ Enable `link_vcpkg_ffmpeg` feature if you want to link ffmpeg libraries installe
460494 #[ cfg( feature = "link_system_ffmpeg" ) ]
461495 if !success {
462496 if let Err ( e) =
463- static_linking_with_pkg_config_and_bindgen ( env_vars, output_binding_path)
497+ linking_with_pkg_config_and_bindgen ( & env_vars, output_binding_path)
464498 {
465499 error. push ( '\n' ) ;
466500 error. push_str ( & format ! ( "Link system FFmpeg failed: {:?}" , e) ) ;
@@ -471,9 +505,10 @@ Enable `link_vcpkg_ffmpeg` feature if you want to link ffmpeg libraries installe
471505 }
472506 #[ cfg( feature = "link_vcpkg_ffmpeg" ) ]
473507 if !success {
474- if let Err ( e) =
475- vcpkg_linking:: linking_with_vcpkg_and_bindgen ( env_vars, output_binding_path)
476- {
508+ if let Err ( e) = vcpkg_linking:: linking_with_vcpkg_and_bindgen (
509+ & env_vars,
510+ output_binding_path,
511+ ) {
477512 error. push ( '\n' ) ;
478513 error. push_str ( & format ! ( "Link vcpkg FFmpeg failed: {:?}" , e) ) ;
479514 } else {
@@ -490,7 +525,11 @@ Enable `link_vcpkg_ffmpeg` feature if you want to link ffmpeg libraries installe
490525 #[ cfg( target_os = "windows" ) ]
491526 {
492527 if let Some ( ffmpeg_libs_dir) = env_vars. ffmpeg_libs_dir . as_ref ( ) {
493- static_linking_with_libs_dir ( & * LIBS , ffmpeg_libs_dir) ;
528+ linking_with_libs_dir (
529+ & * LIBS ,
530+ ffmpeg_libs_dir,
531+ env_vars. ffmpeg_link_mode . unwrap_or ( FfmpegLinkMode :: Static ) ,
532+ ) ;
494533 if let Some ( ffmpeg_binding_path) = env_vars. ffmpeg_binding_path . as_ref ( ) {
495534 use_prebuilt_binding ( ffmpeg_binding_path, output_binding_path) ;
496535 } else if let Some ( ffmpeg_include_dir) = env_vars. ffmpeg_include_dir . as_ref ( ) {
@@ -502,7 +541,7 @@ Enable `link_vcpkg_ffmpeg` feature if you want to link ffmpeg libraries installe
502541 }
503542 } else {
504543 #[ cfg( feature = "link_vcpkg_ffmpeg" ) ]
505- vcpkg_linking:: linking_with_vcpkg_and_bindgen ( env_vars, output_binding_path)
544+ vcpkg_linking:: linking_with_vcpkg_and_bindgen ( & env_vars, output_binding_path)
506545 . expect ( "Linking FFmpeg with vcpkg failed." ) ;
507546 #[ cfg( not( feature = "link_vcpkg_ffmpeg" ) ) ]
508547 panic ! (
@@ -516,7 +555,7 @@ Enable `link_vcpkg_ffmpeg` feature if you want to link ffmpeg provided by vcpkg.
516555 }
517556}
518557
519- fn docs_rs_linking ( env_vars : & EnvVars ) {
558+ fn docs_rs_linking ( env_vars : EnvVars ) {
520559 // If it's a documentation generation from docs.rs, just copy the bindings
521560 // generated locally to `OUT_DIR`. We do this because the building
522561 // environment of docs.rs doesn't have an network connection, so we cannot
@@ -531,11 +570,11 @@ fn docs_rs_linking(env_vars: &EnvVars) {
531570fn main ( ) {
532571 let env_vars = EnvVars :: init ( ) ;
533572 if env_vars. docs_rs . is_some ( ) {
534- docs_rs_linking ( & env_vars) ;
573+ docs_rs_linking ( env_vars) ;
535574 } else if env_vars. ffmpeg_dll_path . is_some ( ) {
536- dynamic_linking ( & env_vars) ;
575+ dynamic_linking ( env_vars) ;
537576 } else {
538577 // fallback to static linking
539- static_linking ( & env_vars) ;
578+ linking ( env_vars) ;
540579 }
541580}
0 commit comments