use std::marker::PhantomData;
use std::path::{Path, PathBuf};
use std::process::Command;
pub struct StatusSetProjectDir;
pub struct StatusSetConfigPreset;
pub struct StatusSetLibraryName;
pub struct StatusConfig;
pub struct StatusBuild;
#[derive(Debug)]
pub struct CMakePresetBuilder<S> {
output_dir: PathBuf,
project_dir: PathBuf,
config_preset: String,
library_name: String,
_phantom: PhantomData<S>,
}
impl CMakePresetBuilder<StatusSetProjectDir> {
pub fn new() -> CMakePresetBuilder<StatusSetProjectDir> {
CMakePresetBuilder {
output_dir: std::env::var("OUT_DIR")
.unwrap_or_else(|_| ".".to_string())
.into(),
project_dir: PathBuf::new(),
config_preset: "".to_string(),
library_name: "".to_string(),
_phantom: PhantomData,
}
}
pub fn set_project_dir<P: AsRef<Path>>(
self,
project_dir: P,
) -> CMakePresetBuilder<StatusSetConfigPreset> {
if !project_dir.as_ref().exists() {
panic!(
"Project directory:{:?} does not exist",
project_dir.as_ref()
);
} else if !project_dir.as_ref().is_dir() {
panic!(
"Project directory:{:?} is not a directory",
project_dir.as_ref()
);
}
println!(
"cargo:rerun-if-changed={}/",
project_dir.as_ref().to_str().unwrap()
);
CMakePresetBuilder {
output_dir: self.output_dir,
project_dir: project_dir.as_ref().to_path_buf(),
config_preset: self.config_preset,
library_name: self.library_name,
_phantom: PhantomData,
}
}
}
impl CMakePresetBuilder<StatusSetConfigPreset> {
pub fn set_config_preset(
self,
preset_name: impl AsRef<str>,
) -> CMakePresetBuilder<StatusSetLibraryName> {
CMakePresetBuilder {
output_dir: self.output_dir,
project_dir: self.project_dir,
config_preset: preset_name.as_ref().into(),
library_name: self.library_name,
_phantom: PhantomData,
}
}
}
impl CMakePresetBuilder<StatusSetLibraryName> {
pub fn set_library_name(
self,
library_name: impl AsRef<str>,
) -> CMakePresetBuilder<StatusConfig> {
println!(
"cargo:rustc-link-search=native={}",
self.output_dir.to_str().unwrap()
);
println!("cargo:rustc-link-lib=static={}", library_name.as_ref());
CMakePresetBuilder {
output_dir: self.output_dir,
project_dir: self.project_dir,
config_preset: self.config_preset,
library_name: library_name.as_ref().to_string(),
_phantom: PhantomData,
}
}
}
impl CMakePresetBuilder<StatusConfig> {
pub fn config(self) -> CMakePresetBuilder<StatusBuild> {
let output_dir = std::env::var("OUT_DIR").unwrap_or_else(|_| ".".to_string());
if !self.project_dir.exists() {
panic!("Project directory does not exist: {:?}", self.project_dir);
}
let output = Command::new("cmake")
.arg("--preset")
.arg(&self.config_preset)
.arg("-B")
.arg(&output_dir)
.current_dir(&self.project_dir)
.output()
.unwrap();
if !output.status.success() {
panic!(
"CMake configure failed: {}",
String::from_utf8_lossy(&output.stderr)
);
}
CMakePresetBuilder {
output_dir: self.output_dir,
project_dir: self.project_dir,
config_preset: self.config_preset,
library_name: self.library_name,
_phantom: PhantomData,
}
}
}
impl CMakePresetBuilder<StatusBuild> {
pub fn build(self) {
let output = Command::new("cmake")
.arg("--build")
.arg(&self.output_dir)
.arg("--parallel")
.current_dir(&self.project_dir)
.output()
.unwrap();
if !output.status.success() {
panic!(
"CMake build failed: {}",
String::from_utf8_lossy(&output.stdout)
);
}
}
}