@@ -33,6 +33,12 @@ mod parse_cflags;
3333mod platform;
3434pub use platform:: QtPlatformLinker ;
3535
36+ mod qml;
37+ pub use qml:: { QmlDirBuilder , QmlPluginCppBuilder , QmlUri } ;
38+
39+ mod qrc;
40+ pub use qrc:: { QResource , QResourceFile , QResources } ;
41+
3642mod tool;
3743pub use tool:: {
3844 MocArguments , MocProducts , QmlCacheArguments , QmlCacheProducts , QtTool , QtToolMoc ,
@@ -44,7 +50,6 @@ mod utils;
4450use std:: {
4551 env,
4652 fs:: File ,
47- io:: Write ,
4853 path:: { Path , PathBuf } ,
4954} ;
5055
@@ -150,7 +155,11 @@ impl QtBuild {
150155 qml_files : & [ impl AsRef < Path > ] ,
151156 qrc_files : & [ impl AsRef < Path > ] ,
152157 ) -> QmlModuleRegistrationFiles {
153- let qml_uri_dirs = uri. replace ( '.' , "/" ) ;
158+ let qml_uri = QmlUri :: new ( uri. split ( '.' ) ) ;
159+ let qml_uri_dirs = qml_uri. as_dirs ( ) ;
160+ let qml_uri_underscores = qml_uri. as_underscores ( ) ;
161+ let plugin_type_info = "plugin.qmltypes" ;
162+ let plugin_class_name = format ! ( "{}_plugin" , qml_uri_underscores) ;
154163
155164 let out_dir = env:: var ( "OUT_DIR" ) . unwrap ( ) ;
156165 let qt_build_utils_dir = PathBuf :: from ( format ! ( "{out_dir}/qt-build-utils" ) ) ;
@@ -159,65 +168,59 @@ impl QtBuild {
159168 let qml_module_dir = qt_build_utils_dir. join ( "qml_modules" ) . join ( & qml_uri_dirs) ;
160169 std:: fs:: create_dir_all ( & qml_module_dir) . expect ( "Could not create QML module directory" ) ;
161170
162- let qml_uri_underscores = uri. replace ( '.' , "_" ) ;
163- let qmltypes_path = qml_module_dir. join ( "plugin.qmltypes" ) ;
164- let plugin_class_name = format ! ( "{qml_uri_underscores}_plugin" ) ;
171+ let qmltypes_path = qml_module_dir. join ( plugin_type_info) ;
165172
166173 // Generate qmldir file
167174 let qmldir_file_path = qml_module_dir. join ( "qmldir" ) ;
168175 {
169- let mut qmldir = File :: create ( & qmldir_file_path) . expect ( "Could not create qmldir file" ) ;
170- write ! (
171- qmldir,
172- "module {uri}
173- optional plugin {plugin_name}
174- classname {plugin_class_name}
175- typeinfo plugin.qmltypes
176- prefer :/qt/qml/{qml_uri_dirs}/
177- "
178- )
179- . expect ( "Could not write qmldir file" ) ;
176+ let mut file = File :: create ( & qmldir_file_path) . expect ( "Could not create qmldir file" ) ;
177+ QmlDirBuilder :: new ( qml_uri. clone ( ) )
178+ . plugin ( plugin_name, true )
179+ . class_name ( & plugin_class_name)
180+ . type_info ( plugin_type_info)
181+ . write ( & mut file)
182+ . expect ( "Could not write qmldir file" ) ;
180183 }
181184
182185 // Generate .qrc file and run rcc on it
183186 let qrc_path =
184187 qml_module_dir. join ( format ! ( "qml_module_resources_{qml_uri_underscores}.qrc" ) ) ;
185188 {
186- fn qrc_file_line ( file_path : & impl AsRef < Path > ) -> String {
187- let path_display = file_path. as_ref ( ) . display ( ) ;
188- format ! (
189- " <file alias=\" {}\" >{}</file>\n " ,
190- path_display,
191- std:: fs:: canonicalize( file_path)
192- . unwrap_or_else( |_| panic!( "Could not canonicalize path {path_display}" ) )
193- . display( )
194- )
195- }
196-
197- let mut qml_files_qrc = String :: new ( ) ;
198- for file_path in qml_files {
199- qml_files_qrc. push_str ( & qrc_file_line ( file_path) ) ;
200- }
201- for file_path in qrc_files {
202- qml_files_qrc. push_str ( & qrc_file_line ( file_path) ) ;
203- }
204-
205- let mut qrc = File :: create ( & qrc_path) . expect ( "Could not create qrc file" ) ;
206189 let qml_module_dir_str = qml_module_dir. to_str ( ) . unwrap ( ) ;
207- write ! (
208- qrc,
209- r#"<RCC>
210- <qresource prefix="/">
211- <file alias="/qt/qml/{qml_uri_dirs}">{qml_module_dir_str}</file>
212- </qresource>
213- <qresource prefix="/qt/qml/{qml_uri_dirs}">
214- {qml_files_qrc}
215- <file alias="qmldir">{qml_module_dir_str}/qmldir</file>
216- </qresource>
217- </RCC>
218- "#
219- )
220- . expect ( "Could note write qrc file" ) ;
190+ let qml_uri_dirs_prefix = format ! ( "/qt/qml/{qml_uri_dirs}" ) ;
191+ let mut qrc = File :: create ( & qrc_path) . expect ( "Could not create qrc file" ) ;
192+ QResources :: new ( )
193+ . resource ( QResource :: new ( ) . prefix ( "/" . to_string ( ) ) . file (
194+ QResourceFile :: new ( qml_module_dir_str) . alias ( qml_uri_dirs_prefix. clone ( ) ) ,
195+ ) )
196+ . resource ( {
197+ let mut resource = QResource :: new ( ) . prefix ( qml_uri_dirs_prefix. clone ( ) ) . file (
198+ QResourceFile :: new ( format ! ( "{qml_module_dir_str}/qmldir" ) )
199+ . alias ( "qmldir" . to_string ( ) ) ,
200+ ) ;
201+
202+ fn resource_add_path ( resource : QResource , path : & Path ) -> QResource {
203+ let resolved = std:: fs:: canonicalize ( path)
204+ . unwrap_or_else ( |_| {
205+ panic ! ( "Could not canonicalize path {}" , path. display( ) )
206+ } )
207+ . display ( )
208+ . to_string ( ) ;
209+ resource
210+ . file ( QResourceFile :: new ( resolved) . alias ( path. display ( ) . to_string ( ) ) )
211+ }
212+
213+ for path in qml_files {
214+ resource = resource_add_path ( resource, path. as_ref ( ) ) ;
215+ }
216+ for path in qrc_files {
217+ resource = resource_add_path ( resource, path. as_ref ( ) ) ;
218+ }
219+
220+ resource
221+ } )
222+ . write ( & mut qrc)
223+ . expect ( "Could note write qrc file" ) ;
221224 }
222225
223226 // Run qmlcachegen
@@ -264,58 +267,12 @@ prefer :/qt/qml/{qml_uri_dirs}/
264267 let qml_plugin_cpp_path = qml_plugin_dir. join ( format ! ( "{plugin_class_name}.cpp" ) ) ;
265268 let include_path;
266269 {
267- let mut declarations = Vec :: default ( ) ;
268- let mut usages = Vec :: default ( ) ;
269-
270- let mut generate_usage = |return_type : & str , function_name : & str | {
271- declarations. push ( format ! ( "extern {return_type} {function_name}();" ) ) ;
272- usages. push ( format ! ( "volatile auto {function_name}_usage = &{function_name};\n Q_UNUSED({function_name}_usage);" ) ) ;
273- } ;
274-
275- // This function is generated by qmltyperegistrar
276- generate_usage ( "void" , & format ! ( "qml_register_types_{qml_uri_underscores}" ) ) ;
277- generate_usage (
278- "int" ,
279- & format ! ( "qInitResources_qml_module_resources_{qml_uri_underscores}_qrc" ) ,
280- ) ;
281-
282- if !qml_files. is_empty ( ) && !qmlcachegen_file_paths. is_empty ( ) {
283- generate_usage (
284- "int" ,
285- & format ! ( "qInitResources_qmlcache_{qml_uri_underscores}" ) ,
286- ) ;
287- }
288- let declarations = declarations. join ( "\n " ) ;
289- let usages = usages. join ( "\n " ) ;
290-
291- std:: fs:: write (
292- & qml_plugin_cpp_path,
293- format ! (
294- r#"
295- #include <QtQml/qqmlextensionplugin.h>
296-
297- // TODO: Add missing handling for GHS (Green Hills Software compiler) that is in
298- // https://code.qt.io/cgit/qt/qtbase.git/plain/src/corelib/global/qtsymbolmacros.h
299- {declarations}
300-
301- class {plugin_class_name} : public QQmlEngineExtensionPlugin
302- {{
303- Q_OBJECT
304- Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlEngineExtensionInterface")
305-
306- public:
307- {plugin_class_name}(QObject *parent = nullptr) : QQmlEngineExtensionPlugin(parent)
308- {{
309- {usages}
310- }}
311- }};
312-
313- // The moc-generated cpp file doesn't compile on its own; it needs to be #included here.
314- #include "moc_{plugin_class_name}.cpp.cpp"
315- "# ,
316- ) ,
317- )
318- . expect ( "Failed to write plugin definition" ) ;
270+ let mut file = File :: create ( & qml_plugin_cpp_path)
271+ . expect ( "Could not create plugin definition file" ) ;
272+ QmlPluginCppBuilder :: new ( qml_uri, plugin_class_name. clone ( ) )
273+ . qml_cache ( !qml_files. is_empty ( ) && !qmlcachegen_file_paths. is_empty ( ) )
274+ . write ( & mut file)
275+ . expect ( "Failed to write plugin definition" ) ;
319276
320277 let moc_product = self . moc ( ) . compile (
321278 & qml_plugin_cpp_path,
0 commit comments