Skip to content

Commit f9dead6

Browse files
committed
feat: support build and link dynamic library
1 parent f9e4a70 commit f9dead6

File tree

1 file changed

+34
-13
lines changed

1 file changed

+34
-13
lines changed

src/lib.rs

+34-13
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,7 @@ pub struct Build {
333333
build_cache: Arc<BuildCache>,
334334
inherit_rustflags: bool,
335335
link_shared_flag: bool,
336+
shared_lib_out_dir: Option<Arc<Path>>,
336337
}
337338

338339
/// Represents the types of errors that may occur while using cc-rs.
@@ -461,6 +462,7 @@ impl Build {
461462
build_cache: Arc::default(),
462463
inherit_rustflags: true,
463464
link_shared_flag: false,
465+
shared_lib_out_dir: None,
464466
}
465467
}
466468

@@ -1237,6 +1239,14 @@ impl Build {
12371239
self
12381240
}
12391241

1242+
/// Configures the output directory where shared library will be located.
1243+
///
1244+
/// This option is automatically scraped from the `OUT_DIR` environment variable by build scripts
1245+
pub fn shared_lib_out_dir<P: AsRef<Path>>(&mut self, out_dir: P) -> &mut Build {
1246+
self.shared_lib_out_dir = Some(out_dir.as_ref().into());
1247+
self
1248+
}
1249+
12401250
#[doc(hidden)]
12411251
pub fn __set_env<A, B>(&mut self, a: A, b: B) -> &mut Build
12421252
where
@@ -1390,16 +1400,26 @@ impl Build {
13901400
Ok(is_supported)
13911401
}
13921402

1393-
fn get_canonical_library_names(name: &str) -> (&str, String, String) {
1394-
let lib_striped = name.strip_prefix("lib").unwrap_or(name);
1403+
/// Get canonical library names for `output`
1404+
fn get_canonical_library_names<'a>(
1405+
&self,
1406+
output: &'a str,
1407+
) -> Result<(&'a str, String, String), Error> {
1408+
let lib_striped = output.strip_prefix("lib").unwrap_or(output);
13951409
let static_striped = lib_striped.strip_suffix(".a").unwrap_or(lib_striped);
1396-
let lib_name = lib_striped.strip_suffix(".so").unwrap_or(static_striped);
13971410

1398-
(
1411+
let dyn_ext = if self.get_target()?.env == "msvc" {
1412+
".dll"
1413+
} else {
1414+
".so"
1415+
};
1416+
let lib_name = lib_striped.strip_suffix(dyn_ext).unwrap_or(static_striped);
1417+
1418+
Ok((
13991419
lib_name,
14001420
format!("lib{lib_name}.a"),
1401-
format!("lib{lib_name}.so"),
1402-
)
1421+
format!("lib{lib_name}{dyn_ext}"),
1422+
))
14031423
}
14041424

14051425
/// Run the compiler, generating the file `output`
@@ -1418,7 +1438,7 @@ impl Build {
14181438
}
14191439
}
14201440

1421-
let (lib_name, static_name, dynlib_name) = Self::get_canonical_library_names(output);
1441+
let (lib_name, static_name, dynlib_name) = self.get_canonical_library_names(output)?;
14221442
let dst = self.get_out_dir()?;
14231443

14241444
let objects = objects_from_files(&self.files, &dst)?;
@@ -1428,12 +1448,13 @@ impl Build {
14281448
if self.link_shared_flag {
14291449
let objects = objects.iter().map(|o| o.dst.clone()).collect::<Vec<_>>();
14301450

1431-
let mut command = self.try_get_compiler()?.to_command();
1432-
let cmd = command
1433-
.args(["-shared", "-o"])
1434-
.arg(dst.join(dynlib_name))
1435-
.args(&objects);
1436-
run(cmd, &self.cargo_output)?;
1451+
let mut cmd = self.try_get_compiler()?.to_command();
1452+
let dynlib_path = dst.join(&dynlib_name);
1453+
cmd.args(["-shared", "-o"]).arg(&dynlib_path).args(&objects);
1454+
run(&mut cmd, &self.cargo_output)?;
1455+
if let Some(out_dir) = &self.shared_lib_out_dir {
1456+
fs::copy(dynlib_path, out_dir.join(&dynlib_name))?;
1457+
}
14371458
} else {
14381459
self.assemble(lib_name, &dst.join(static_name), &objects)?;
14391460
}

0 commit comments

Comments
 (0)