[SOLVED] Deploying .app on mac OSX



  • Hi,

    I'm having a bit of trouble creating a .app that runs by itself
    My app use only Qt modules and Qwt ("see otools before I run macdeployqt":https://www.dropbox.com/s/qq5zw6mi2c8att7/otoolMyApp.png)

    When I compile my application, If I go add manually in the "MacOS" folder "qwt.framework" and start the application from QtCreator, it runs well.

    However, when I run "macdeployqt", so I can run the app standalone (not in QtCreator) it generate all the QtModule in Contents/Framework and also gives an error about Qwt ("see image":https://www.dropbox.com/s/ntjfxyqisedl88z/macDeployqt.png)
    After that, the output of "otool" has changed for qwt ("see here":https://www.dropbox.com/s/t1dnnftcdb4ochc/otoolaftermacDeploy.png)

    When I try to run the application, it crashes when it runs (I suspect it is because of Qwt)
    I manually copied qwt.framework folder to Contents/Frameworks but app still crash on execution

    Hopefully I get better at deploying at mac this is my first time, any help appreciated!
    Thanks


  • Lifetime Qt Champion

    Hi,

    What error message do you if you start your application from the command line (not using open, starting it with ./PowerVelo2.app/Contents/MacOS/PowerVelo2) ?



  • bq. When I compile my application, If I go add manually in the “MacOS” folder “qwt.framework” and start the application from QtCreator, it runs well.

    The MacOS directory is supposed to only contain executable files and not any subdirectories. Your app runs ok because it's configured to expect qwt.framework at that place, like the first otool -L shows. But it's not kosher.

    And "macdeployqt" -goes bonkers (I mean misunderstands)- it tries its best and thinks your qwt.framework is located in the global /Library/Frameworks directory, but obviously it's not there, hence the error.

    There should a better place for your qwt.framework, how does your .pro file look?

    EDIT: Nevermind the .pro file, had a cup of coffee, realized you can most likely fix your app to be runnable again after you've run "macdeployqt", by copying "qwt.framework" again but this time not to your "MacOS" folder, instead copy it to your Frameworks folder (i.e. PowerVelo2.app/Contents/Frameworks). That way you set things correct according to what the 2nd "otool -L" shows.

    Finally, since you're copying qwt.framework manually, you need to check that framework's dependencies on other Qt libs, do an otool -L on it. If it has, these must be changed before you can deploy to another Mac.

    (That utility "macdeployqt" hadn't seen it before, I've typed my install_name_tools -change by hand, lucky I have a wide screen. Definitely gonna use it.)



  • Oy and happy monday!

    Ah pretty good to run the app from command line, I can see the qDebug message on the command line :)
    I rebuilded and repacked my app just by adding qwt.frameworks in the /Contents/Frameworks after running macdeployqt.

    On app start, I get theses warnings about 2 versions of QtWidgets, I guess it's normal since Qt is installed on this mac and also present in /Contents/Frameworks :
    @tourlou2s-Mac:build-PowerVelo2-Desktop_Qt_5_2_1_clang_64bit-Release tourlou2$ ./PowerVelo2.app/Contents/MacOS/PowerVelo2
    objc[1266]: Class NotificationReceiver is implemented in both /Users/tourlou2/Qt5.2.1/5.2.1/clang_64/lib/QtWidgets.framework/Versions/5/QtWidgets and /Users/tourlou2/Dropbox/build-PowerVelo2-Desktop_Qt_5_2_1_clang_64bit-Release/PowerVelo2.app/Contents/Frameworks/QtWidgets.framework/Versions/5/QtWidgets. One of the two will be used. Which one is undefined.
    objc[1266]: Class QCocoaPageLayoutDelegate is implemented in both /Users/tourlou2/Qt5.2.1/5.2.1/clang_64/lib/QtPrintSupport.framework/Versions/5/QtPrintSupport and /Users/tourlou2/Dropbox/build-PowerVelo2-Desktop_Qt_5_2_1_clang_64bit-Release/PowerVelo2.app/Contents/Frameworks/QtPrintSupport.framework/Versions/5/QtPrintSupport. One of the two will be used. Which one is undefined.
    objc[1266]: Class QCocoaPrintPanelDelegate is implemented in both /Users/tourlou2/Qt5.2.1/5.2.1/clang_64/lib/QtPrintSupport.framework/Versions/5/QtPrintSupport and /Users/tourlou2/Dropbox/build-PowerVelo2-Desktop_Qt_5_2_1_clang_64bit-Release/PowerVelo2.app/Contents/Frameworks/QtPrintSupport.framework/Versions/5/QtPrintSupport. One of the two will be used. Which one is undefined.
    qDebug - Slot ready to read My Ip!
    qDebug -"174.138.198.166"@

    The application crash with that last message shown on the command line :
    @qDebug- End_Workout, creating workout
    qDebug- OK SLOT FINISHED! retrieve workout list!
    QWidget: Must construct a QApplication before a QWidget
    Abort trap: 6
    tourlou2s-Mac:build-PowerVelo2-Desktop_Qt_5_2_1_clang_64bit-Release tourlou2$ @

    Weird now that I added qwt.framework inside /Contents/Frameworks applications also crash in QtCreator with same message error.
    Getting close to it I feel! Thanks for your support again and again :)



  • Ah and I forgot.. here is my otool on qwt-framework:

    tourlou2s-Mac:build-PowerVelo2-Desktop_Qt_5_2_1_clang_64bit-Release tourlou2$ otool -L PowerVelo2.app/Contents/Frameworks/qwt.framework/qwt
    PowerVelo2.app/Contents/Frameworks/qwt.framework/qwt:
    /usr/local/qwt-6.1.0/lib/qwt.framework/Versions/6/qwt (compatibility version 6.1.0, current version 6.1.0)
    /Users/tourlou2/Qt5.2.1/5.2.1/clang_64/lib/QtOpenGL.framework/Versions/5/QtOpenGL (compatibility version 5.2.0, current version 5.2.1)
    /Users/tourlou2/Qt5.2.1/5.2.1/clang_64/lib/QtWidgets.framework/Versions/5/QtWidgets (compatibility version 5.2.0, current version 5.2.1)
    /Users/tourlou2/Qt5.2.1/5.2.1/clang_64/lib/QtGui.framework/Versions/5/QtGui (compatibility version 5.2.0, current version 5.2.1)
    /Users/tourlou2/Qt5.2.1/5.2.1/clang_64/lib/QtCore.framework/Versions/5/QtCore (compatibility version 5.2.0, current version 5.2.1)
    /Users/tourlou2/Qt5.2.1/5.2.1/clang_64/lib/QtSvg.framework/Versions/5/QtSvg (compatibility version 5.2.0, current version 5.2.1)
    /Users/tourlou2/Qt5.2.1/5.2.1/clang_64/lib/QtPrintSupport.framework/Versions/5/QtPrintSupport (compatibility version 5.2.0, current version 5.2.1)
    /Users/tourlou2/Qt5.2.1/5.2.1/clang_64/lib/QtConcurrent.framework/Versions/5/QtConcurrent (compatibility version 5.2.0, current version 5.2.1)
    /System/Library/Frameworks/OpenGL.framework/Versions/A/OpenGL (compatibility version 1.0.0, current version 1.0.0)
    /System/Library/Frameworks/AGL.framework/Versions/A/AGL (compatibility version 1.0.0, current version 1.0.0)
    /usr/lib/libstdc++.6.dylib (compatibility version 7.0.0, current version 60.0.0)
    /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1197.1.1)



  • Update:

    I noted app crash at this place :
    Seems it doesn't like this spot:

    @void Main_WorkoutPage::retrieveWorkoutList() {

    qDebug() << "OK SLOT FINISHED! retrieve workout list!";
    labelLoading->setVisible(false);
    
    QList<Workout> lstWorkout = xmlUtil->getLstWorkout();
    tableModel->setListWorkout(lstWorkout);
    ui->tableView_workout->resizeColumnsToContents();
    

    }

    ////////////////////////////////////////////////////////////
    QList<Workout> XmlUtil::getLstWorkout() {

    return this->lstWorkout;
    

    }
    @

    [Edit
    Code doesn't seem to be the problem, crash is happening at a new place now

    Logs:
    @OK SLOT FINISHED! retrieve workout list!
    Done retrieve workout list!
    GOT HERE READ READY PLAN LIST

    "<?xml version="1.0" encoding="UTF-8"?>
    <root><element><planID>0</planID><plan_name>Aucun</plan_name><plan_description/></element><element><planID>4</planID><plan_name>Rouge et Or - Plan general</plan_name><plan_description/></element></root>
    "
    QWidget: Must construct a QApplication before a QWidget
    Abort trap: 6@

    "update #2 --
    I'll try recompiling Qwt and make sure it's the same version release than my Qt version, will post result!
    http://www.qtcentre.org/threads/10959-QWidget-Must-construct-a-QApplication-before-a-QPaintDevice



  • Just a guess: those messages at start point to a ghost/copy build of the same app inside your Dropbox directory. When you copy the Qwt framework into your app, make sure you don't run macdeployqt before copying.

    Also those messages "... Which one is undefined." means you suffer from the "double-runtime" syndrome, i.e. you mix frameworks from two different build flavors, like two different Qt versions, or one build without macdeployqt and one build with macdeployqt done on it. And that's probably why the app crashes...



  • I copied qwt.framework to /Contents/Frameworks and then ran macdeployqt, "still got this message though":https://www.dropbox.com/s/ntjfxyqisedl88z/macDeployqt.png
    It wants me to put it in the /Library folder? What is up with that? It is in /Frameworks...

    About the 2 implementations, not sure I can fix it, one is my Qt installation(#1) and the other is the copied version that was done with macdeployqt(#2)

    1-
    /Users/tourlou2/Qt5.2.1/5.2.1/clang_64/lib/QtWidgets.framework/Versions/5/QtWidgets
    2-
    /Users/tourlou2/Dropbox/build-PowerVelo2-Desktop_Qt_5_2_1_clang_64bit-Release/PowerVelo2.app/Contents/Frameworks/QtWidgets.framework/Versions/5/QtWidgets. One of the two will be used. Which one is undefined.



  • Once you've run macdeployqt on a build, consider it "infected" :-) I mean zip it or move it to another machine, don't copy parts out of it otherwise this double-runtime syndrome can strike...

    Yeah, that problem of qwt.framework which otool thinks lives in /Library/Framework. Maybe it's time anyway to look at the .pro files of your projects, could you post them?



  • haha I get it that macdeployqt is the last thing you should do, but I did as told and only added qwt.framework before running it :)

    Oh mister you asked for it, theses .pro files are monsters!

    Here is the main project .pro :

    @QT += core widgets gui multimedia

    TARGET = PowerVelo2
    TEMPLATE = app

    CONFIG += qwt
    CONFIG += release
    CONFIG += qt thread
    CONFIG += c++11
    CONFIG += x86_64
    CONFIG -= i386

    fix a compile bug on windows

    DEFINES += NOMINMAX

    #src files for qwt
    INCLUDEPATH += /Users/tourlou2/Dropbox/qwt-6.1.0/src

    #src vlc
    INCLUDEPATH += /Users/tourlou2/Dropbox/vlc/include
    INCLUDEPATH += /Users/tourlou2/Dropbox/vlc/include/vlc

    #src vlc-qt
    INCLUDEPATH += /Users/tourlou2/Dropbox/vlc-qt-0.9.0/src/core
    INCLUDEPATH += /Users/tourlou2/Dropbox/vlc-qt-0.9.0/src/widgets

    include ( /Users/tourlou2/Dropbox/qwt-6.1.0/qwt.prf )
    include (_subclassQT/_subclassQT.pri)
    include (_subclassQWT/_subclassQWT.pri)
    include (main/main.pri)
    include (model/model.pri)
    include (gui/gui.pri)
    include (m_xml/m_xml.pri)

    include (ANT/heart_rate/ANT_HeartRate.pri)
    include (ANT/cadence/ANT_Cadence.pri)
    include (ANT/speed/ANT_Speed.pri)
    include (ANT/speed_cadence/ANT_SpeedCadence.pri)
    include (ANT/power/ANT_Power.pri)
    include (ANT/ANT.pri)

    include (videoPlayer_pri/videoPlayer_pri.pri)

    RESOURCES +=
    MyResources.qrc

    TRANSLATIONS = powervelo_en.ts
    powervelo_fr.ts
    #powervelo_de.ts
    @

    Here is Ant.pri

    @INCLUDEPATH += $$PWD
    DEPENDPATH += $$PWD

    SOURCES +=
    ANT/hub.cpp
    ANT/utilpowercurve.cpp \

    HEADERS +=
    ANT/hub.h
    ANT/utilpowercurve.h
    ANT/common_pages.h
    ANT/antplus.h

    #FOR ANT+
    #////////////////////////////////////////////////////////////////////////////////////////////////////////
    INCLUDEPATH += /Users/tourlou2/Dropbox/ANT_LIB_mac/inc
    INCLUDEPATH += /Users/tourlou2/Dropbox/ANT_LIB_mac/software/serial
    INCLUDEPATH += /Users/tourlou2/Dropbox/ANT_LIB_mac/software/system
    INCLUDEPATH += /Users/tourlou2/Dropbox/ANT_LIB_mac/software/USB/devices
    INCLUDEPATH += /Users/tourlou2/Dropbox/ANT_LIB_mac/software/USB/device_handles
    INCLUDEPATH += /Users/tourlou2/Dropbox/ANT_LIB_mac/software/USB

    #static ANT_LIB builded with ANT_LIB project (Compile it with ANT_LIB PROJECT)
    LIBS += /Users/tourlou2/Dropbox/libANT_LIB.a
    LIBS += -framework IOKit
    LIBS += -framework CoreFoundation@

    Here is video_player.pri

    @INCLUDEPATH += $$PWD
    DEPENDPATH += $$PWD

    SOURCES +=
    videoPlayer_pri/playerwidget.cpp

    HEADERS +=
    videoPlayer_pri/playerwidget.h

    FORMS +=
    videoPlayer_pri/PlayerWidget.ui

    RESOURCES +=
    videoPlayer_pri/ResourceVideoPlayer.qrc

    LIBS += /Users/tourlou2/Dropbox/vlc_lib/libvlc.5.dylib
    LIBS += /Users/tourlou2/Dropbox/vlc_lib/libvlc.dylib
    LIBS += /Users/tourlou2/Dropbox/vlc_lib/libvlccore.7.dylib
    LIBS += /Users/tourlou2/Dropbox/vlc_lib/libvlccore.dylib@

    Rest of the .pri are just header/source code.
    I'll pay you both wiskey soon..



  • Big yes, not your grandpa's .pro files that's for sure.

    Hmmm, SGaist I'll give you some of my whiskey if you can help...



  • Meanwhile I'm reinstalling XCode5 and trying everything from scratch (rebuild qwt, ant_lib.a, ..) will see if the same error appears

    • 10 000 Dogecoins for the help └(°ᴥ°)┘

    [Edit:
    I think one major concept I didn't understand is linking library
    ie: tell the linker to link against the library by adding this line:
    LIBS += -l[...]
    So I probably build using some other libs, but since they are not required at runtime, this crash the app? will investigate..



  • Okay I reinstalled Xcode5 and Qt from scratch
    and now when I try to use "macdeployqt" I get command not found.. sigh -_-

    Update: After fresh reinstall and build of my application, I copied qwt.framework to MyApp.app/Contents/MacOs and run app from QtCreator, app works 100% fine.
    As you said im almost sure it's crashing because of the "“double-runtime” syndrome" but I can't test this again because "macdeployqt" is gone for some reason.

    so problem with the crash is only when I start app from outside QtCreator, i'm taking a break and will test again when my sanily level drop back to normal :)



  • Don't worry, "macdeployqt" is probably where it should be.
    This is how I start it on my Mac:!http://www.tripleboot.org/wp-content/uploads/2014/03/InvokingMacDeployQt.png(launching macdeployqt)!

    (picture is from "my blog post":http://www.tripleboot.org/?p=138 )

    [Update: ] Checked your .pro files a bit, this line sure look suspicious:
    LIBS += /Users/tourlou2/Dropbox/libANT_LIB.a

    What happens if you comment it out?
    (Because linking to libANT_LIB.a is possible way for you to get the "double runtime" into your app)


  • Lifetime Qt Champion

    Double Qt Syndrome

    The double Qt syndrome comes from a dependency that has not yet been update to load the Qt bundled with your application. That can be one of your custom lib (but generally macdeployqt handles that) That can be one of your external library that has been copied but not updated. Have a look at libvlc, they also use Qt for their GUI.

    Once macdeployqt has run, check the error message, it might get lost trying to copy all dependencies. Then have a look at the Frameworks and PlugIns folder content and run otool -L on them to see if they indeed refer only to the Qt libraries/other non system libraries in your bundle. You should also check all non system libraries to see it their paths are correctly pointing inside your bundle.

    LIBS

    When doing LIBS += -Lsome_path you tell the linker to look in some_path to find additional libraries, on OS X you also have -F for folder containing frameworks.

    LIBS += -lmylibname tells the linker that you want to link to a given library. Depending on what library file it finds, it will link to the dynamic or static version.
    Giving the full path to the static library tells the linker to link against that specific static library file, it can't be used for dynamic library.

    On a side note, you should only need to do QT += qwt if the installation went correctly.



  • Solved
    Thank you both for your kind help!
    Since macdeployqt was complaining all the time about qwt.framework not in /Library/Frameworks, I added it to it. Then when running macdeployqt after a fresh build, qwt.frameworks get copied automatically and that seem to have fixed the problem. I suspect macdeployqt fixed bad dependencies on the qwt.frameworks that were not pointing at the good Qt libs (double qt syndrome)

    SGaist,
    I get the LIBS+= [some_path] but not sure about the -L meaning before it.
    In my .pro, I added the all the libs with LIBS+= [pathlib/libname] "
    When I run otool -L on my app I get "this as result":https://www.dropbox.com/s/t1dnnftcdb4ochc/otoolaftermacDeploy.png
    Does this mean all the other libs I added in the .pro are only used for building the app and not actually running it? how does Qt knows which one is needed at runtime vs not needed? For example I added a static library "LIBS += /Users/tourlou2/Dropbox/libANT_LIB.a"
    and this one is not listed when I run otool. I'm happy it's working but i'd like to understand why so not to bother you guys again :)

    Have a great day, i'll certainly have one!


  • Lifetime Qt Champion

    -L is a switch that tells the linker that what follows is a path that it must look in to find libraries.

    A static library won't be listed as dependency since all the code used from it is copied inside the application or library that links against it.



  • Ohh I get it now, that is why the licensing difference with static lib

    One last thing, i've been reading "this guide":http://qt-project.org/doc/qt-4.8/deployment-mac.html but it doesn't mention where to put the translation file ".qm" on macOSX, on windows I just added them in the folder with the executable but it doesn't seem to work here.

    last update :
    the double dependency problem comes again when I run the app from inside QtCreator after running macdeployqt, once I ran it in qtCreator just one time, the package is spoiled and I have to rebuild/package again

    So the solution I found for now is to debug/test the application in QtCreator, and when everything is ready I can use macdeployqt as as* last step* but to get back to developpement later I'll have to rebuild again and delete what macdeployqt as done

    @Starting /Users/tourlou2/Dropbox/build-PowerVelo2-Desktop_Qt_5_2_1_clang_64bit-Release/PowerVelo2.app/Contents/MacOS/PowerVelo2...
    objc[2737]: Class NotificationReceiver is implemented in both /Users/tourlou2/Qt/5.2.1/clang_64/lib/QtWidgets.framework/Versions/5/QtWidgets and /Users/tourlou2/Dropbox/build-PowerVelo2-Desktop_Qt_5_2_1_clang_64bit-Release/PowerVelo2.app/Contents/Frameworks/QtWidgets.framework/Versions/5/QtWidgets. One of the two will be used. Which one is undefined.
    objc[2737]: Class QCocoaPageLayoutDelegate is implemented in both /Users/tourlou2/Qt/5.2.1/clang_64/lib/QtPrintSupport.framework/Versions/5/QtPrintSupport and /Users/tourlou2/Dropbox/build-PowerVelo2-Desktop_Qt_5_2_1_clang_64bit-Release/PowerVelo2.app/Contents/Frameworks/QtPrintSupport.framework/Versions/5/QtPrintSupport. One of the two will be used. Which one is undefined.
    objc[2737]: Class QCocoaPrintPanelDelegate is implemented in both /Users/tourlou2/Qt/5.2.1/clang_64/lib/QtPrintSupport.framework/Versions/5/QtPrintSupport and /Users/tourlou2/Dropbox/build-PowerVelo2-Desktop_Qt_5_2_1_clang_64bit-Release/PowerVelo2.app/Contents/Frameworks/QtPrintSupport.framework/Versions/5/QtPrintSupport. One of the two will be used. Which one is undefined.
    QObject::moveToThread: Current thread (0x7f95cbc09940) is not the object's thread (0x7f95cbc25050).
    Cannot move to target thread (0x7f95cbc09940)

    On Mac OS X, 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.
    This application failed to start because it could not find or load the Qt platform plugin "cocoa".@


  • Lifetime Qt Champion

    Indeed, macdeployqt is only to be used once you are ready to distribute your application.



  • Yeah I learn this the hard way
    Could be good if macdeployqt just created another folder in the build folder instead of touching the real executable, but i'm always asking too much :)

    as for the translation file for MacOSX, is there a preferred place to put them?


  • Lifetime Qt Champion

    Since it's an OS X program, put them in the Resources folder



  • Thanks SGaist,

    The best solution I found is to add the translation file ".qm" files into my Ressource file, then it is loaded the same way on Windows and Mac OSX, save me the headaches of pathing..


  • Lifetime Qt Champion

    You're welcome !

    That's also a good solution


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.