use std::path::PathBuf;
use std::process::Command;
use crate::{LinkResult, Linker, OsStr, OsString};
pub struct GenLink<L> {
linker: L,
output: OsString,
command: Command,
}
impl<L: Linker> GenLink<L> {
pub fn new(linker: L) -> Self {
let mut command = Command::new(linker.name());
let output = linker.default_output().into();
linker.preproc(&mut command);
Self {
linker,
output,
command,
}
}
pub fn output<T: Into<OsString>>(&mut self, path: T) -> &mut Self {
self.output = path.into();
self
}
pub fn obj<T: AsRef<OsStr>>(&mut self, path: T) -> LinkResult<&mut Self> {
let path = std::fs::canonicalize(path.as_ref())?;
self.linker.obj(&mut self.command, path.as_os_str());
Ok(self)
}
pub fn objs<T, TS>(&mut self, paths: TS) -> LinkResult<&mut Self>
where
T: AsRef<OsStr>,
TS: IntoIterator<Item = T>,
{
for path in paths {
self.obj(path)?;
}
Ok(self)
}
pub fn lib<T: AsRef<OsStr>>(&mut self, path: T) -> &mut Self {
self.linker.lib(&mut self.command, path.as_ref());
self
}
pub fn libs<T, TS>(&mut self, paths: TS) -> &mut Self
where
T: AsRef<OsStr>,
TS: IntoIterator<Item = T>,
{
for path in paths {
self.lib(path);
}
self
}
pub fn path<T: AsRef<OsStr>>(&mut self, path: T) -> &mut Self {
self.linker.path(&mut self.command, path.as_ref());
self
}
pub fn paths<T, TS>(&mut self, paths: TS) -> &mut Self
where
T: AsRef<OsStr>,
TS: IntoIterator<Item = T>,
{
for path in paths {
self.path(path);
}
self
}
pub fn link(&mut self) -> LinkResult<PathBuf> {
let dest = std::fs::canonicalize(&self.output)?;
self.linker.output(&mut self.command, dest.as_os_str());
let output = self.command.output()?;
if output.status.success() {
Ok(dest)
} else {
Err(output.into())
}
}
}