Qt QML Hot Tips #7
Mike Trahearn - Qt QML Hot Tips

Qt QML Hot Tips #7

Part 7 - Does my RCC look BIG in this?

Or, "How to handle your large assets"....

How does one answer that tactfully? ;-)

Have you ever stuffed your QRC face with chubbyBunnies.gif or donutEatingComp.mov or anything else that instantly bloats out your sugar-laden resources and kills your compile time or even just kills your compiler?

A real example might be adding unicode fonts which can be quite large or a set of images for the Qt Quick Controls Imagine Style or sets of multi-resolution images for large retina displays. These can make some compilers fall over or, if they don't, they take an age to crunch through the bits.

Fortunately Qt has a solution: you can use RCC to embed and compile your big files as part of a two-step process which not only gets past the compiler limitation problems, it is magnitudes faster!

QMake Solution

CONFIG += resources_big

# yeah, not big_resources... hmm        

That's it, barring a possible call to Q_INIT_RESOURCE(yourResource) if you need to - there are cases where you don't.

But what about CMake? That's where it gets a little more interesting - and fun!

CMake Solution

Before I go on, I'll assume familiarity with QML Modules as per Qt 6.2 onwards and using Qt 6.5 and CMake 3.23 although the solutions here are not limited to QML Modules.

To start with, here's a quick example of a testApp with a QML Module carrying a large file in its RESOURCES:

qt_add_executable(testApp
   main.cpp
)

qt_add_qml_module(testApp
??URI TestApp
??AUTO_RESOURCE_PREFIX # :/qt/qml
??VERSION 1.0
?QML_FILES
??   main.qml
??RESOURCES
???? MassiveUnicodeFont.otf
)        

The compiler will crawl over the font as it tries to pull in the file into the QML Module's resources. So long as you don't need to do that too often, this works, but as you add more and more QML files, your incremental build time for a one line change will include recompiling that big font over and over again since it is in the same generated QRC file as the QML files. That's if your compiler doesn't die trying when it runs out of space processing the file.

Solution 1: Place your big files in a separate QRC file and process it separately.

  1. We make a new file fonts_large_resources.qrc, and set its internal prefix to match the FULL QRC path of the QML Module i.e. "/qt/qml/TestApp" and add the font file under that prefix.
  2. Remove the font file entry from the QML Module RESOURCES list
  3. add the following command: qt_add_big_resources(FONTS_LARGE_RESOURCES fonts_large_resources.qrc)
  4. To see the QRC's files in the project tree, we need to add a list:
  5. list(APPEND FONTS_LARGE_RESOURCES fonts_large_resources.qrc)
  6. Tell RCC not to process this QRC in the same way as would be usual:
  7. set_source_files_properties(fonts_large_resources.qrc PROPERTIES SKIP_AUTORCC ON)
  8. Add the generated sources to your QML Module (shown below)
  9. Somewhere in your code you need to Q_INIT_RESOURCE(fonts_large_resource) to be able to access the files in the resource system at run time. This is because we only add the generated SOURCES but nothing else.

This results in the following CMake code:

qt_add_executable(testApp
   main.cpp
)

qt_add_big_resources(FONTS_LARGE_RESOURCES 
   fonts_large_resources.qrc
)

list(APPEND FONTS_LARGE_RESOURCES 
   fonts_large_resources.qrc
)

set_source_files_properties(
   fonts_large_resources.qrc 
   PROPERTIES
      SKIP_AUTORCC ON
)

qt_add_qml_module(testApp
??URI TestApp
??AUTO_RESOURCE_PREFIX # :/qt/qml
??VERSION 1.0
  SOURCES
?    ${FONTS_LARGE_RESOURCES}
 ?QML_FILES
??   main.qml
)

# Q_INIT_RESOURCE(fonts_large_resource) required in the source code        


Solution 2: Target Based Approach

In my view, Solution 1 contains far too many steps which are all trying to get things to do what we want.

However I offer you Solution 2 and the reason for this Qt QML Hot Tips!

Start with the following simple setup:

qt_add_executable(testApp
   main.cpp
)

qt_add_qml_module(testApp
??URI TestApp
??AUTO_RESOURCE_PREFIX # :/qt/qml
??VERSION 1.0
?QML_FILES
??   main.qml
)        

Then we add the magic:

qt_add_resources(testApp "testApp_large_resources"
??PREFIX /qt/qml/TestApp
??BIG_RESOURCES
??FILES
????MassiveUnicodeFont.otf
)        

That's it. Really!

The above adds additional resources to the target "testApp", gives it a name (for code generation), tells RCC to use the BIG_RESOURCES two-step process over the specified FILES and builds them into your binary already initialised.

  • You DO NOT have to Q_INIT_RESOURCE anything - it is done for you
  • You DO NOT have to list() the files for the project tree - it is done for you
  • You DO NOT need to manually create a QRC file - it is done for you
  • You DO NOT need to SKIP_AUTO_RCC because - it is (implicitly) done for you - since you are not adding any QRC files to any target SOURCES property of any QML Module declaration

FOUR nice big DO-NOTs and whole heap of icing!

Better than a box of Krispy-Kremes.

Summary

qt_add_resources( <target> ... BIG_RESOURCES) gives you a really simple way to separate your big resources in your CMake file in one well organised place and get all the benefits of faster compiler time, auto initialisation and a much better development experience without having to do any the work!

Happy cake eating!

Mike Trahearn

Qt Champion??????, Qt QML C++ Specialist, Director, Codecept Software Pty Ltd; A Unique Thinker, Detailed Craftsman with Precise Foresight and a Personal Approach

1 年

As of Qt 6.5 AUTO_RESOURCE_PREFIX is gone and you need to make the following well explained slight adjustments - which, if you read well enough, are big enablers! https://www.qt.io/blog/whats-new-for-qml-modules-in-6.5 Additionally, the added resource command could share a common variable for the resource prefix with the target's resource prefix to avoid duplication and possible error.

回复

要查看或添加评论,请登录

社区洞察

其他会员也浏览了