extern crate bindgen;
extern crate cc;
extern crate pkg_config;
use std::env;
use std::fs;
use std::path::PathBuf;
#[derive(Debug)]
struct BwBindgenCallbacks {}
fn rerun_if_directory_changed<P>( _path: P ) where P: Into<PathBuf> {
let path: PathBuf = _path.into();
let dir_iterator = match fs::read_dir( &path ) {
Err(e) => panic!( "Unable to read directory: {}", e ),
Ok( iterator ) => iterator
};
for sub_path in dir_iterator {
match sub_path {
Err(e) => panic!( format!("Unable to read directory entry for dir {}: {}", path.as_os_str().to_str().unwrap(), e) ),
Ok( entry ) => {
if entry.path().is_dir() {
rerun_if_directory_changed( entry.path() );
}
else {
println!("cargo:rerun-if-changed={}", entry.path().as_os_str().to_str().unwrap() );
}
}
}
}
}
fn main() {
println!("cargo:rerun-if-env-changed=CEF_PATH");
rerun_if_directory_changed("src");
let target = env::var("TARGET").unwrap();
let out_path = PathBuf::from( env::var("OUT_DIR").expect("Unable to get output directory for C/C++ code base crate") );
let backup_file = PathBuf::from( env::var("CARGO_MANIFEST_DIR").unwrap() + "/bindgen_backup.rs" );
if let Ok(_) = env::var("DOCS_RS") {
fs::copy( &backup_file, out_path.join("c_bindings.rs") ).expect("Unable to copy backup c bindings");
return
}
let mut build = cc::Build::new();
let std_flag = if cfg!(feature = "cef") {
if target.contains("msvc") {
"/std:c++17"
}
else {
"-std=c++17"
}
}
else {
if target.contains("msvc") {
"/std:c11"
}
else {
"-std=c11"
}
};
let mut bgbuilder = bindgen::Builder::default()
.parse_callbacks( Box::new( BwBindgenCallbacks {} ) )
.clang_arg("-DBW_BINDGEN")
.header("src/application.h")
.header("src/browser_window.h")
.header("src/common.h")
.header("src/err.h")
.header("src/string.h")
.header("src/window.h");
if target.contains("windows") {
bgbuilder = bgbuilder.clang_arg("-DBW_WIN32");
build
.file("src/win32.c")
.file("src/application/win32.c")
.file("src/window/win32.c")
.define("BW_WIN32", None)
.define("_CRT_SECURE_NO_WARNINGS", None); }
else if cfg!(feature = "gtk") {
bgbuilder = bgbuilder.clang_arg("-DBW_GTK");
build
.file("src/application/gtk.c")
.file("src/window/gtk.c")
.define("BW_GTK", None);
match pkg_config::Config::new().atleast_version("3.0").arg("--cflags").probe("gtk+-3.0") {
Err(e) => panic!("Unable to find GTK 3 development files: {}", e),
Ok( lib ) => {
for inc in &lib.include_paths {
build.include( inc );
}
}
}
}
else if cfg!(feature = "cef") {
bgbuilder = bgbuilder.clang_arg("-DBW_CEF_WINDOW");
build
.file("src/application/cef_window.cpp")
.file("src/window/cef.cpp")
.define("BW_CEF_WINDOW", None);
}
if cfg!(feature = "cef") {
bgbuilder = bgbuilder.clang_arg("-DBW_CEF");
build.flag_if_supported("-Wno-unused-parameter"); match env::var("CEF_PATH") {
Err(e) => {
match e {
env::VarError::NotPresent => {
if let Err(_) = env::var("DOCS_RS") {
panic!("Environment variable CEF_PATH is not set! This is needed by Browser Window to find CEF's development files. See https://github.com/bamilab/browser-window/tree/master/docs/getting-started for more information.")
}
},
other => panic!("Unable to use CEF_PATH: {}", other)
}
},
Ok(cef_path) => {
build.include(&cef_path);
println!("cargo:rustc-link-search={}/libcef_dll_wrapper", &cef_path);
println!("cargo:rustc-link-search={}/Release", &cef_path);
if target.contains("msvc") {
println!("cargo:rustc-link-search={}", &cef_path);
println!("cargo:rustc-link-search={}/libcef_dll_wrapper/Release", &cef_path);
println!("cargo:rustc-link-lib=static=libcef_dll_wrapper");
println!("cargo:rustc-link-lib=dylib={}", "libcef");
} else {
println!("cargo:rustc-link-lib=static={}", "cef_dll_wrapper");
println!("cargo:rustc-link-lib=dylib={}", "cef");
}
match pkg_config::Config::new().arg("--cflags").arg("--libs").probe("x11") {
Err(_) => {}, Ok( result ) => {
for inc in &result.include_paths {
build.include( inc );
}
}
}
}
}
build
.file("src/application/cef.cpp")
.file("src/browser_window/cef.cpp")
.file("src/cef/bw_handle_map.cpp")
.file("src/cef/client_handler.cpp")
.file("src/cef/exception.cpp")
.file("src/cef/util.cpp")
.define("BW_CEF", None)
.cpp(true);
}
build
.file("src/application/common.c")
.file("src/browser_window/common.c")
.file("src/err.c")
.file("src/string.c")
.file("src/window/common.c")
.flag( std_flag )
.compile("browser_window_c");
bgbuilder
.generate().expect("Unable to generate FFI bindings!")
.write_to_file( out_path.join("c_bindings.rs") ).expect("Unable to write FFI bindings to file!");
if let Ok(_) = env::var("UPDATE_BINDGEN_BACKUP") {
fs::copy( out_path.join("c_bindings.rs"), backup_file ).expect("Unable to copy backup file");
}
}
impl bindgen::callbacks::ParseCallbacks for BwBindgenCallbacks {
fn item_name(&self, item_name: &str) -> Option<String> {
Some( "c".to_owned() + item_name )
}
}