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:
3 thoughts on “Notes on building C++ projects on Windows”
digiKam project left definitively the way to compile whole source code under windows as well. It’s a waste of time… but we cross compile ALL. When i said ALL, this want mean from scratch under Linux :
– low level libraries
– whole Qt5
– whole KF5
– whole digiKam & co (1.4 M lines of code)
– The NSIS installer
… And all without any errors, in 32 bits and 64 bits. This take 2h30 to build all with a 8 cores i7 CPU and 32 Gb of RAM.
… And without possible Windows Virus !
all is driven with BASH and CMAKE and MXE cross compile for Linux. If you can do better than this with native Windows script, let’s me know, but seriously, Windows is really a shame for developers…
Interested : https://cgit.kde.org/digikam.git/tree/project/bundles/mxe
I definitely can’t do better than that on windows 😉
I’ve experimented some with MXE and got stuck on building libsasl which has a horrific autotools buildsystem and builds a code-generator that is then executed during the build process. I never got the code-generator to build for the host system, so it could actually run there… I’m sure it’s a solvable problem though.
Crosscompiling also seems like a bit of a hack to me, it just doesn’t seem right to build for one platform from something entirely different… But yeah, it’s definitely tempting to be able to do everything from a sane system, and despite whatever drawbacks there may be (some say the native compiler is just “better”), it clearly works out for some projects at least.
Thanks for your input!