PDA

View Full Version : Strange errors on OS X only if libraries are inside application bundle



Hodapp87
18th March 2010, 16:11
I was tasked with maintaining a Mac OS X port of a Qt application in Qt Creator (most of the development is done for Windows in Visual Studio). Everything builds fine, and then I am using a script which utilizes macdeployqt to add in Qt dependencies to the application bundle.
If I try to run this bundle, I get the error: "QWidget: Must construct a QApplication before a QPaintDevice". Running from commandline shows that a series of messages like this precede it:

objc[12020]: Class QMacSoundDelegate is implemented in both
/Library/Frameworks/QtGui.framework/Versions/4/QtGui and
/Users/uliggett/Q/NAVY_SBIR_NDE_PII/NLign3D/NLign3D.app/
Contents/MacOS/../Frameworks/QtGui.framework/Versions/4/QtGui.
Using implementation from /Users/uliggett/Q/NAVY_SBIR_NDE_PII/NLign3D/NLign3D.app/
Contents/MacOS/../Frameworks/QtGui.framework/Versions/4/QtGui.
This happens in both debug mode and release mode.

If I remove all the Qt libraries from the Contents/Frameworks/ folder of the bundle (I tried this after reading this thread (http://www.qtcentre.org/threads/23559-Application-deployment-on-Mac-OS-X-(10-5)?p=136044&highlight=)), then the application starts and runs flawlessly, apparently using the Qt libraries from the system path rather than the bundle. However, this is not a viable solution because the bundle is something that we will distribute, likely to users who do not have Qt installed elsewhere.
I tried directly copying the relevant libraries from the system path into the bundle. This resulted in the new error "QWidget: Cannot create a QWidget when no GUI is being used."
As far as I can tell, the libraries inside the bundle and the libraries inside /Libraries/Framework etc. are completely identical except that 'otool -L' reports that they are linked against different locations of Qt libraries (i.e. those inside the bundle point to more libraries inside the bundle, while those in the system path point to more in the system path, which makes sense).

Can anyone shed some light on this issue?

Hodapp87
15th April 2010, 20:05
I fixed my own issue eventually. The problem was that all the dylibs with which the main executable was linked were referring to (for instance) QtOpenGL.Framework/Versions/4/OpenGL and it was taking that as a relative path from /Library/Frameworks rather than from the location of the dylib (which would have put it inside the bundle in the proper location). As a result, some parts of the program were referring to different libraries and so Qt had a different context (or something) there.
While there is probably a better way to solve this, I just added this to the deployment script to work around it temporarily:

# Get each dylib to point to the proper location for the Qt libraries -
# that is, inside the bundle, not into /Library/Frameworks.
PREFIX="@executable_path/../Frameworks/"
# (1) Get each dylib (files only - not symlinks) and get the
# main executable too.
find $DESTDIR/NLign3D.app/Contents/Frameworks -type f | egrep "\.dylib$" > /tmp/libs.txt
echo $DESTDIR/NLign3D.app/Contents/MacOS/NLign3D >> /tmp/libs.txt
cat /tmp/libs.txt |
while read LIBNAME
do
# (2) Find any reference to Qt libs that aren't
# via @executable_path/.. etc.
otool -L $LIBNAME |
sed -e "s/^[[:blank:]]*//g" |
egrep "^Qt" |
cut -d ' ' -f 1 |
while read LIBREF
do
# (3) Prefix these refs with $PREFIX so that the
# dylibs look inside the bundle for Qt, rather than
# in /Library/Frameworks.
NEWREF=$PREFIX$LIBREF
install_name_tool -change $LIBREF $NEWREF $LIBNAME
done
done