qt_build_utils/tool/
moc.rs1use crate::{QmlUri, QtInstallation, QtTool};
7
8use std::{
9 path::{Path, PathBuf},
10 process::Command,
11};
12
13pub struct MocProducts {
15 pub cpp: PathBuf,
17 pub metatypes_json: PathBuf,
19}
20
21#[derive(Default, Clone)]
24pub struct MocArguments {
25 uri: Option<QmlUri>,
26 include_paths: Vec<PathBuf>,
27}
28
29impl MocArguments {
30 pub fn uri(mut self, uri: impl Into<QmlUri>) -> Self {
32 self.uri = Some(uri.into());
33 self
34 }
35
36 pub fn get_uri(&self) -> Option<&QmlUri> {
38 self.uri.as_ref()
39 }
40
41 pub fn include_path(mut self, include_path: impl AsRef<Path>) -> Self {
43 self.include_paths.push(include_path.as_ref().to_owned());
44 self
45 }
46
47 pub fn include_paths(
49 mut self,
50 include_paths: impl IntoIterator<Item = impl AsRef<Path>>,
51 ) -> Self {
52 self.include_paths.extend(
53 include_paths
54 .into_iter()
55 .map(|path| path.as_ref().to_owned()),
56 );
57 self
58 }
59}
60
61pub struct QtToolMoc {
63 executable: PathBuf,
64 qt_include_paths: Vec<PathBuf>,
65 qt_framework_paths: Vec<PathBuf>,
66}
67
68impl QtToolMoc {
69 pub fn new(qt_installation: &dyn QtInstallation, qt_modules: &[String]) -> Self {
71 let executable = qt_installation
72 .try_find_tool(QtTool::Moc)
73 .expect("Could not find moc");
74 let qt_include_paths = qt_installation.include_paths(qt_modules);
75 let qt_framework_paths = qt_installation.framework_paths(qt_modules);
76
77 Self {
78 executable,
79 qt_include_paths,
80 qt_framework_paths,
81 }
82 }
83
84 pub fn compile(&self, input_file: impl AsRef<Path>, arguments: MocArguments) -> MocProducts {
88 let input_path = input_file.as_ref();
89 let moc_dir = QtTool::Moc.writable_path();
91 std::fs::create_dir_all(&moc_dir).expect("Could not create moc dir");
92 let output_path = moc_dir.join(format!(
93 "moc_{}.cpp",
94 input_path.file_name().unwrap().to_str().unwrap()
95 ));
96
97 let metatypes_json_path = PathBuf::from(&format!("{}.json", output_path.display()));
98
99 let mut include_args = vec![];
100 for include_path in self
102 .qt_include_paths
103 .iter()
104 .chain(arguments.include_paths.iter())
105 {
106 include_args.push(format!("-I{}", include_path.display()));
107 }
108
109 for framework_path in &self.qt_framework_paths {
111 include_args.push(format!("-F{}", framework_path.display()));
112 }
113
114 let mut cmd = Command::new(&self.executable);
115
116 if let Some(uri) = arguments.uri {
117 cmd.arg(format!("-Muri={uri}", uri = uri.as_dots()));
118 }
119
120 cmd.args(include_args);
121 cmd.arg(input_path.to_str().unwrap())
122 .arg("-o")
123 .arg(output_path.to_str().unwrap())
124 .arg("--output-json");
125 let cmd = cmd
126 .output()
127 .unwrap_or_else(|_| panic!("moc failed for {}", input_path.display()));
128
129 if !cmd.status.success() {
130 panic!(
131 "moc failed for {}:\n{}",
132 input_path.display(),
133 String::from_utf8_lossy(&cmd.stderr)
134 );
135 }
136
137 MocProducts {
138 cpp: output_path,
139 metatypes_json: metatypes_json_path,
140 }
141 }
142}