How to install Qt6 for C++ on Mac

Posted on Oct 22, 2022

Lately I have been working on a hobby project written in C++ and Qt6.

Had I not ditched Conan to use Vcpkg, due to their backward incompatible migration from v1 to v2 which completely wasted my build, probably this would post wouldn’t exist. :)

Anyway, I stumbled upon a quite nasty issue that seems to hit some people using Qt, probably because of the way it is installed.

In fact, after using Conan, I decided to use homebrew to install qt, and the behavior is, to say the least, weird.

When you build your project with cmake and package it as an OSX Bundle like in the code:

if (APPLE)
    add_executable(myapp MACOSX_BUNDLE)
# ...
endif()

Then you get an issue like:

objc[97951]: Class RunLoopModeTracker is implemented in both /usr/local/Cellar/qt/6.3.2/lib/QtCore.framework/Versions/A/QtCore (0x10d0626c8) and /Users/path/to/myapp/build/bin/myapp.app/Contents/Frameworks/QtCore.framework/Versions/A/QtCore (0x11d0ca6c8). One of the two will be used. Which one is undefined.QObject::moveToThread: Current thread (0x6020000024f0) is not the object's thread (0x60200000e910). 

Cannot move to target thread (0x6020000024f0)

You might be loading two sets of Qt binaries into the same process. Check that all plugins are compiled against the right Qt binaries. Export DYLD_PRINT_LIBRARIES=1 and check that only one set of binaries are being loaded.qt.qpa.plugin: Could not load the Qt platform plugin "cocoa" in "" even though it was found.This application failed to start because no Qt platform plugin could be initialized. Reinstalling the application may fix this problem.

However, if you use macdeployqt, the issue disappears. This, though, means you automagically lose the ability to use the “Run in IDE” functionality, because it just doesn’t work.

The weird thing is that after the build (and before using macdeployqt) the package folder contains lots of libraries, including the cocoa plugin it apparently fails to find, the Qt dependencies you need and also the ones you don’t need (e.g., I don’t use QtNetwork, but it also appears in the directory). Therefore, at least from the look of it, everything should be there in the folder, and there shouldn’t be any need for loading things from outside.

Finally, after hours of useless debugging, trying to understand which library or plug-in was causing the double loading, I decided to find another way to install Qt.

I chose aqtinstall, the tool behind the Github Action to install Qt in the CI environment - which I use on Github already. Nonetheless, the method applies to any machine, so why not.

With a couple of simple commands:

$ mkdir qt6
$ cd qt6
$ aqt install-qt mac desktop 6.3.2 clang_64

At this point, you need to set the environment variables so that when you run CMake, the qt libs are found correctly. I recommend creating a simple file, e.g., ~/setup-qt.sh, so that you can load it also from your IDE (e.g., in CLion you can load an environment file in Preferences | Build, Execution, Deployment | Toolchains).

$ export Qt6_DIR=/path/to/qt6/6.3.2/macos/
$ export QT_PLUGIN_PATH=/path/to/qt6/6.3.2/macos/plugins
$ export PKG_CONFIG_PATH=/path/to/qt6/6.3.2/macos/lib/pkgconfig
$ export QML2_IMPORT_PATH=/path/to/qt6/6.3.2/macos/qml
$ export PATH="/path/to/qt6/6.3.2/macos/bin:$PATH"

Now, you should finally have an environment that works like a charm - without having to rely on the deployment tool.