extern crate cpp_to_rust;
use cpp_to_rust::config::Config;
use cpp_to_rust::errors::{Result, ChainErr};
use cpp_to_rust::log;
use cpp_to_rust::utils::run_command;
use cpp_to_rust::file_utils::PathBufWithAdded;
mod fix_header_names;
use std::path::PathBuf;
use std::process::Command;
use std::env;
fn run_qmake_query(arg: &str) -> Result<PathBuf> {
let result = try!(run_command(Command::new("qmake").arg("-query").arg(arg), true, true));
Ok(PathBuf::from(result.trim()))
}
pub trait QtConfig {
fn setup_qt_library(&mut self) -> Result<()>;
fn exclude_qlist_eq_based_methods<S: AsRef<str>, I: IntoIterator<Item=S>>(&mut self, types: I);
fn exclude_qvector_eq_based_methods<S: AsRef<str>, I: IntoIterator<Item=S>>(&mut self, types: I);
}
impl QtConfig for Config {
fn setup_qt_library(&mut self) -> Result<()> {
let qt_lib_name = try!(env::var("CARGO_MANIFEST_LINKS")
.chain_err(|| "no environment variable: CARGO_MANIFEST_LINKS"));
if !qt_lib_name.starts_with("Qt5") {
return Err(format!("Invalid library name (must start with \"Qt5\"): {}",
qt_lib_name)
.into());
}
let folder_name = format!("Qt{}", &qt_lib_name[3..]);
log::info("Detecting Qt directories...");
let qt_install_headers_path = try!(run_qmake_query("QT_INSTALL_HEADERS"));
log::info(format!("QT_INSTALL_HEADERS = \"{}\"",
qt_install_headers_path.display()));
let qt_install_libs_path = try!(run_qmake_query("QT_INSTALL_LIBS"));
log::info(format!("QT_INSTALL_LIBS = \"{}\"", qt_install_libs_path.display()));
self.add_include_path(&qt_install_headers_path);
let dir = qt_install_headers_path.with_added(&folder_name);
let qt_this_lib_headers_dir = if dir.exists() {
self.add_include_path(&dir);
self.add_target_include_path(&dir);
self.add_lib_path(&qt_install_libs_path);
self.add_linked_lib(qt_lib_name);
dir
} else {
let dir2 = qt_install_libs_path.with_added(format!("{}.framework/Headers", folder_name));
if dir2.exists() {
self.add_include_path(&dir2);
self.add_target_include_path(&dir2);
self.add_framework_path(&qt_install_libs_path);
self.add_linked_framework(folder_name.clone());
dir2
} else {
return Err(format!("extra header dir not found (tried: {}, {})",
dir.display(),
dir2.display())
.into());
}
};
self.add_include_directive(&folder_name);
self.add_cpp_data_filter(Box::new(move |cpp_data| {
fix_header_names::fix_header_names(cpp_data, &qt_this_lib_headers_dir)
}));
self.add_cpp_parser_blocked_name("qt_check_for_QGADGET_macro");
Ok(())
}
fn exclude_qlist_eq_based_methods<S: AsRef<str>, I: IntoIterator<Item=S>>(&mut self, types: I) {
let types: Vec<String> = types.into_iter().map(|x| x.as_ref().to_string()).collect();
self.add_cpp_ffi_generator_filter(Box::new(move |method| {
if let Some(ref info) = method.class_membership {
if info.class_type.name == "QList" {
let args = try!(info.class_type.template_arguments.as_ref()
.chain_err(|| "failed to get QList args"));
let arg = try!(args.get(0).chain_err(|| "failed to get QList arg"));
let arg_text = arg.to_cpp_pseudo_code();
if types.iter().any(|x| x == &arg_text) {
match method.name.as_ref() {
"operator==" | "operator!=" | "indexOf" | "lastIndexOf" | "contains" |
"startsWith" | "endsWith" | "removeOne" | "removeAll" | "value" |
"toVector" | "toSet" => return Ok(false),
"count" => if method.arguments.len() == 1 { return Ok(false); },
_ => {}
}
}
}
}
Ok(true)
}));
}
fn exclude_qvector_eq_based_methods<S: AsRef<str>, I: IntoIterator<Item=S>>(&mut self, types: I) {
let types: Vec<String> = types.into_iter().map(|x| x.as_ref().to_string()).collect();
self.add_cpp_ffi_generator_filter(Box::new(move |method| {
if let Some(ref info) = method.class_membership {
if info.class_type.name == "QVector" {
let args = try!(info.class_type.template_arguments.as_ref()
.chain_err(|| "failed to get QVector args"));
let arg = try!(args.get(0).chain_err(|| "failed to get QVector arg"));
let arg_text = arg.to_cpp_pseudo_code();
if types.iter().any(|x| x == &arg_text) {
match method.name.as_ref() {
"operator==" | "operator!=" | "indexOf" | "lastIndexOf" | "contains" |
"startsWith" | "endsWith" | "removeOne" | "removeAll" | "toList" => return Ok(false),
"count" => if method.arguments.len() == 1 { return Ok(false); },
_ => {}
}
}
}
}
Ok(true)
}));
}
}