use std::path::PathBuf;
use std::env;
#[cfg(feature = "ffi-regenerate")]
mod build_dependencies {
use bindgen::callbacks::{ParseCallbacks, DeriveInfo};
use super::*;
use std::fs;
#[derive(Debug)]
struct CloneCallback;
impl ParseCallbacks for CloneCallback {
fn add_derives(&self, info: &DeriveInfo) -> Vec<String> {
let mut data = vec!["Clone".into()];
if info.name.starts_with("mjui") || info.name == "mjrRect_" {
data.push("Copy".into());
}
else if info.name.starts_with("mjt") { data.push("Copy".into());
}
data
}
}
pub(crate) fn generate_ffi() {
let output_path = PathBuf::from("./src/");
let current_dir = env::current_dir().unwrap();
let include_dir_mujoco = current_dir.join("src/cpp/include/mujoco");
let include_dir_simulate = include_dir_mujoco.join("viewer");
let bindings_mujoco = bindgen::Builder::default()
.header(include_dir_mujoco.join("mujoco.h").to_str().unwrap())
.header(include_dir_simulate.join("simulate.hpp").to_str().unwrap())
.header(include_dir_simulate.join("glfw_dispatch.hpp").to_str().unwrap())
.clang_arg("-std=c++20")
.clang_arg("-stdlib=libc++")
.clang_arg(format!("-I{}", current_dir.join("mujoco/build/_deps/glfw3-src/include/").display()))
.blocklist_item("std::tuple.*")
.allowlist_item("mj.*")
.allowlist_item("mujoco::.*")
.allowlist_item("new_simulate")
.allowlist_item("free_simulate")
.layout_tests(false)
.derive_default(false)
.opaque_type("std::.*")
.derive_copy(false)
.rustified_enum(".*")
.parse_callbacks(Box::new(CloneCallback))
.generate()
.expect("unable to generate MuJoCo bindings");
let outputfile_dir = output_path.join("mujoco_c.rs");
let mut fdata = bindings_mujoco
.to_string();
fdata = fdata.replace("pub __lx: std_basic_string_value_type<_CharT>,", "pub __lx: std::mem::ManuallyDrop<std_basic_string_value_type<_CharT>>,");
let re = regex::Regex::new(r"#\[derive\((.*?Clone.*?), Clone,?(.*?)\)\]").unwrap();
fdata = re.replace_all(&fdata, "#[derive($1, $2)]").to_string();
fs::write(outputfile_dir, fdata).unwrap();
}
}
fn main() {
if std::env::var("DOCS_RS").is_ok() {
return;
}
const MUJOCO_STATIC_LIB_PATH_VAR: &str = "MUJOCO_STATIC_LINK_DIR";
const MUJOCO_DYN_LIB_PATH_VAR: &str = "MUJOCO_DYNAMIC_LINK_DIR";
println!("cargo:rerun-if-env-changed={MUJOCO_STATIC_LIB_PATH_VAR}");
println!("cargo:rerun-if-env-changed={MUJOCO_DYN_LIB_PATH_VAR}");
let mujoco_lib_path= env::var(MUJOCO_STATIC_LIB_PATH_VAR);
if let Ok(path) = mujoco_lib_path {
let mj_lib_pathbuf = PathBuf::from(path);
let mj_lib_simulate_path = mj_lib_pathbuf.join("libsimulate.a");
println!("cargo::rerun-if-changed={}", mj_lib_simulate_path.canonicalize().unwrap().display());
println!("cargo:rustc-link-search={}", mj_lib_pathbuf.canonicalize().unwrap().display());
#[cfg(feature = "cpp-viewer")]
println!("cargo:rustc-link-lib=simulate");
println!("cargo:rustc-link-lib=mujoco");
println!("cargo:rustc-link-lib=lodepng");
println!("cargo:rustc-link-lib=tinyxml2");
println!("cargo:rustc-link-lib=qhullstatic_r");
println!("cargo:rustc-link-lib=ccd");
if cfg!(unix) {
println!("cargo:rustc-link-lib=stdc++");
}
}
else {
let mujoco_dylib_path = PathBuf::from(env::var(MUJOCO_DYN_LIB_PATH_VAR)
.unwrap_or_else(|_| panic!("nor the static library path ({MUJOCO_STATIC_LIB_PATH_VAR}),\
nor the dynamic library path ({MUJOCO_DYN_LIB_PATH_VAR}) was given.")));
println!("cargo:rustc-link-search={}", mujoco_dylib_path.canonicalize().unwrap().display());
println!("cargo:rustc-link-lib=mujoco");
}
#[cfg(feature = "ffi-regenerate")]
build_dependencies::generate_ffi();
}