RCCExtensions: Difference between revisions
(Created page with "= Extending the Qt Resource System = The Qt resource system was designed to embed arbitrary files into the program executable (or library) and provide convenient access to th...") |
|||
(3 intermediate revisions by one other user not shown) | |||
Line 1: | Line 1: | ||
= Extending the Qt Resource System = | == Extending the Qt Resource System == | ||
The Qt resource system was designed to embed arbitrary files into the | The Qt resource system was designed to embed arbitrary files into the | ||
Line 27: | Line 27: | ||
processing to the extension program according if the configuration | processing to the extension program according if the configuration | ||
matches. | matches. | ||
It is not a goal to create a fully-fledged build system inside rcc. It | |||
is important to limit the functionality to only support common use-cases | |||
and avoid creating a generic build system that may also end up building your | |||
Linux kernel. | |||
The following sections briefly outline some of the common anticipated | The following sections briefly outline some of the common anticipated | ||
Line 161: | Line 166: | ||
specify overrides. | specify overrides. | ||
The build system calling rcc shall pass the path to the target | <strike>The build system calling rcc shall pass the path to the target | ||
"makespec", where further configuration files can be located. In | "makespec", where further configuration files can be located</strike> NO, this makes rcc build-system specific; Qbs will not use mkspecs in the long term, or they may at least be optional.</nowiki> | ||
In | |||
addition variables such as symbolic name for the deployment target (such | addition variables such as symbolic name for the deployment target (such | ||
as QMAKE_IOS_DEPLOYMENT_TARGET) could be forwarded by the build system | as QMAKE_IOS_DEPLOYMENT_TARGET) could be forwarded by the build system | ||
Line 169: | Line 176: | ||
=== Native resource systems === | === Native resource systems === | ||
Target platforms such as iOS provide the developer with a system similar | Target platforms such as Apple platforms (macOS, iOS, tvOS, watchOS) provide the developer with a system similar | ||
to the Qt resource system that can take care of slicing the actual | to the Qt resource system that can take care of slicing the actual | ||
resource data depending on the target device automatically. For example | resource data depending on the target device automatically. For example | ||
on | on Apple platforms the asset catalogs can be configured to group images for x2 and | ||
x3 screen resolutions accordingly, Apple transparently then slices the | x3 screen resolutions accordingly, Apple transparently then slices the | ||
data at application | data at application installation time and the NSImage/UIImage API (for images), NSColor/UIColor (for colors), or NSDataAsset API (for other raw data files) provides the correctly sliced data transparently to the developer. | ||
provides the correctly sliced data transparently to the developer. | |||
Automatic use of such facilities can be integrated into the Qt Resource | Automatic use of such facilities can be integrated into the Qt Resource | ||
System as an rcc extension by means of external binary resource files. | System as an rcc extension by means of accessing external binary resource files via the native platform APIs. | ||
The rcc compiler can be configured to produce different binary resource | The rcc compiler can be configured to produce different binary resource | ||
files for each requested flavor and use the native resource system to | files for each requested flavor and use the native resource system to | ||
include these resource files accordingly. With iOS as target, the | include these resource files accordingly. With macOS, iOS, tvOS, or watchOS as target, the | ||
slicing would then result in the | slicing would then result in the production of an additional binary resource file (Assets.car) which gets deployed in the app bundle's resources directory, by producing an asset catalog containing a subset of the inputs and invoking the actool compiler to transform it, and the rcc asset catalog extension could provide rcc with the stub C++ loader code that would be compiled into the final executable (or as part of QtCore) that uses the native API to get hold of the binary resource file, image, or color. | ||
stub C++ loader code that would be compiled into the final executable | |||
that uses the | |||
Finally that resource file data is registered with | Finally that resource file data is registered with | ||
QResource::registerResource() and the data becomes available | QResource::registerResource() and the data becomes available | ||
transparently to the Qt developer via the Qt resource system API. | transparently to the Qt developer via the Qt resource system API. | ||
=== Comments === | |||
Perhaps the file names in the resource system should never be replaceable. | |||
So the option of renaming as per the first example could be replaced with | |||
a simpler mechanism where the content of the original .png file is replaced | |||
with textual content (json?) that provides the names of the etc1 files to | |||
the QtQuick run-time. | |||
=== Final notes === | === Final notes === |
Latest revision as of 21:44, 19 December 2017
Extending the Qt Resource System
The Qt resource system was designed to embed arbitrary files into the program executable (or library) and provide convenient access to the data using familiar interfaces (QFile) and using resource paths as identifiers.
This proposal suggests to add an extension mechanism the Qt resource system, to make it possible to optimize the resources for target environment specific conditions. For example an image handling extension could be used for embedded target platforms to replace the use of .png image files with a GPU specific texture compression file format, transparently for the developer. Another example is an extension that would react to .qml and .js files and compile them ahead of time into a more efficient binary representation, for embedding in the program executable.
Extensions to rcc consists of a command line tools as well a configuration file that's installed into a directory that rcc reads.
The configuration file tells rcc about the extension's capabilities in terms of acceptable input file formats, output formats and conversion options.
When rcc processes files specified in the .qrc files, it inspects the file name extensions as well as general attributes and delegates processing to the extension program according if the configuration matches.
It is not a goal to create a fully-fledged build system inside rcc. It is important to limit the functionality to only support common use-cases and avoid creating a generic build system that may also end up building your Linux kernel.
The following sections briefly outline some of the common anticipated use-cases for rcc extensions.
Simple filter processing
The simplest way of extending the resource system is to transform an input file to a new file format and ask the Qt resource system to embed that alternate format instead. The extension program acts as single pass filter.
The input to the extension program is
(1) the path of the file in the virtual resource file system (2) the path of the input file on the real file system
Correspondingly, the output is
(3) the potentially new file name of the converted resource in the resource system (4) the alternate content to embed in the program executable by rcc instead.
The configuration file for such a filter extension could look like this:
{ "name": "etc2-converter", "input-formats": ["png", "jpg"], "output-formats": "["etc1", "etc2"], }
Determining the output (3) and (4) is done by calling the extension program twice, once with the "process-file-name" sub-command and once with the "process-data" sub-command.
For the example with a texture compressor that replaces .png input files with .etc1 compressed textures, the two calls could look like this:
rcc-extension-png process-file-name --resource-path="/path/in/resources.png" --local-file-path="/Users/qt/dev/something/photo.png"
prints
/path/in/resources.etc1
on stdout. Then rcc calls
rcc-extension-png process-data --resource-path="/path/in/resources.png" --local-file-path="/Users/qt/dev/something/photo.png" --output-file="/tmp/XZY1234"
and the extension program would write the etc1 compressed texture data into the provided temporary file. Finally rcc would embed that binary data in the program executable under the path provided in the first call.
Combined processing
A more advanced use-case for resource pre-processing is to combine multiple images into so-called atlas textures. This poses three additional requirements to the rcc extension mechanism:
(1) The ability to process multiple files in one go, to determine which files are suitable for atlas embedding and which ones are not. (2) The ability to combine files of different formats (different file extension) into the same output. (3) The ability to replace the content of the original files in the future virtual file system with information that leads to the new location within the atlas.
The configuration file for such an atlas extension could look like this:
{ "name": "atlas-compressor", "input-formats": ["png", "jpg"], "output-formats": ["png", "jpg"], "combine-input": true, "provides-substitutes": true, }
Similarly to the single file conversion, rcc would call the atlas compressor first to determine the file mapping:
rcc-extension-atlas process-file-names --resource-paths=/path/to/temporary/file_with_all_matching_file_paths.txt --local-file-paths=/path/to/temporary/file_with_all_matching_real_paths.txt
prints first the virtual file name of the atlas file, followed by all the files that are part of the atlas:
atlas1.png smallimage1.png anotherphoto2.png thirdonefitsaswell.png
If the compressor decides to produce multiple atlas files, two newlines are used to separate the different atlas files and their group. So the output could continue with two newlines, followed by
atlas2.png image4.png image5.png
and finally any files for which the atlas compressor decides that they are not suitable, the output shall be two newlines followed by a single dash, a newline and the remaining file names:
- doesnotfintintoatlas.png notsuitedeither.png
Based on this output, rcc can determine the groups of files that belong into an atlas and call the atlas compressor again for each group:
rcc-extension-atlas process-data --file-group=/path/to/file_with_output_of_first_group.txt --output-file="/tmp/XZY1234" --replacement-content="/tmp/5678XZY"
The output file shall be the encoded output file atlas image and the replacement content shall be textual separate with newline characters per file.
Target specific optimizations
There exists a need to configure certain defaults for the convenience of the user. For example a texture compression converter needs to know which type of format the target GPU supports. We need the ability for Qt to provide defaults as well as the possiblity for the developer to specify overrides.
The build system calling rcc shall pass the path to the target
"makespec", where further configuration files can be located NO, this makes rcc build-system specific; Qbs will not use mkspecs in the long term, or they may at least be optional.</nowiki>
In addition variables such as symbolic name for the deployment target (such as QMAKE_IOS_DEPLOYMENT_TARGET) could be forwarded by the build system to the command line as --deployment-target="$VALUE_THAT_APPLIES" .
Native resource systems
Target platforms such as Apple platforms (macOS, iOS, tvOS, watchOS) provide the developer with a system similar to the Qt resource system that can take care of slicing the actual resource data depending on the target device automatically. For example on Apple platforms the asset catalogs can be configured to group images for x2 and x3 screen resolutions accordingly, Apple transparently then slices the data at application installation time and the NSImage/UIImage API (for images), NSColor/UIColor (for colors), or NSDataAsset API (for other raw data files) provides the correctly sliced data transparently to the developer.
Automatic use of such facilities can be integrated into the Qt Resource System as an rcc extension by means of accessing external binary resource files via the native platform APIs.
The rcc compiler can be configured to produce different binary resource files for each requested flavor and use the native resource system to include these resource files accordingly. With macOS, iOS, tvOS, or watchOS as target, the slicing would then result in the production of an additional binary resource file (Assets.car) which gets deployed in the app bundle's resources directory, by producing an asset catalog containing a subset of the inputs and invoking the actool compiler to transform it, and the rcc asset catalog extension could provide rcc with the stub C++ loader code that would be compiled into the final executable (or as part of QtCore) that uses the native API to get hold of the binary resource file, image, or color. Finally that resource file data is registered with QResource::registerResource() and the data becomes available transparently to the Qt developer via the Qt resource system API.
Comments
Perhaps the file names in the resource system should never be replaceable. So the option of renaming as per the first example could be replaced with a simpler mechanism where the content of the original .png file is replaced with textual content (json?) that provides the names of the etc1 files to the QtQuick run-time.
Final notes
This draft is by no means intended to be a final specification. Instead it serves as material to iterate on, in order to refine for example the communication between rcc and the extension programs. Finally it can serve as input to the documentation for the rcc extension feature for the Qt documentation.