Building C++ projects is bad enough, doing it on Windows is torture. The tooling sucks, the commandline sucks, the OS sucks. I might be biased.
I don’t think there’s a “good” way to build software for windows (Maybe it’s just using native tooling, I wouldn’t know), but here are some notes
on what I did, and perhaps it helps another poor soul out there trying to get something to work on windows.
Orchestrating the build
Unless your project is trivial, you will have to use something to orchestrate your builds. You will have to build all your dependencies (or cobble something together from installers on the internet…). Various solutions exist, none is any good.
Among the options are:
- CMake with ExternalProject: Not much better than any other scripting language, but would work I guess.
- Craft: Don’t expect everything to work out of the box, but it’s python and it’s fixable. It also covers everything from fetching the sources to building an installer, which is nice.
For the individual parts that you build you’ll require some build tools. Whatever you think of CMake, when it comes to cross platform support there is just nothing better.
Wherever I could choose I chose CMake together with clang-cl which is the $MS style clang frontend.
That leaves you with the projects where you could not choose. In some cases it’s just easier to rewrite the buildsystem in cmake and get on with it.
In other cases you actually have to use an autotools buildsystem, so you have to resort to something like MSYS2.
There are few options for installers, and NSIS still seems like the easiest of the lot, and it works.
You will have to touch that windows system for quite some time, but you’ll want to stop as soon as possible, so setup some CI solution to do the dirty work for you. Personally I’ve used Buildbot, I suppose Jenkins would work as well.
- By default everything is hidden (which is the opposite of what we have on linux). Export explicitly what you want to use from a shared library.
- Shared libraries consist of: a .dll containing the code, a .imp that contains the symbol table. All compiler specific.
- C++ ABI is compiler specific. While it is possible to e.g. cross-compile a library from linux using mingwg and then link against that on windows,
it’s not straightforward because you have to generate a .imp file that uses a mangling scheme that the compiler on windows understands (by default it wont work).
- If you compile 64bit, all your libraries that you want to link against need to be 64bit.
- If you use qt from the installer, add a qt.conf file to adjust the prefix. The compiled in paths for e.g. plugins won’t be available on the target system.
- File paths passed to QML have to be converted with QUrl::fromLocalFile from a string. While absolute paths as strings work fine on unixes, it won’t work on windows.
- Symlinks aren’t a thing on windows. For icon-themes (which make heavy use of symlinks), use a qrc file.
- Qt is not deployed with SSL by default and tries to load the openssl libraries at run-time. Qt thus dictates which OpenSSL version you have to use. For Qt 5.9 OpenSSL 1.0.2o will work, for 5.10 you’ll need >= 1.1. Make sure you get 64/32bit depending on your Qt deployment. To deploy with the application I had to buld from source, but in general an installer like https://slproweb.com/download/Win64OpenSSL_Light-1_0_2o.exe will work as well (I did not manage to package the appropriate dlls from the installer though). QSslSocket provides functions to check whether the loading worked.
- libcurl needs to be built with -DCMAKE_USE_OPENSSL=TRUE switch to have ssl support.
Windows survival tools
- Get a backtrace: windbg, make sure you get the 64bit version.
- strace: procmon.exe
- Get debug output: DebugView.exe
- The only barely usable terminal on windows is cmdr
- It’s possible to setup ssh access to windows, but it will still be a pain to use.
- Wireshark works on windows too.
- Stay away from anything autotools if you can. It is often even easier to rewrite the buildsystem with cmake (sad, but true).
- AWK scripts not working on msys2
- buildsystems abusing compilers to generate code (hint; it’s not gonna work)
- If ninja ends up rerunning the cmake configuration phase over and over in an endless loop, try checking out the source repository again. I think it has something to do with file timestamps…
Last but not least, here’s the code I’m using: