use crate::{utils, QmlUri, QtInstallation, QtTool};
use std::{
path::{Path, PathBuf},
process::Command,
};
#[derive(Clone)]
pub struct QmlCacheArguments {
pub uri: QmlUri,
pub qmldir_path: PathBuf,
pub qmldir_qrc_path: PathBuf,
}
pub struct QmlCacheProducts {
pub qml_cache_path: PathBuf,
pub qml_resource_path: String,
}
pub struct QtToolQmlCacheGen {
executable: PathBuf,
}
impl QtToolQmlCacheGen {
pub fn new(qt_installation: &dyn QtInstallation) -> Self {
let executable = qt_installation
.try_find_tool(QtTool::QmlCacheGen)
.expect("Could not find qmlcachegen");
utils::check_executable_help(&executable).unwrap();
Self { executable }
}
pub fn compile(
&self,
common_args: QmlCacheArguments,
file: impl AsRef<Path>,
) -> QmlCacheProducts {
let uri = common_args.uri;
let qml_uri_dirs = uri.as_dirs();
let qmlcachegen_dir = QtTool::QmlCacheGen.writable_path().join(&qml_uri_dirs);
std::fs::create_dir_all(&qmlcachegen_dir)
.expect("Could not create qmlcachegen directory for QML module");
let common_args = [
"-i".to_owned(),
common_args.qmldir_path.to_string_lossy().into_owned(),
"--resource".to_owned(),
common_args.qmldir_qrc_path.to_string_lossy().into_owned(),
];
let qml_cache_path = qmlcachegen_dir.join(format!(
"{}.cpp",
file.as_ref().file_name().unwrap().to_string_lossy()
));
let qml_resource_path = format!("/qt/qml/{qml_uri_dirs}/{}", file.as_ref().display());
let specific_args = vec![
"--resource-path".to_owned(),
qml_resource_path.clone(),
"-o".to_owned(),
qml_cache_path.to_string_lossy().into_owned(),
std::fs::canonicalize(&file)
.unwrap()
.to_string_lossy()
.into_owned(),
];
let cmd = Command::new(&self.executable)
.args(common_args.iter().chain(&specific_args))
.env_clear()
.output()
.unwrap_or_else(|_| {
panic!(
"qmlcachegen failed for {} in QML module {uri}",
file.as_ref().display()
)
});
if !cmd.status.success() {
panic!(
"qmlcachegen failed for {} in QML module {uri}:\n{}",
file.as_ref().display(),
String::from_utf8_lossy(&cmd.stderr)
);
}
QmlCacheProducts {
qml_cache_path,
qml_resource_path,
}
}
pub fn compile_loader(
&self,
common_args: QmlCacheArguments,
qml_resource_paths: &[String],
) -> PathBuf {
let uri = common_args.uri;
let qml_uri_dirs = uri.as_dirs();
let qml_uri_underscores = uri.as_underscores();
let qmlcachegen_dir = QtTool::QmlCacheGen.writable_path().join(qml_uri_dirs);
std::fs::create_dir_all(&qmlcachegen_dir)
.expect("Could not create qmlcachegen directory for QML module");
let common_args = [
"-i".to_owned(),
common_args.qmldir_path.to_string_lossy().into_owned(),
"--resource".to_owned(),
common_args.qmldir_qrc_path.to_string_lossy().into_owned(),
];
let qmlcachegen_loader = qmlcachegen_dir.join("qmlcache_loader.cpp");
let specific_args = vec![
"--resource-name".to_owned(),
format!("qmlcache_{qml_uri_underscores}"),
"-o".to_owned(),
qmlcachegen_loader.to_string_lossy().into_owned(),
];
let cmd = Command::new(&self.executable)
.args(
common_args
.iter()
.chain(&specific_args)
.chain(qml_resource_paths),
)
.env_clear()
.output()
.unwrap_or_else(|_| panic!("qmlcachegen failed for QML module {uri}"));
if !cmd.status.success() {
panic!(
"qmlcachegen failed for QML module {uri}:\n{}",
String::from_utf8_lossy(&cmd.stderr)
);
}
qmlcachegen_loader
}
}