@@ -332,6 +332,7 @@ pub struct Build {
332332 shell_escaped_flags : Option < bool > ,
333333 build_cache : Arc < BuildCache > ,
334334 inherit_rustflags : bool ,
335+ link_shared_flag : bool ,
335336}
336337
337338/// Represents the types of errors that may occur while using cc-rs.
@@ -459,6 +460,7 @@ impl Build {
459460 shell_escaped_flags : None ,
460461 build_cache : Arc :: default ( ) ,
461462 inherit_rustflags : true ,
463+ link_shared_flag : false ,
462464 }
463465 }
464466
@@ -1227,6 +1229,14 @@ impl Build {
12271229 self
12281230 }
12291231
1232+ /// Configure whether cc should build dynamic library and link with `rustc-link-lib=dylib`
1233+ ///
1234+ /// This option defaults to `false`.
1235+ pub fn link_shared_flag ( & mut self , link_shared_flag : bool ) -> & mut Build {
1236+ self . link_shared_flag = link_shared_flag;
1237+ self
1238+ }
1239+
12301240 #[ doc( hidden) ]
12311241 pub fn __set_env < A , B > ( & mut self , a : A , b : B ) -> & mut Build
12321242 where
@@ -1380,6 +1390,22 @@ impl Build {
13801390 Ok ( is_supported)
13811391 }
13821392
1393+ fn get_canonical_library_names ( name : & str ) -> ( & str , String , String ) {
1394+ let lib_striped = name. strip_prefix ( "lib" ) . unwrap_or ( name) ;
1395+ let lib_name = if lib_striped. ends_with ( ".a" ) {
1396+ & lib_striped[ ..lib_striped. len ( ) - 2 ]
1397+ } else if lib_striped. ends_with ( ".so" ) {
1398+ & lib_striped[ ..lib_striped. len ( ) - 3 ]
1399+ } else {
1400+ lib_striped
1401+ } ;
1402+ (
1403+ lib_name,
1404+ format ! ( "lib{lib_name}.a" ) ,
1405+ format ! ( "lib{lib_name}.so" ) ,
1406+ )
1407+ }
1408+
13831409 /// Run the compiler, generating the file `output`
13841410 ///
13851411 /// This will return a result instead of panicking; see [`Self::compile()`] for
@@ -1396,21 +1422,25 @@ impl Build {
13961422 }
13971423 }
13981424
1399- let ( lib_name, gnu_lib_name) = if output. starts_with ( "lib" ) && output. ends_with ( ".a" ) {
1400- ( & output[ 3 ..output. len ( ) - 2 ] , output. to_owned ( ) )
1401- } else {
1402- let mut gnu = String :: with_capacity ( 5 + output. len ( ) ) ;
1403- gnu. push_str ( "lib" ) ;
1404- gnu. push_str ( output) ;
1405- gnu. push_str ( ".a" ) ;
1406- ( output, gnu)
1407- } ;
1425+ let ( lib_name, static_name, dynlib_name) = Self :: get_canonical_library_names ( output) ;
14081426 let dst = self . get_out_dir ( ) ?;
14091427
14101428 let objects = objects_from_files ( & self . files , & dst) ?;
14111429
14121430 self . compile_objects ( & objects) ?;
1413- self . assemble ( lib_name, & dst. join ( gnu_lib_name) , & objects) ?;
1431+
1432+ if self . link_shared_flag {
1433+ let objects = objects. iter ( ) . map ( |o| o. dst . clone ( ) ) . collect :: < Vec < _ > > ( ) ;
1434+
1435+ let mut command = self . try_get_compiler ( ) ?. to_command ( ) ;
1436+ let cmd = command
1437+ . args ( [ "-shared" , "-o" ] )
1438+ . arg ( dst. join ( dynlib_name) )
1439+ . args ( & objects) ;
1440+ run ( cmd, & self . cargo_output ) ?;
1441+ }
1442+
1443+ self . assemble ( lib_name, & dst. join ( static_name) , & objects) ?;
14141444
14151445 let target = self . get_target ( ) ?;
14161446 if target. env == "msvc" {
@@ -1435,8 +1465,13 @@ impl Build {
14351465 }
14361466
14371467 if self . link_lib_modifiers . is_empty ( ) {
1438- self . cargo_output
1439- . print_metadata ( & format_args ! ( "cargo:rustc-link-lib=static={}" , lib_name) ) ;
1468+ if self . link_shared_flag {
1469+ self . cargo_output
1470+ . print_metadata ( & format_args ! ( "cargo:rustc-link-lib=dylib={}" , lib_name) ) ;
1471+ } else {
1472+ self . cargo_output
1473+ . print_metadata ( & format_args ! ( "cargo:rustc-link-lib=static={}" , lib_name) ) ;
1474+ }
14401475 } else {
14411476 self . cargo_output . print_metadata ( & format_args ! (
14421477 "cargo:rustc-link-lib=static:{}={}" ,
0 commit comments