use std::env; use std::error::Error; use std::fs; use std::io::{Read, Write}; use std::path::PathBuf; use std::process::Command; fn main() -> Result<(), Box> { if env::var("DOCS_RS").is_err() & !cfg!(feature = "sitk_no_build") { let sitk_dir = PathBuf::from("SimpleITK"); // use cmake to compile the SimpleITK C++ code let dst = cmake::Config::new(sitk_dir.join("SuperBuild")) .no_build_target(true) .define("ITK_SKIP_PATH_LENGTH_CHECKS", "ON") .define("BUILD_EXAMPLES", "OFF") .define("BUILD_TESTING", "OFF") .define("WRAP_CSHARP", "OFF") .define("WRAP_JAVA", "OFF") .define("WRAP_LUA", "OFF") .define("WRAP_R", "OFF") .define("WRAP_RUBY", "OFF") .define("WRAP_TCL", "OFF") .define("WRAP_PYTHON", "OFF") .define("WRAP_DEFAULT", "OFF") .define("SimpleITK_USE_ELASTIX", "ON") .build(); // there does not seem to be any way to tell cargo to group libraries together // when linking, so we group all objects together in three big static libraries let merged_lib = cmake::Config::new("merged_lib") .out_dir(dst.join("merged_lib")) .no_build_target(true) .build(); let mut b = autocxx_build::Builder::new( "src/lib.rs", ["cxx", dst.join("include/SimpleITK-3.0").to_str().unwrap()], ) .extra_clang_args(&["-std=c++17"]) .build()?; b.flag("-std=c++17").compile("sitk_autocxx"); cc::Build::new() .include(dst.join("include/SimpleITK-3.0")) .file("cxx/ffi_extra.cxx") .compile("sitk_ffi_extra"); let cxx_file = dst.join("autocxx-build-dir/rs/autocxx-ffi-default-gen.rs"); let mut cxx = String::new(); let _ = fs::File::open(&cxx_file)?.read_to_string(&mut cxx)?; let ra = regex::Regex::new(r"\s*(#|\s(fn|use|mod|pub|struct|enum)\s)\s*")?; let rb = regex::Regex::new(r"\s(;)\s")?; let pointer = regex::Regex::new(r"pub type pointer = root\s+::\s+pointer;")?; let cpp_string = regex::Regex::new(r"pub mod simple \{")?; let rb_tree = regex::Regex::new( r"pub type _Rb_tree_insert_return_type = root :: std :: _Node_insert_return < _Iterator , _NodeHandle >;", )?; { let mut f = fs::OpenOptions::new() .write(true) .truncate(true) .open(&cxx_file)?; write!( f, "#[allow(unused_imports)]\n#[allow(unsafe_op_in_unsafe_fn)]\n#[allow(clippy::missing_safety_doc)]\n" )?; let cxx = ra.replace_all(&cxx, "\n$1"); let cxx = rb.replace_all(&cxx, "$1\n"); let cxx = pointer.replace_all(&cxx, r"// $0"); let cxx = rb_tree.replace_all(&cxx, r"// $0"); let cxx = cpp_string.replace_all(&cxx, "pub mod simple {\nuse crate::ffi::ToCppString;"); write!(f, "{}", cxx)?; } if cfg!(feature = "copy_autocxx_src") { fs::copy(dst.join(&cxx_file), "src/autocxx-ffi-default-gen_unfmt.rs")?; Command::new("rustfmt").arg(&cxx_file).status()?; fs::copy(dst.join(&cxx_file), "src/autocxx-ffi-default-gen.rs")?; } println!("cargo:warning=merged_lib={}", merged_lib.join("build").display()); println!("cargo:rustc-link-search={}", merged_lib.join("build").display()); println!("cargo:rustc-link-lib=static=sitk_ffi_extra"); println!("cargo:rustc-link-lib=static=sitk"); println!("cargo:rustc-link-lib=static=elastix"); println!("cargo:rustc-link-lib=static=itk"); println!("cargo:rerun-if-changed=build.rs"); println!("cargo:rerun-if-changed=src/lib.rs"); println!("cargo:rerun-if-changed=cxx/ffi_extra.h"); println!("cargo:rerun-if-changed=cxx/ffi_extra.cxx"); } else { let dst = PathBuf::from(env::var("OUT_DIR")?); fs::create_dir_all(dst.join("autocxx-build-dir/rs"))?; fs::copy( "src/autocxx-ffi-default-gen.rs", dst.join("autocxx-build-dir/rs/autocxx-ffi-default-gen.rs"), )?; } Ok(()) }