#[cfg(feature = "bindings")]
mod error {
use cbindgen::Error as BindgenError;
#[cfg(feature = "ctests")]
use cc::Error as CcError;
use std::{env::VarError, error, fmt, io};
#[allow(unused)]
#[derive(Debug)]
pub enum Error {
Bindgen(BindgenError),
#[cfg(feature = "ctests")]
Cc(CcError),
Io(io::Error),
Env(VarError),
Unspecified,
}
impl error::Error for Error {
#[inline]
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
match *self {
Error::Bindgen(ref e) => Some(e),
Error::Io(ref e) => Some(e),
Error::Env(ref e) => Some(e),
_ => None,
}
}
#[inline]
fn description(&self) -> &str {
match *self {
Error::Bindgen(ref e) => e.description(),
Error::Io(ref e) => e.description(),
Error::Env(ref e) => e.description(),
#[cfg(feature = "ctests")]
Error::Cc(_) => "A c compiler error occurred",
Error::Unspecified => "An unspecified error occurred",
}
}
}
impl fmt::Display for Error {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
Error::Bindgen(ref e) => fmt::Display::fmt(e, f),
#[cfg(feature = "ctests")]
Error::Cc(_) => f.write_str(error::Error::description(self)),
Error::Unspecified => f.write_str(error::Error::description(self)),
Error::Io(ref e) => fmt::Display::fmt(e, f),
Error::Env(ref e) => fmt::Display::fmt(e, f),
}
}
}
#[cfg(feature = "ctests")]
impl From<CcError> for Error {
#[inline]
fn from(e: CcError) -> Self {
Error::Cc(e)
}
}
impl From<io::Error> for Error {
#[inline]
fn from(e: io::Error) -> Self {
Error::Io(e)
}
}
impl From<BindgenError> for Error {
#[inline]
fn from(e: BindgenError) -> Self {
Error::Bindgen(e)
}
}
impl From<VarError> for Error {
#[inline]
fn from(e: VarError) -> Self {
Error::Env(e)
}
}
}
#[cfg(feature = "bindings")]
fn main() -> Result<(), error::Error> {
use cbindgen::{self, Config, Language};
use std::{
env::{self, VarError},
path::PathBuf,
};
let crate_dir = env::var("CARGO_MANIFEST_DIR")?;
let mut bindings = cbindgen::generate(crate_dir)?;
push_stdio(&mut bindings.config);
let mut header_path = target_dir()?;
header_path.push("include/bvh_anim/bvh_anim.h");
bindings.write_to_file(header_path);
build_and_run_ctests()?;
#[inline]
fn target_dir() -> Result<PathBuf, VarError> {
env::var("CARGO_TARGET_DIR")
.map(PathBuf::from)
.or_else(|_| {
env::var("CARGO_MANIFEST_DIR")
.map(PathBuf::from)
.map(|p| p.join("target"))
})
}
#[inline]
fn push_stdio(config: &mut Config) {
match config.language {
Language::Cxx => config.sys_includes.push("cstdio".to_string()),
Language::C => config.sys_includes.push("stdio.h".to_string()),
}
}
#[cfg(feature = "ctests")]
fn build_and_run_ctests() -> Result<(), error::Error> {
use cc::Build;
use std::{io, fs};
let crate_dir = PathBuf::from(env::var("CARGO_MANIFEST_DIR")?);
let ctests_dir = crate_dir.join("ctests");
if !ctests_dir.exists() {
println!("Skipping ctests");
return Err(error::Error::Unspecified);
}
let entries = fs::read_dir(ctests_dir)?;
let mut include_dir = target_dir()?;
include_dir.push("include");
let mut out_dir = PathBuf::from(env::var("OUT_DIR")?);
out_dir.push("ctests");
panic!("{:?}", out_dir);
for entry in entries {
let entry = entry?;
let entry_path = entry.path();
match entry_path.extension() {
Some(ext) if ext == "c" || ext == "cpp" => (),
_ => continue,
}
let file_name = entry_path.file_name().unwrap();
Build::new()
.file(&entry_path)
.include(&include_dir)
.out_dir(&out_dir)
.try_compile(file_name.to_str().unwrap())?;
}
Ok(())
}
#[cfg(not(feature = "ctests"))]
fn build_and_run_ctests() -> Result<(), error::Error> {
Ok(())
}
Ok(())
}
#[cfg(not(feature = "bindings"))]
fn main() {}