Maurice Kalinowski

Introduction to Windows RT Frameworks

Published Friday June 14th, 2013
8 Comments on Introduction to Windows RT Frameworks
Posted in desktop, Qt, Windows | Tags: , , , , ,

It happens seldomly, but a couple of weeks ago I had the chance to look at some parts of the Windows Runtime port again and now I have some time to write about the outcome.

One of the tedious items when working on the port is that all applications have to be “pre-packaged” to be run on the host system. As this is not really a cross-compile environment, where you need to deploy an application and its dependencies to a device, it feels weird. On the other hand it reflects the real world scenario pretty well, which helps you as an app developer so that you do not forget to put items into the final package.
So right now the test build needs to look like this:

  • App.exe
  • AppManifest.XML
  • QtCore5d.dll
  • Platform/Imageformat plugins…

That implies that you need to copy Qt every time you want to test something. This usually is not a problem for an application developer, who copies Qt once. Doing that while developing on Qt itself is time consuming and error-prone, as for each test application you need to copy again.
Browsing through the documentation I found the following option to be interesting: “Framework

There is not much documentation about it, but what you basically can do is to create a “Framework bundle package” and install that. Applications can then specify in their manifest that they depend on it like documented here.

There is no real information available how we can deploy that to a store, but what it basically would provide is something similar to Ministro on Android, meaning a Qt delivery package, which only needs to be downloaded once. You can check on your system, which frameworks are installed by calling Get-AppXPackage on the Windows Power Shell. For each package there is a section called IsFramework. Parsing through that you will figure out that only the C-runtime is deployed currently as a framework, which proves that there is no documentation for good reason.

First let me describe how you can create a framework and how you depend on it before I will talk about the problems and why we cannot use it.

To prepare packaging you will need a certificate to sign your framework, you create it like that (in an Admin shell!!):

 MakeCert /n "CN=QtProject, O=QtProject, L=Berlin, S=Berlin, C=Germany" /r /h 0 /eku "1.3.6.1.5.5.7.3.3,1.3.6.1.4.1.311.10.3.13" /e 06/06/2013 /sv qtkey.pvk qtkey.cer

Write down the company specification, you will need it again at a later step.
Now let’s create the pfx file, again you need to be admin:

Pvk2Pfx /pvk qtkey.pvk /pi <password> /spc qtkey.cer /pfx qtkey.pfx /po <password>

<password> specifies the password you gave to the certificate in the first step.
Following we will create the framework bundle and install it to the system:

  1. Move all files you need to a directory where you do the packaging
  2. Create your ApplicationManifest.xml file and remember to specify the same company details as in the certificate above. Otherwise signing will fail!
  3. Create an framework package:
    makeappx pack /d package /h SHA256 /p qt5.appx
  4. Sign the package:
    SignTool sign /a /v /fd SHA256 /f qtkey.pfx /p <password> qt5.appx
  5. Add yourself to the trusted area, otherwise Windows does not allow to side load the framework:
    Certutil -addStore TrustedPeople qtkey.cer
  6. Finally install the package to the system:
    Add-AppxPackage .\qt5.appx

So, we have Qt5 installed as a framework, now what? To make use of that in the application, your application needs to specify Qt as a dependency in the manifest. Please note that you have to specify the minimum version correctly, you cannot just depend on Qt5 in general.
In case you want to update the Qt5 package you must update the Qt Version number in the manifest. Windows does not allow to just exchange the package! Afterwards call makeappx/SignTool/Add-Appxpackage as described above. As you specified the minimum version in your application, it will automatically use that. However, you will need to update the version each time you try to update the registered Qt version.

Secondly, in case you remove the application, Qt will be deleted as well. As soon as no application depends on a framework, it is gone. And installing an application depending on Qt5 does not work, as there is no source information where to retrieve it from. Luckily the install steps are the same for first install and update install. Hence you will not notice this fact most of the time.

Also note that compared to application packages you cannot use “-Register”. This options allows application developers to use a directory as a virtual package. It does not enforce you to bundle the application etc. But as stated, for Frameworks this does not apply. You have to fully package, sign and install Qt, there is no development version or such. However, debugging into the framework works.

So there are already a lot of steps required to use Qt as a framework, but still we achieved the scenario we wanted to have. Exchanging Qt is (relatively) simple and we could run the test apps against that without requiring to reinstall them all the time. Let us now go into further downsides of the frameworks:

What I have been curious about is how you parse the content of a framework. To summarize: you don’t! You can only take what is inside the root directory and then you can also have libraries there only. Those libraries are then added to the resolving order for dependencies.
So, if your app bundle depends on the Qt5 framework, when you launch your app the system will figure it requires for instance Qt5Core.dll. After not finding it in the app bundle, it checks the Qt5 framework, locates it in the root folder and resolves it. For libraries everything is fine. But what about plugins? You cannot specify to search inside a “platforms” directory inside the Qt5 framework. Everything outside the root directory of a framework is just wasted space.

Exaggerating the approach with frameworks, you could consider frameworks for each plugin. Then your app manifest could specify the plugins to use: “jpeg image handler, sql database, winrt platform plugin”. It could actually simplify deployment as there is nothing you can miss during development, but it would cause troubles for startup times etc. Remember that all dependencies must be in the root directory. So if the plugins are scanned it would need to scan through all dlls in all frameworks, including Qt libraries, different plugins and fitting plugins.

So you could still bundle the plugins inside the application package and have the Qt libraries inside the framework. This might work as long as we assume there is no behavior difference between different versions, nor compatibility breaks. Also, it does not help in our initial problem, meaning to speed up Qt development itself. So we are at a dead-end here.

The result of this far too long entry? Frameworks seem to be an interesting approach, but they do not fulfill our needs for development on Qt, neither for application developers using Qt. At least right now, documentation is lacking, public information is basically non-existent. Certainly the concept is a good starting point, but there is quite some steps missing. In addition to this, there have been some efforts towards implementing a command line tool, which helps you as a developer to get all files and dependencies on Windows (and Windows RT) in place, namely windeployqt. For those of you interested it works fairly well inside the port and also for Qt5 based desktop applications already and we will put some further efforts into finalizing this one.

 

Do you like this? Share it
Share on LinkedInGoogle+Share on FacebookTweet about this on Twitter

Posted in desktop, Qt, Windows | Tags: , , , , ,

8 comments

rubi says:

First – I like very much the port efforts on WinRT, and I hope that you’ll find the right “hack” (Driver developer kit?) to do C++ development faster.
Yet.. why both here, and Android Ministro are focused providing QT as DLL? Best thing is just to .. oh well.. compile with static libraries. Is it a legal issue? Because, frankly, I don’t give a damn if my application is 50M in size, I just don’t want the poor user to have to deal with another download/service. Moreover, this can only lead to a DLL HELL..
I personally would cancel all dlls everywhere 🙂 but especially with such delicate ports.. can’t we just provide a compiled app? wouldn’t that be the best?

Of c

Maurice says:

@rubi

First of all, I mentioned Ministro as an example. We surely would not invest in another downloading server. My expectation is that the Microsoft store offers something alike as soon as you can distribute frameworks.

It is good to hear that size of the packages is not an issue for you, but for many it is. So asking the user to download Qt only once and then reuse it, is an often requested feature.

And lastly, while the investigation went also into the deployment scenario, it mostly has been about “How can we (re-)compile Qt and reuse testing apps without the need to repackage all of them again and again.

Witold says:

There is also a matter of memory usage. With static libraries each app will have a private copy of the library while when shared objects are used, the library is loaded into memory only once for all processes currently using it thus decreasing memory footprint (hence the name “shared library”). Considering that Qt libraries are not that small in size this makes a significant difference.

Maurice says:

@Witold

I am not sure about that one due to the sandboxing inside Windows RT. But it also an area to check, thanks for mentioning it.

Chris says:

You are only looking at part of the problem. In my case, I need to send programs to customers over and over again over a yearly period. If I move to qt 5.0.3 do I then need to send all of qt again? (windows environment).
The qt static build is huge compared to others on the market. I can only assume this is due to large source files going to large object files. Yet looking at ALL the objects created in a static build it is only 9Meg.

Doing a basic hello world gui application in qt linked statically with minimal stuff included ended up being 11 meg. Compare that to embarcadaro (ne borland) with a fully loaded application at 6 meg. I don’t know what’s going on here to create the huge file difference.

I would expect my app (.5 Meg) + minimal qt core stuff to be less then 11 meg.

Rubi says:

AFAIK compiled/linked application size (linked against static libraries) does not get your application as the size of the static libraries. In fact with the correct compiler switches (function level linking) you can get only the functions you need from the static libraries into your compiled exe. Nothing near 1Mb or even 100Kb for a hello world application, nor for a slightly more complex one. Static linking is by far the best method also with regard to RAM consumption (DLL’s are fully loaded into memory, whereas static libraries are only there at link time).

So Maurice & Chris you did not convince me at all. Sorry.. You might want to do your tests again.. There is no way a well linked static application will consume more memory than a DLL. This is just against all reason. And I didn’t even start to talk about compatibility issues..

Kuba Ober says:

I wouldn’t use the term “huge difference” unless we’re talking at least of an order of magnitude. There’s merely a factor of two difference between 6 and 11. Never mind that the scope and functionality offered by both frameworks I’m sure differs, um, a bit.

Mika says:

Lets get used up t0 d bbbone in here this week, shall we!!!

Commenting closed.

Get started today with Qt Download now