use std::env;
fn main() {
let mut build = cc::Build::new();
build.include("vendor/VulkanMemoryAllocator/include");
build.include("vendor/Vulkan-Headers/include");
build.include("wrapper");
#[cfg(not(debug_assertions))]
build.define("NDEBUG", "");
build.define("VMA_STATIC_VULKAN_FUNCTIONS", "0");
build.define("VMA_DYNAMIC_VULKAN_FUNCTIONS", "0");
#[cfg(feature = "recording")]
build.define("VMA_RECORDING_ENABLED", "1");
let source_files = ["wrapper/vma_lib.cpp"];
for source_file in &source_files {
build.file(&source_file);
}
let target = env::var("TARGET").unwrap();
if target.contains("darwin") {
build
.flag("-std=c++17")
.flag("-Wno-missing-field-initializers")
.flag("-Wno-unused-variable")
.flag("-Wno-unused-parameter")
.flag("-Wno-unused-private-field")
.flag("-Wno-reorder")
.flag("-Wno-nullability-completeness")
.cpp_link_stdlib("c++")
.cpp_set_stdlib("c++")
.cpp(true);
} else if target.contains("ios") {
build
.flag("-std=c++17")
.flag("-Wno-missing-field-initializers")
.flag("-Wno-unused-variable")
.flag("-Wno-unused-parameter")
.flag("-Wno-unused-private-field")
.flag("-Wno-reorder")
.cpp_link_stdlib("c++")
.cpp_set_stdlib("c++")
.cpp(true);
} else if target.contains("android") {
build
.flag("-std=c++17")
.flag("-Wno-missing-field-initializers")
.flag("-Wno-unused-variable")
.flag("-Wno-unused-parameter")
.flag("-Wno-unused-private-field")
.flag("-Wno-reorder")
.cpp_link_stdlib("c++")
.cpp(true);
} else if target.contains("linux") {
build
.flag("-std=c++17")
.flag("-Wno-missing-field-initializers")
.flag("-Wno-unused-variable")
.flag("-Wno-unused-parameter")
.flag("-Wno-unused-private-field")
.flag("-Wno-reorder")
.cpp_link_stdlib("stdc++")
.cpp(true);
} else if target.contains("windows") && target.contains("gnu") {
build
.flag("-std=c++17")
.flag("-Wno-missing-field-initializers")
.flag("-Wno-unused-variable")
.flag("-Wno-unused-parameter")
.flag("-Wno-unused-private-field")
.flag("-Wno-reorder")
.flag("-Wno-type-limits")
.cpp_link_stdlib("stdc++")
.cpp(true);
}
build.compile("vma_cpp");
link_vulkan();
generate_bindings("gen/bindings.rs");
}
#[cfg(feature = "link_vulkan")]
fn link_vulkan() {
use std::path::PathBuf;
let target = env::var("TARGET").unwrap();
if target.contains("windows") {
if let Ok(vulkan_sdk) = env::var("VULKAN_SDK") {
let mut vulkan_sdk_path = PathBuf::from(vulkan_sdk);
if target.contains("x86_64") {
vulkan_sdk_path.push("Lib");
} else {
vulkan_sdk_path.push("Lib32");
}
println!("cargo:rustc-link-search=native={}", vulkan_sdk_path.to_str().unwrap());
}
println!("cargo:rustc-link-lib=dylib=vulkan-1");
} else {
if target.contains("apple") {
if let Ok(vulkan_sdk) = env::var("VULKAN_SDK") {
let mut vulkan_sdk_path = PathBuf::from(vulkan_sdk);
vulkan_sdk_path.push("macOS/lib");
println!("cargo:rustc-link-search=native={}", vulkan_sdk_path.to_str().unwrap());
} else {
let lib_path = "wrapper/macOS/lib";
println!("cargo:rustc-link-search=native={}", lib_path);
}
println!("cargo:rustc-link-lib=dylib=vulkan");
}
}
}
#[cfg(not(feature = "link_vulkan"))]
fn link_vulkan() {}
#[cfg(feature = "generate_bindings")]
fn generate_bindings(output_file: &str) {
let bindings = bindgen::Builder::default()
.clang_arg("-I./wrapper")
.clang_arg("-I./vendor/Vulkan-Headers/include")
.header("vendor/VulkanMemoryAllocator/include/vk_mem_alloc.h")
.rustfmt_bindings(true)
.size_t_is_usize(true)
.blocklist_type("__darwin_.*")
.allowlist_function("vma.*")
.allowlist_function("PFN_vma.*")
.allowlist_type("Vma.*")
.parse_callbacks(Box::new(FixAshTypes))
.blocklist_type("Vk.*")
.blocklist_type("PFN_vk.*")
.raw_line("use ash::vk::*;")
.trust_clang_mangling(false)
.layout_tests(false)
.generate()
.expect("Unable to generate bindings!");
bindings.write_to_file(std::path::Path::new(output_file)).expect("Unable to write bindings!");
}
#[cfg(not(feature = "generate_bindings"))]
fn generate_bindings(_: &str) {}
#[cfg(feature = "generate_bindings")]
#[derive(Debug)]
struct FixAshTypes;
#[cfg(feature = "generate_bindings")]
impl bindgen::callbacks::ParseCallbacks for FixAshTypes {
fn item_name(&self, original_item_name: &str) -> Option<String> {
if original_item_name.starts_with("Vk") {
Some(original_item_name.trim_start_matches("Vk").to_string())
} else if original_item_name.starts_with("PFN_vk") && original_item_name.ends_with("KHR") {
Some(original_item_name.trim_end_matches("KHR").to_string())
} else {
None
}
}
fn add_derives(&self, name: &str) -> Vec<String> {
if name.starts_with("VmaAllocationInfo") || name.starts_with("VmaDefragmentationStats") {
vec!["Debug".into(), "Copy".into(), "Clone".into()]
} else {
vec![]
}
}
}