6.0.0-rc4Source

The Nt Resource System

Compiling files into a program with ntrcc and reading them with QFile.

Resources are files, such as icons, translations or default settings, that are compiled into the program so that it does not need to find them on disk at run time. Nt reads the Qt resource collection files (.qrc) that Qt projects already have, and compiles them with ntrcc, its replacement for Qt's rcc.

Resource Collection Files

A .qrc file is XML. Each <qresource> element puts the files it lists below its prefix; each <file> names a file relative to the .qrc file, and its alias attribute gives it another name. A directory is added with every file in it, except hidden ones.

<!DOCTYPE RCC>
<RCC version="1.0">
    <qresource prefix="/">
        <file>icons/open.svg</file>
        <file alias="config.json">defaults/config-1.2.json</file>
        <file>themes</file>
    </qresource>
    <qresource prefix="/text" lang="fr">
        <file alias="welcome.txt">welcome_fr.txt</file>
    </qresource>
</RCC>

Compression

ntrcc compresses a file when that makes it at least 70% smaller, with Zstandard if Nt was built with libzstd, otherwise with zlib. QFile decompresses a resource into memory when it opens it, so code that reads resources does not change. The attributes of a <file> override the command line for that file:

<file compression-algorithm="zlib" compress="9">data/catalog.json</file>
<file compression-algorithm="none">images/photo.jpg</file>
<file threshold="20">help/index.html</file>

compression-algorithm is zstd, zlib, best or none; compress is the level (1 to 9 for zlib, 1 to 22 for Zstandard, -1 for the default, 0 for none); threshold is the percentage a file must shrink by. Files that are already compressed, such as PNG or JPEG images, rarely pass the threshold and are stored as they are.

zlib and libzstd are found when Nt is configured; turn them off with -DNT_USE_ZLIB=OFF and -DNT_USE_ZSTD=OFF. A build without an algorithm cannot read resources compressed with it, and its ntrcc refuses to write them.

Locales

The lang attribute makes a variant for one language (fr) or one language and territory (fr_FR). A file is read in the variant that best fits the locale: one for the language and territory, then one for the language, then one without lang.

Building with CMake

The helpers are in NtRcc.cmake, which the Nt6 package includes. Either list the .qrc file among the sources and turn on AUTORCC:

add_executable(viewer main.cpp viewer.qrc)
target_link_libraries(viewer PRIVATE Nt::Core)
nt_enable_autorcc(viewer)

or compile it explicitly, as qt_add_resources() does:

nt_add_resources(viewer_resources viewer.qrc)
add_executable(viewer main.cpp ${viewer_resources})

The Qt 6 form names the files in CMake and needs no .qrc file. Each file is named by its path relative to BASE, or by its QT_RESOURCE_ALIAS source file property:

nt_add_resources(viewer icons PREFIX /icons BASE art FILES art/open.svg art/save.svg)

nt_add_binary_resources() writes a binary .rcc file instead, to be loaded at run time with QResource::registerResource(). Unless Qt's own are defined, qt_add_resources(), qt6_add_resources(), qt_add_binary_resources() and qt6_add_binary_resources() are the same functions, and Qt6::rcc is ntrcc, so CMAKE_AUTORCC finds it.

Using Resources

A resource path starts with a colon. QFile opens it for reading, QFileInfo describes it, and QDir and QDirIterator list resource directories:

QFile file(":/config.json");
if (file.open(QIODevice::ReadOnly))
    settings = QJsonDocument::fromJson(file.readAll());

for (const QString &name : QDir(":/icons").entryList(QDir::Files))
    addIcon(name);

Resources cannot be written, removed or renamed. QResource reads the bytes of a resource without opening it, and registers .rcc files.

Resources compiled into an executable are registered when the program starts. Resources in a static library are registered only if their object file is linked, so call Q_INIT_RESOURCE(name), with the base name of the .qrc file, from a function in the global namespace such as main(). Q_CLEANUP_RESOURCE(name) undoes it.

Search Paths

QDir::setSearchPaths() gives a list of directories a name prefix, and the directories can be resource directories. A name such as icons:open.png then refers to the first open.png in the list, so files on disk can override resources:

QDir::setSearchPaths("icons", QStringList() << QDir::homePath() + "/.viewer/icons" << ":/icons");
QFile icon("icons:open.png");

QFile, QFileInfo, QDir and QDirIterator all understand prefixes, and QDir::addSearchPath() appends to a list. A file that exists in none of the directories is created in the first one, if it can be written.

Running ntrcc

ntrcc [options] <inputs.qrc>...

qCleanupResources_<name>(), used by the macros. The default is the base name of the first input.

resource paths for --list-mapping.

default) or none.

<percent> of it (70 by default).

Single dashes work as well as double ones, as with rcc. When SOURCE_DATE_EPOCH is set, the time stamps of the resources are clamped to it, for reproducible builds.

Differences from Qt

Compression needs zlib or libzstd when Nt is built, and the default Zstandard level is 14. The compiled format is Nt's own, so .rcc files from Qt's rcc cannot be registered, and Nt's cannot be read by Qt. QResource has no search paths of its own, as in Qt 6: use QDir::setSearchPaths(). The qrc: URL scheme is not understood by QFile. Resources and their directories are listed in name order. The BIG_RESOURCES option and OUTPUT_TARGETS of qt_add_resources() are accepted and have no effect.

See also QResource, QFile and QDir.