So, our Boss came in to check on our progress. They were starting to wonder why it takes a whole day to port a 3 lines application to a new system. But the real reason of their visit was to ask for a new feature. While our “Hello world” business is booming, the marketing department thinks the lack of graphical UI is hurting sales.

See, nobody escapes software bloat.

Still. Eager to make the boss forget the time it takes to setup MSVC on Linux, I went above and beyond and completed a full rewrite of our app.

Of course, we also provide a small nifty build file.

QBS is love, QBS is life. CMake is definitively Shrek 👹

The Linux version is still building fine. Duh

The author likes to pretend all Linux machines are born with Qt And QBS installed. Just play along.

In case of nuclear disaster, click “no”

Let’s enthusiastically build the Windows version

Not so Qt.

Yeah, turns out, we need a build of Qt compatible with our compiler. Right now, even QBS doesn’t know about Qt.

I went to download Qt on https://www.qt.io/download. That site is getting worse by the day. The Qt company tries to dissuade people to get the open source version. But if you go to https://download.qt.io/ you have all the tarballs and installers.

Speaking of installers, they do not offer a 64 bits version for Windows. in 2018. We may have to restrict ourselves to 32 bits builds and extract that with WINE. Except it doesn’t work because the Qt installer framework has no silent mode ( apparently, you can script a silent mode in 100 lines of JavaScript ) and uses some Windows methods unsupported by WINE.

Nevermind. I will build Qt myself to prove how awesome my WINE toolchain is. And it will be 64 bits. I’ll get promoted and the intern who has 4 PHD will bring me cappuccinos. Maybe people will even use my name as a verb ( If you don’t Godbolt yet, you should definitively check it out !).

Except. Qt still uses qmake to build itself. And qmake exists only to make cmake look cool and modern. There is an ongoing effort to build Qt with qbs and while this is very exciting, it may be a bit too cutting edge, even for this blog.

So, we are stuck with qmake . qmake is a build system generator which unfortunately conflates toolchains and build systems. I did attempt to create configuration for my wine toolchain, it was actually rather simple, and it did generates some Makefiles with the proper commands. But they were Makefiles for nmake which is a make-like tool for windows albeit with a format that is not quite compatible with the original make. I tried using nmake (which works fine) but then all the subsequents cl.exe / link.exe calls happen in the wine environment which means it executes the actual cl.exe rather than our wrapper and so our crude slashes-to-backslashes transformation script never gets run and the compilation fails because cl.exe assumes anything starting with / is an option. And we can’t get nmake to call our fake cl.exe wrapper since nmake is a windows process and windows doesn’t know about ELF.

It is left as an exercise to the reader to calculate how many millions of dollars Windows using \ as a path separator and is costing the industry.

The solution would be to patch qmake . Which even the maintainer of qmake actively avoid to do. So let’s not do that.

I’m very sorry, but we will go back to our Windows VM and build Qt from there.

That should be simple, right ?

Of course, the VC build tools are unable to set up their environment properly.

How many Microsoft Engineers does it take to set up a build environment ? Certainly quite a few, since I was able to find about 1900 lines of batch scripts serving that purpose, in 20 or so files. There are probably more.

I manage to get my environment sorted in 3 lines. Remember, regardless of how complex your build system is, it boils down to a handful of variables. A compiler doesn’t needs much.

set "INCLUDE=C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Tools\MSVC\14.12.25827\include;

%INCLUDE%"

set "LIB=C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Tools\MSVC\14.12.25827\lib\x64\;%LIB%"

set "PATH=%PATH%;C:\Users\cor3ntin\Documents\qtbase-everywhere-src-5.10.0\gnuwin32"

After that, it was a matter of downloading Qt 5.10 setting up a x64 build environment ( I used vcvars64.bat + the three lines above, but you can set up PATH manually and not bother with vcvars.bat at all).

Make sure perl is installed and in the PATH .

For the purpose of this article, I only need Qt Base (Core, Gui, Network… ) so that’s what I’m building. Building QtWebEngine - which uses chromium - is a bit more involved.

configure -release -opensource -confirm-license -platform win32-msvc -nomake examples -nomake tests

nmake

nmake install

Once Qt has done building, copy the folders back to your linux host. You need at least bin, include, lib, plugins . put them in a new directory. I called mine qt5_10base-x64 .

I had issues with the includes referencing src . So you can run perl bin\syncqt.pl -copy -windows -version 5.10.0 -outdir cpy from the Qt directory on windows and use the include folder generated in cpy . Even then I had to copy a few files manually ( qconfig.h, q{core,gui,widgets,network,xml}-config.h) from the src folder to their respective include folder. Definitively a bit fiddly but eventually you will get there.

My Linux is slowly morphing into a Windows Box. I expect Clippy to appear at any moment now.

So now we have Qt. But how can we tell QBS to actually use it ?

The profile system of QBS is one of the things that make it great. You can set up compiler toolchain globally and switch from one to another effortlessly.

However to works with Qt, qbs needs a complete set of modules per profile. The gcc profile we used earlier is made of 160 qbs files setting each Qt library and component.

Fortunately, all you need to do is to call this handy tool.

qbs-setup-qt -h

This tool creates qbs profiles from Qt versions.



Usage:



qbs-setup-qt [--settings-dir <settings directory>] --detect



qbs-setup-qt [--settings-dir <settings directory>] <path to qmake> <profile name>



qbs-setup-qt -h|--help



The first form tries to auto-detect all known Qt versions, looking them up via the PATH environment variable.



The second form creates one profile for one Qt version.

Except we can’t call that tool from linux because the built qmake is a windows application expected to run on Windows. Hopefully, someday we will get rid of qmake entirely, but for now, back to our Windows machine.

We first install a windows build of qbs and run the tool.

qbs-windows-x86_64-1.10.0\bin\qbs-setup-qt.exe --settings-dir . bin\qmake.exe msvc14-x64-qt

That should create a qbs folder with the proper Qt configuration. Move that folder to your linux machine in the qt5_10base-x64 folder created earlier.

If you open on of the .qbs file, say 1.10.0/profiles/msvc14-x64-qt/modules/Qt/gui/gui.qbs , you will notice a reference to a path. For some reason, in mine it’s /usr/local/Qt-5.10.0 . I guess I messed up somewhere since we should have a windows path. In any case we need to transform that path to the actual locations of Qt on our Linux machine, which is easy to do, just use sed .

find -name "*.qbs" -exec sed -i -e 's\#/usr/local/Qt-5.10.0\#/home/cor3ntin/dev/cross-compilers/windows/qt-5.10-msvc-x64\#g' {} \;

We then need to modify our qbs.conf to use those qt modules. Edit the QBS file created in part one to reference them:

qt-project\qbs\profiles\msvc14-x86_64\preferences\qbsSearchPaths=/home/cor3ntin/dev/Qt/qbs-wine-toolchain,/home/cor3ntin/dev/cross-compilers/windows/qt5_10base-x64/qbs/1.10.0/profiles/msvc14-x64-qt

I realize it’s all a bit tricky. Eventually though, we can run qbs and it compiles our Qt-based hello world for Windows.

It won’t run because it can’t find the Qt dll. You can either copy the dll to the build directory, or make sure they are in the PATH. The windows/wine PATH that is.

The only way I found to do that is to run regedit — make sure to do it from the appropriate WINEPREFIX and add the location of the Qt’s bin directory to Path which is under HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment .

If you know a way to script that away, please let me know.

Using regedit on Linux. What would I not do for my readers ?

We also need to put a qt.conf file next to our built helloworld.exe binary to tell Qt where to load the plugins from. In my case

[Paths]

Prefix = /home/cor3ntin/dev/cross-compilers/windows/qt5_10base-x64/

Plugins = plugins

And that’s it ! It wasn’t too hard, was it ?

I made a clicky thing !

And So, Microsoft Studio Visual C++ Compiler is the greatest thing ever !