Using QtCreator together with the Visual Studio Build Tools

published at 09.02.2017 16:22 by Jens Weller
Save to Instapaper Pocket

For a while I've been using QtCreator as my IDE, mostly because its deep integration with Qt, as most of my projects are Qt related. With this, I also preferred (and still do a little) to use the MinGW builds of Qt on Windows. In the past, as GCC was a little bit better with the newer standards, today, well, never change a running system...

... but with Qt 5.7 new things came to Qt, the QWebEngine replacing the QtWebKit module, so for my HTML Editor to run, I have to use this new, chrome based browser system included in Qt. Under Windows though, Chrome does not build with MinGW. So, a switch to the MSVC flavor of Qt is needed.

It comes handy, that QtCreator can handle different compilers over its compiler kit interface, so I don't have to setup a full Visual Studio project and figure out what pitfalls are unknown to me with Visual Studio + Qt. Even better, with the Visual Studio Build Tools, there is a compiler only version available. These also exist for the 2017rc, but for now I am on the latest 2015 version. You also might want to install the Windows Debugger, which is part of a larger SDK, but you can disable everything else, even Debugging works in QtCreator!

So, for now this is my setup: Qt 5.8 brings the latest QtCreator (4.2.1), the Visual Studio Build Tools provide me with the build chain, and a debugger is the last thing you need to install. Maybe some of this is already on your machine. Oh, and I use boost, don't want to figure out how to build boost with the new build chain (probably quite easy), so there is also a binary package with pre build libraries from boost available.

Pitfalls

And this all works, just out of the box! Qt should auto detect the tool chain and debugger, so you might want to install them first. You might need to change the default debugger to x64 instead of x86 though.

But as it turned out, installing was the one thing, getting my project to compile again, is another. All of this had compiled with MinGW, and as I don't use lots of TMP or other platform dependent things, I expected this to go through. But, one issue popped up: boost::factory did not compile in the way I use it.

Movesemantics and old libraries

When I started searching for an explanation, I did not get much hints, except that someone else had the same problems a few years ago. Through the boost mailing list an explanation was found: boost::factory predates C++11, and hence does not know about move semantics, forwarding, etc. This then leads to a strange compiler error:

Error: boost\bind\bind.hpp:249: error: C2664: 'Panel *boost::factory::operator ()(void) const': cannot convert argument 1 from 'Widget *' to 'Widget *&'

Thanks to Peter Dimov for solving this riddle, he pointed me at boost::forward_adapter, which acts as a forwarding layer between boost::factory and the actual factory managing code:

factory.registerType(js_typeid,boost::bind<QWidget*>(boost::forward_adapter<boost::factory<ListPanel*>>(boost::factory<ListPanel*>()),_1,_2,_3));

This is an easy fix, but one also can replace boost::factory with a quick and easy template:

template<class RType, class Type = RType>
struct type_factory
{
    template<class ...Args>
    RType* operator()(Args... args){return new Type(std::forward<Args>(args)...);}
};

At least, this is enough to replace my usage of boost::factory. Actually I'd like to have lambda for this code, but afaik lambdas don't have yet template type parameters. e.g: []<RType,Type>(auto ...args){...}.

Almost compiling!

Well, not so bad to have only one bigger obstacle to get a large program compiling on a different compiler. But not so fast, because you know there is lots of possible linker errors. Linking to the boost libraries is easy, as under MSVC this adds automatically the right libs to your build. This seems to lead to errors in this configuration, adding DEFINES += _MT "fixes" to include the right libs, but its better to turn this feature off with BOOST_ALL_NO_LIBS. I do prefer to have the libs I need to have linked in my makefiles...

After passing linker errors, there is waiting a different pitfall: dlls. You need to be careful which paths are visible in the runtime environment, or your application might crash. One reason can be, that Qt DLLs do not include the compiler or exact Qt version in their name, so that a Qt5Modulename.dll (Q5gui.dll e.g.) might be found, but its not the correct version. Especially when you have used MinGW builds of Qt for some time on the same machine, this can lead to errors while trying to start the program. There is an easy fix: have the correct DLLs available in the PATH environment or copy them locally into the folder of your executable.

To be continued...

With my CMS finally compiling and running again, I can take on the next task: to get the HTML Editor running with QWebEngine. Which is a topic of its own.

Join the Meeting C++ patreon community!
This and other posts on Meeting C++ are enabled by my supporters on patreon!