Question

I have a problem since the version 5.1rc2 of Qt for Mac OS X. (5.1 is also affected, not the 5.1rc1)
When I build my app and do a otool -L on the binary file to see the paths of the shared libraries, I get: (it's just a sample, I removed some of them for clarity)

/System/Library/Frameworks/AppKit.framework/Versions/C/AppKit 
    (compatibility version 45.0.0, current version 1187.37.0)
/Users/chris/**Qt5.1.0//5.1.0**/clang_64/lib/QtWebKitWidgets.framework/Versions/5/QtWebKitWidgets
    (compatibility version 5.1.0, current version 5.1.0)
/Users/chris/Qt5.1.0//5.1.0/clang_64/lib/QtQuick.framework/Versions/5/QtQuick
    (compatibility version 5.1.0, current version 5.1.0)
/Users/chris/Qt5.1.0//5.1.0/clang_64/lib/QtQml.framework/Versions/5/QtQml
    (compatibility version 5.1.0, current version 5.1.0)
/Users/chris/Qt5.1.0//5.1.0/clang_64/lib/QtNetwork.framework/Versions/5/QtNetwork
    (compatibility version 5.1.0, current version 5.1.0)
/Users/chris/Qt5.1.0//5.1.0/clang_64/lib/QtCore.framework/Versions/5/QtCore
    (compatibility version 5.1.0, current version 5.1.0)
/Users/chris/Qt5.1.0//5.1.0/clang_64/lib/QtGui.framework/Versions/5/QtGui
    (compatibility version 5.1.0, current version 5.1.0)

As you can see there is a double slash in the paths of the Qt libraries. When I use macdeployqt to deploy my app, those paths aren't changed to local frameworks (@executable_path/../Frameworks/...), because of this... I have to do it manually with the install_name_tool, and it's really annoying.

What can I do to fix this? (I've tried re-installing Qt, cleaning, runing qmake again and rebuilding without change)

Was it helpful?

Solution

having the same issue. I applied next workaround:

after I build my program, I've changed links inside exe to a right ones

install_name_tool -change /Users/username/Qt5.1.0//5.1.0/clang_64/lib/QtQuick.framework/Versions/5/QtQuick  /Users/username/Qt5.1.0/5.1.0/clang_64/lib/QtQuick.framework/Versions/5/QtQuick <YourExecutable>

After this workaround macdeployqt has changed all links inside exe to a relative ones.

But my App became broken. The thing is that I've added all my images and QML files into resources. After I ran macdeployqt - I can not run my app. When I ran this with gdb - I see next error:

QQmlApplicationEngine failed to load component 
qrc:/qml/main.qml:-1 File not found

Error: Your root item has to be a Window.

So somehow all my resources became unavailable. Does anyone know how to fix that?

I also started a discussion on qt forum

UPDATE, HOW TO DEPLOY:

  1. Use this script to get rid of double slashes inside dynamic linking paths.

    ./fixqt.sh ~/Qt5.1.0/5.1.0/clang_64

  2. Build macdeployqt tool from this repository.

  3. Run macdeployqt and specify dir with your qml source:

    macdeployqt MyApp.app/ -qmldir=../src/qml -dmg

After those steps I managed to run my application on different OS X system, without QT Installed. I've added all my qml files and images into resources. QtQuick and QtQuick.2 modules copied inside MyApp.app/Content/MacOS/

Hope it helps

OTHER TIPS

I'm posting this as a solution as I just lost (another) day to this process with 5.3 (and I assume it is the same for 5.4).

macdeployqt now works as intended but the failed piece of documentation here is that you need to specify and absolute path to each qml directory (relative might work but I've had no luck at all).

Here's how I solved that for my release process:

In the project file I now have

  mac {
    CONFIG += x86
    CONFIG += c++11
    #Disable these for development
    QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.9 #I'm not sure I need this
    QMAKE_POST_LINK = {path to macdeployqt}/macdeployqt {appname}.app -qmldir=$$PWD/qml/{appname}/ -verbose=3
  }

This effectively calls: macdeployqt appname.app - /path/to/source/code/appname/qml/appname/ -verbose=3

When the absolute path is specified it appears to work fine but when I use a relative path I run into several problems. PWD is the source directory and the executables are run from the build directory. The absolute path of the build is OUT_PWD.

The beauty of keeping this in the release configuration in the project is that I debug normally (no app package) and the release package correctly builds from creator. Theoretically I can just wrap that into a Jenkins build and be done with this headache once and for all.

The Short Answer

macdeployqt MUST SCAN your qml files if you're using them otherwise the imports will be broken and you'll see errors like:

QQmlApplicationEngine failed to load component
qrc:/qml/LightAssistant.qml:5 module "QtQuick.Dialogs" is not installed
qrc:/qml/LightAssistant.qml:3 module "QtQuick.Window" is not installed
qrc:/qml/LightAssistant.qml:4 module "QtQuick.Controls" is not installed
qrc:/qml/LightAssistant.qml:1 module "QtQuick" is not installed
qrc:/qml/LightAssistant.qml:2 module "QtQuick.Layouts" is not installed

Finally, my directory structure looks like this:

  Project
    - qml
      - appname
        files1.qml
        files2.qml
        ...
        filesX.qml 
    - js
    - images

These then get packaged into the Resource file which, by definition, are not copied to the build directory and thus macdeployqt can't scan them unless the pathing is perfect. By using this build process I have a step in my build (release) that just deals with it and I don't have to run macdeployqt when I'm debugging. Keep in mind if you use the app_bundle you need to run macdeployqt on each build which will really mess with your debugging workflow.

This thread:

http://www.qtcentre.org/threads/55277-Qt-5-1-and-Mac-Bug-making-macdeployqt-not-working-properly

contains this link:

https://gist.github.com/lasconic/5965542

to this script by lasconic (not my work):

BIN_FILE=YOURBINARY
for P in `otool -L $BIN_FILE | awk '{print $1}'` 
do 
    if [[ "$P" == *//* ]] 
    then 
        PSLASH=$(echo $P | sed 's,//,/,g')
        install_name_tool -change $P $PSLASH $BIN_FILE
    fi 
done 

QTDIR=$1
for F in `find $QTDIR/lib $QTDIR/plugins $QTDIR/qml  -perm 755 -type f` 
do 
    for P in `otool -L $F | awk '{print $1}'`
    do   
        if [[ "$P" == *//* ]] 
        then 
            PSLASH=$(echo $P | sed 's,//,/,g')
            install_name_tool -change $P $PSLASH $F
        fi 
     done
done

You just need to replace YOURBINARY with e.g. myapp.app/Contents/MacOS/myapp

And QTDIR=$1 with QTDIR=/Users/MyName/Qt5.1.0/5.1.0/clang_64

Save the file in the same dir as myapp.app

And run it with

sh thankslasconic.sh

then you can run

macdeployqt myapp.app

and it should work. For me it did. That is why I am posting it here.

I think its a installer bug. All librarys and tool (compiled/linked by installer?) referenced to .../Qt5.1.0//5.1.0/... (with double slash)

I've tried online and offline installer for Mac with the same result.

I've reported it as a bug. https://bugreports.qt-project.org/browse/QTBUG-32467

Just as a follow-up, this bug appears to be fixed in Qt5.1.1 https://bugreports.qt.io/browse/QTBUG-32365

Tried all of the above with qt 5.1.1 but always got this crash:

QMessageLogger::fatal(char const*, ...) const + 161
QGuiApplicationPrivate::createPlatformIntegration() + 1763
QGuiApplicationPrivate::createEventDispatcher() + 28
QCoreApplication::init() + 101
QCoreApplication::QCoreApplication(QCoreApplicationPrivate&) + 42

so I created this elixir, YMMV:

1) get the above mentioned mostly kinda working macqtdeploy from github.

2) build this new macqtdeploy

3) add this to main.cpp for mac os x only. this stuffs "-platformpluginpath" into argv before starting qapplication.

int macStart(int argc, char *argv[]) {
    QFileInfo fi(argv[0]);
    QDir plugd(fi.dir());
    plugd.cdUp();
    plugd.cd("PlugIns");
    QString plugins = plugd.absolutePath();
    qDebug() << "PlugIns" << plugins;

    char* argv_sub[argc + 2];
    for (int i = 0; i < argc; ++i) {
        char* temp = (char*) malloc(strlen(argv[i]) + 1);
        strcpy(temp, argv[i]);
        argv_sub[i] = temp;
    }

    char ppp[255];
    strcpy(ppp, "-platformpluginpath");
    argv_sub[argc] = ppp;

    char pathx[2048];
    strcpy(pathx, (char*) plugd.absolutePath().toLocal8Bit().constData());
    argv_sub[argc + 1] = pathx;

    DCApplication app(argc + 2, argv_sub);
    app.startup();
    return app.exec();
}

4) build app

5) run new macqtdeploy on app

6) goodness

set plugin folder to libraryPaths

QStringList paths;
paths.append("folder with plugins"); //can be inside bundle
QApplication::setLibraryPaths(paths);

I always ended up in this discussion when looking for a similar error with macdeployqt and QT Quick 2.0 using QML.

The error I found was this:

Machine:MacOS MyName$ ./tool QQmlApplicationEngine failed to load component qrc:/main.qml:1 plugin cannot be loaded for module "QtQuick": '/Users/thorstenbux/DAQRI/gitHub/artoolkit6/Source/Utilities/ImageDBSerialiser/build-ui/imageDatabase.app/Contents/PlugIns/quick/libqtquick2plugin.dylib' is not a valid Mach-O binary (not a dynamic library)

and this:

ERROR: Could not parse otool output: "/Users/myname/DAQRI/gitHub/tool/Source/Utilities/tool/build-tool-Desktop_Qt_5_8_0_clang_64bit-Release/tool.app/Contents/PlugIns/quick/libqtquick2plugin.dylib:\n"

I created a separate question for that kind of error here: QT Quick (QML) assemble mac-.bundle -> not a dynamic library error when using macdeployqt

Just in case someone has the same issue and reads this thread.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top