qt_build_utils/tool/
qmltyperegistrar.rs

1// SPDX-FileCopyrightText: 2025 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
2// SPDX-FileContributor: Andrew Hayzen <andrew.hayzen@kdab.com>
3//
4// SPDX-License-Identifier: MIT OR Apache-2.0
5
6use crate::{QmlUri, QtInstallation, QtTool};
7use semver::Version;
8use std::{
9    path::{Path, PathBuf},
10    process::Command,
11};
12
13/// A wrapper around the [qmltyperegistrar](https://www.qt.io/blog/qml-type-registration-in-qt-5.15) tool
14pub struct QtToolQmlTypeRegistrar {
15    executable: PathBuf,
16}
17
18impl QtToolQmlTypeRegistrar {
19    /// Construct a [QtToolQmlTypeRegistrar] from a given [QtInstallation]
20    pub fn new(qt_installation: &dyn QtInstallation) -> Self {
21        let executable = qt_installation
22            .try_find_tool(QtTool::QmlTypeRegistrar)
23            .expect("Could not find qmltyperegistrar");
24
25        Self { executable }
26    }
27
28    /// Run [qmltyperegistrar](https://www.qt.io/blog/qml-type-registration-in-qt-5.15)
29    pub fn compile(
30        &self,
31        metatypes_json: &[impl AsRef<Path>],
32        qmltypes: impl AsRef<Path>,
33        uri: &QmlUri,
34        version: Version,
35    ) -> Option<PathBuf> {
36        // Filter out empty jsons
37        let metatypes_json: Vec<_> = metatypes_json
38            .iter()
39            .filter(|f| {
40                std::fs::metadata(f)
41                    .unwrap_or_else(|_| panic!("couldn't open json file {}", f.as_ref().display()))
42                    .len()
43                    > 0
44            })
45            .map(|f| f.as_ref().to_string_lossy().into_owned())
46            .collect();
47
48        // Only run qmltyperegistrar if we have valid json files left out
49        if metatypes_json.is_empty() {
50            return None;
51        }
52
53        let qml_uri_underscores = uri.as_underscores();
54        // TODO: note before this was the plugin folder
55        let output_folder = QtTool::QmlTypeRegistrar.writable_path();
56        std::fs::create_dir_all(&output_folder).expect("Could not create qmltyperegistrar dir");
57        let qmltyperegistrar_output_path =
58            output_folder.join(format!("{qml_uri_underscores}_qmltyperegistration.cpp"));
59
60        let mut args = vec![
61            "--generate-qmltypes".to_owned(),
62            qmltypes.as_ref().to_string_lossy().into_owned(),
63            "--major-version".to_owned(),
64            version.major.to_string(),
65            "--minor-version".to_owned(),
66            version.minor.to_string(),
67            "--import-name".to_owned(),
68            uri.to_string(),
69            "-o".to_owned(),
70            qmltyperegistrar_output_path.to_string_lossy().into_owned(),
71        ];
72        args.extend(metatypes_json);
73        let cmd = Command::new(&self.executable)
74            .args(args)
75            .output()
76            .unwrap_or_else(|_| panic!("qmltyperegistrar failed for {uri}"));
77        if !cmd.status.success() {
78            panic!(
79                "qmltyperegistrar failed for {uri}:\n{}",
80                String::from_utf8_lossy(&cmd.stderr)
81            );
82        }
83
84        Some(qmltyperegistrar_output_path)
85    }
86}