Deployment problems on Mac OSX
-
macdeployqt is your friend. The second tool listing looks good. Is the app still not starting?
- Is your mylibrary lib a plugin? If not, there is no need to load it with QLibrary, just link it.
- If you use open, the command line output is swallowed. Just run the executable instead, without open: ./myConsole.app/Contents/MacOS/myConsole It should then also print errors in case the dynamic linker misses something.
[EDIT: fixed list formating (* instead of -), Volker]
-
Thank you Miroslav,
I am using macdeployqt. The "libmylibrary.dylib" is not a Qt plugin. It is just a shared library that also uses Qt. Actually the libmylibrary will build the QApplication. It runs fine from QtCreator.
There are 2 things I am wondering about:
when I load the "libmylibrary.dylib", I specify
@
QLibrary* lib=new QLibrary("libmylibrary");
@and not
@
QLibrary* lib=new QLibrary("libmylibrary.1.0.0.dylib");
@The other point I was wondering about: when I copy the "libmylibrary.1.0.0.dylib" into my bundle, I do a simple copy and paste. Should I use the "cp -R" command instead?
Edit: Actually, compiling "myLibrary" produces following 4 files:
@
libmylibrary.1.0.0.dylib
libmylibrary.1.0.dylib
libmylibrary.1.dylib
libmylibrary.dylib
@I always copied and pasted all 4 files into the bundle's MacOS directory before running macdeployqt
-
Just answering from the top of my head:
- If mylibrary is just a plain library, you need to link it at link time, not load it at runtime. Check out the -L <path> and -l <libname> statements in qmake.
- Once the library is properly linked, macdeployqt should take care of copying it over automatically. No manual copying should be required.
- The use of QLibrary should be unnecessary. You are trying to do the linker's job.
-
Thanks again for your help Miroslav.
myLibrary is a shared library. It is loaded by "myConsole", but also by non-qt plugins. Each of thoses plugin will be able to call myLibrary's API functions. Following are the 3 types of elements that I have:
@
*myConsole (client application)
- Is in charge of dynamically loading and binding "myLibrary"
- Is in charge of dynamically loading and binging various plugins (non-qt plugins)
- Except for the QLibrary function to load and bind "myLibrary", this application doesn't directly require Qt*myLibrary (collection of API functions)
- Contains a collection of API functions. Those functions need to be accessed by "myConsole" and the plugins (see below)
- Heavily relies on Qt*various plugins
- They do not rely on Qt
- They need to access the API functions of "myLibrary"
@For the tests however, I do not load any of above mentionned plugins.
what makes me crazy is that everything works like a charm when launched from QtCreator. I only have trouble with the bundling.
I could actually also write the "myConsole" without Qt, by using XCode. Would that simplify my problem? I used Qt for "myConsole" simply because I don't yet have any experience with XCode, but already know Qt from other platforms
-
Ok, understood. The QLibrary use is needed in that case (sorry if I led you in the wrong direction).
What could happen is that the paths deviate from what QLibrary expects. You could assemble an absolute path using QCoreApplication::applicationFilePath to see if that is the problem (try QCoreApplication::applicationFilePath + ../MacOs/libmylibrary.1.0.0.dylib, check that it is really there). From the docs, it seems like QLibrary will first try using the passed in name as an absolute path.
-
What you could also try is adding the frameworks directory of your bundle to the library path of QCoreApplication (QCoreApplication::addLibraryPath). I think the bundle frameworks directory is not added automatically.
The docs are a bit vague about the search order of QLibrary, though.
-
Thanks again Miroslav!
I got it to work, but there is something strange going on:
Following does not work:
@
QCoreApplication::addLibraryPath("/Users/me/Documents/myConsole/myConsoleRelease/myConsole.app/Contents/MacOS");
QLibrary* lib=new QLibrary("libmylibrary");
@But following works:
@
QLibrary* lib=new QLibrary("/Users/me/Documents/myConsole/myConsoleRelease/myConsole.app/Contents/MacOS/libmylibrary");
@Might this be a bug in the addLibraryPath function?
Does anyone know from the top of his head a non-Qt command to get the path location of the current application? (including the inside folders of the bundle, so that I can build the absolute path of my library without having to build a QApplication object in order to use "applicationDirPath") -
Thanks Miroslav,
I don't wanna use applicationDirPath() because this requires me to build a QApplication object (and this is done in the "MyLibrary"). Finally, I solved my problems with following code:
@
std::string libLocation(argv[0]);
libLocation.erase(libLocation.end()-9,libLocation.end()); // not elegant, but I just remove the "myConsole" string
chdir(libLocation.c_str());
QLibrary lib=new QLibrary("libmylibrary");
@Thanks to both of you for your help... as it seems now it was a small thing, but it took a lot of effort for me and I wouldn't have found it without your help!!
Cheers
-
the library path of QCoreApplication is not used. The docs state:
bq. When loading the library, QLibrary searches in all system-specific library locations (e.g. LD_LIBRARY_PATH on Unix), unless the file name has an absolute path.
QCoreApplication::libraryPath() is not mentioned here. You might want to try to set the DYLD_LIBRARY_PATH environment variable before you try to load the library. You can try the following snippet, I did not test it, though.
@
QByteArray dyldPath = qgetenv("DYLD_LIBRARY_PATH");
if(!dyldPath.isEmpty())
dyldPath.append(":");
dyldPath.append(QCoreApplication::applicationDirPath());
qputenv("DYLD_LIBRARY_PATH", dyldPath);// call QLibrary load after the stuff above
@Please be aware that on Linux the environment variable is LD_LIBRARY_PATH and on Windows you will have to use PATH (although by default Windows looks into the directory that contains the .exe).
-
Thank you very much Volker!