use crate::{utils, QmlUri, QtInstallation, QtTool};
use std::{
path::{Path, PathBuf},
process::Command,
};
pub struct MocProducts {
pub cpp: PathBuf,
pub metatypes_json: PathBuf,
}
#[derive(Default, Clone)]
pub struct MocArguments {
uri: Option<QmlUri>,
include_paths: Vec<PathBuf>,
}
impl MocArguments {
pub fn uri(mut self, uri: impl Into<QmlUri>) -> Self {
self.uri = Some(uri.into());
self
}
pub fn get_uri(&self) -> Option<&QmlUri> {
self.uri.as_ref()
}
pub fn include_path(mut self, include_path: impl AsRef<Path>) -> Self {
self.include_paths.push(include_path.as_ref().to_owned());
self
}
pub fn include_paths(
mut self,
include_paths: impl IntoIterator<Item = impl AsRef<Path>>,
) -> Self {
self.include_paths.extend(
include_paths
.into_iter()
.map(|path| path.as_ref().to_owned()),
);
self
}
}
pub struct QtToolMoc {
executable: PathBuf,
qt_include_paths: Vec<PathBuf>,
qt_framework_paths: Vec<PathBuf>,
}
impl QtToolMoc {
pub fn new(qt_installation: &dyn QtInstallation, qt_modules: &[String]) -> Self {
let executable = qt_installation
.try_find_tool(QtTool::Moc)
.expect("Could not find moc");
utils::check_executable_help(&executable).unwrap();
let qt_include_paths = qt_installation.include_paths(qt_modules);
let qt_framework_paths = qt_installation.framework_paths(qt_modules);
Self {
executable,
qt_include_paths,
qt_framework_paths,
}
}
pub fn compile(&self, input_file: impl AsRef<Path>, arguments: MocArguments) -> MocProducts {
let input_path = input_file.as_ref();
let moc_dir = QtTool::Moc.writable_path();
std::fs::create_dir_all(&moc_dir).expect("Could not create moc dir");
let output_path = moc_dir.join(format!(
"moc_{}.cpp",
input_path.file_name().unwrap().to_str().unwrap()
));
let metatypes_json_path = PathBuf::from(&format!("{}.json", output_path.display()));
let mut include_args = vec![];
for include_path in self
.qt_include_paths
.iter()
.chain(arguments.include_paths.iter())
{
include_args.push(format!("-I{}", include_path.display()));
}
for framework_path in &self.qt_framework_paths {
include_args.push(format!("-F{}", framework_path.display()));
}
let mut cmd = Command::new(&self.executable);
if let Some(uri) = arguments.uri {
cmd.arg(format!("-Muri={uri}", uri = uri.as_dots()));
}
cmd.args(include_args);
cmd.arg(input_path.to_str().unwrap())
.arg("-o")
.arg(output_path.to_str().unwrap())
.arg("--output-json");
let cmd = cmd
.env_clear()
.output()
.unwrap_or_else(|_| panic!("moc failed for {}", input_path.display()));
if !cmd.status.success() {
panic!(
"moc failed for {}:\n{}",
input_path.display(),
String::from_utf8_lossy(&cmd.stderr)
);
}
MocProducts {
cpp: output_path,
metatypes_json: metatypes_json_path,
}
}
}