Skip to content

Commit

Permalink
run qmlcachegen on registered QML modules
Browse files Browse the repository at this point in the history
Fixes KDAB#242
  • Loading branch information
Be-ing committed Aug 8, 2023
1 parent d526f12 commit 5bd4f0b
Show file tree
Hide file tree
Showing 2 changed files with 99 additions and 2 deletions.
3 changes: 3 additions & 0 deletions crates/cxx-qt-build/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -535,6 +535,9 @@ where
self.cc_builder.file(qml_type_registration_files.plugin);
cc_builder_whole_archive.file(qml_type_registration_files.plugin_init);
cc_builder_whole_archive.file(qml_type_registration_files.qrc);
for qmlcachegen_file in qml_type_registration_files.qmlcachegen {
cc_builder_whole_archive.file(qmlcachegen_file);
}
self.cc_builder.define("QT_STATICPLUGIN", None);
cc_builder_whole_archive_files_added = true;
}
Expand Down
98 changes: 96 additions & 2 deletions crates/qt-build-utils/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,8 @@ pub struct QmlTypeRegistrationFiles {
pub plugin_init: PathBuf,
/// File generated by rcc for the QML plugin
pub qrc: PathBuf,
/// Files generated by qmlcachegen
pub qmlcachegen: Vec<PathBuf>,
}

/// Helper for build.rs scripts using Qt
Expand All @@ -186,6 +188,7 @@ pub struct QtBuild {
qmake_executable: String,
moc_executable: Option<String>,
qmltyperegistrar_executable: Option<String>,
qmlcachegen_executable: Option<String>,
rcc_executable: Option<String>,
qt_modules: Vec<String>,
}
Expand Down Expand Up @@ -286,6 +289,7 @@ impl QtBuild {
qmake_executable: executable_name.to_string(),
moc_executable: None,
qmltyperegistrar_executable: None,
qmlcachegen_executable: None,
rcc_executable: None,
version,
qt_modules,
Expand All @@ -309,6 +313,7 @@ impl QtBuild {
qmake_executable: executable_name.to_string(),
moc_executable: None,
qmltyperegistrar_executable: None,
qmlcachegen_executable: None,
rcc_executable: None,
version,
qt_modules,
Expand Down Expand Up @@ -634,6 +639,12 @@ impl QtBuild {
.expect("Could not find qmltyperegistrar"),
);
}
// qmlcachegen has a different CLI in Qt 5, so only support Qt >= 6
if self.qmlcachegen_executable.is_none() && self.version.major >= 6 {
if let Ok(qmlcachegen_executable) = self.get_qt_tool("qmlcachegen") {
self.qmlcachegen_executable = Some(qmlcachegen_executable);
}
}

let uri = &qml_module.uri;
let qml_uri_dirs = uri.replace('.', "/");
Expand All @@ -646,8 +657,8 @@ impl QtBuild {
let typeinfo_path = format!("{qml_uri_cpp_symbol_safe}.qmltypes");
let plugin_class_name = format!("{qml_uri_cpp_symbol_safe}_plugin");

let mut qmldir =
File::create(format!("{qml_module_dir}/qmldir")).expect("Could not create qmldir file");
let qmldir_file_path = format!("{qml_module_dir}/qmldir");
let mut qmldir = File::create(&qmldir_file_path).expect("Could not create qmldir file");
write!(
qmldir,
"module {uri}
Expand Down Expand Up @@ -770,11 +781,94 @@ Q_IMPORT_PLUGIN({plugin_class_name});
)
.unwrap();

let mut qmlcachegen_file_paths = Vec::new();
// qmlcachegen needs to be run once for each .qml file with --resource-path,
// then once for the module with --resource-name.
if let Some(qmlcachegen_executable) = &self.qmlcachegen_executable {
let qmlcachegen_dir = format!("{out_dir}/qmlcachegen/{qml_uri_dirs}");
std::fs::create_dir_all(&qmlcachegen_dir)
.expect("Could not create qmlcachegen directory for QML module");

let common_args = vec![
"-i".to_string(),
qmldir_file_path.to_string(),
"--resource".to_string(),
qrc_path,
];

let mut qml_file_qrc_paths = Vec::new();
for file in qml_module.qml_files {
let qrc_resource_path =
format!("/qt/qml/{qml_uri_dirs}/{}", file.as_ref().display());

let qml_compiled_file = format!(
"{qmlcachegen_dir}/{}.cpp",
file.as_ref().file_name().unwrap().to_string_lossy()
);
qmlcachegen_file_paths.push(PathBuf::from(&qml_compiled_file));

let specific_args = vec![
"--resource-path".to_string(),
qrc_resource_path.clone(),
"-o".to_string(),
qml_compiled_file,
std::fs::canonicalize(file)
.unwrap()
.to_string_lossy()
.to_string(),
];

let cmd = Command::new(&qmlcachegen_executable)
.args(common_args.iter().chain(&specific_args))
.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)
);
}
qml_file_qrc_paths.push(qrc_resource_path);
}

let qmlcachegen_loader = format!("{qmlcachegen_dir}/qmlcache_loader.cpp");
let specific_args = vec![
"--resource-name".to_string(),
format!("qmlcache_{qml_uri_cpp_symbol_safe}"),
"-o".to_string(),
qmlcachegen_loader.clone(),
];

let cmd = Command::new(&qmlcachegen_executable)
.args(
common_args
.iter()
.chain(&specific_args)
.chain(&qml_file_qrc_paths),
)
.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_file_paths.push(PathBuf::from(&qmlcachegen_loader));
}

QmlTypeRegistrationFiles {
qmltyperegistrar: output_path,
plugin: qml_plugin_cpp_path,
plugin_init: qml_plugin_init_path,
qrc: qrc_output,
qmlcachegen: qmlcachegen_file_paths,
}
}

Expand Down

0 comments on commit 5bd4f0b

Please sign in to comment.