问题
I'm having a hard time deploying dynamic shared libraries on iOS.
To isolate and expose the problem, I have a very simple "HelloWorld" project: A library exporting class with a function returning "Hello World" and a program using the class and displaying the message.
I'm using QtCreator with Qt 5.5.
I'm able to generate the .dylib
file and link my program. But, when I deploy it on the iPhone, I get the error:
Démarrage des processus distants.
dyld: Library not loaded: libMyLib.1.dylib
Referenced from: /private/var/mobile/Containers/Bundle/Application/D6942CCE-828D-4C10-86DA-F7DA7ADF7449/MyApp.app/MyApp
Reason: image not found
On Android, I had the same kind of issue and could fix it by manually adding the shared library to the final package (apk) file, using ANDROID_EXTRA_LIBS
. But I can find no equivalent for iOS.
Here are my .pro files. Full project can be downloaded here. I reported this to Qt as a bug, but if one could propose a kind of workaround this would help!
MyLib.pro:
QT -= core gui
TARGET = MyLib
TEMPLATE = lib
DEFINES += MYLIB_LIBRARY
SOURCES += mylib.cpp
CONFIG += shared
HEADERS += mylib.h\
mylib_global.h
MyApp.pro:
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = MyApp
TEMPLATE = app
SOURCES += main.cpp\
dialog.cpp
HEADERS += dialog.h
INCLUDEPATH += ../MyLib
LIBS += ../MyLib/libMyLib.dylib
I'd like the solution to be all embedded in QtCreator. The only think that should be changed here is one of the two .pro files. Possibly with post-build calls to MACOS commands...? Or just a post-build instruction in MyApp.pro to copy the dylib in the right place (.app target folder) before application is deployed? I'm really surprised this is not covered silently by QtCreator....
Note: This question suggests to set DYLD_LIBRARY_PATH
. But I have no clue hox to do this within the MyApp.pro file nor how it will help upon iOS deployment (as DYLD_LIBRARY_PATH can be set the MAC PATH to the lib, not the iPhone PATH to the lib...)
回答1:
1) In your library project make sure your dylibs have installname @rpath/mylib.dylib
or such. E.g. by adding QMAKE_SONAME_PREFIX = @rpath
to your library .pro file.
(You can check by looking at the first line of otool -L /path/to/libmylib.dylib
. If the library is a prebuilt 3rdparty one, change it with install_name_tool -id @rpath/libmylib.dylib
)
2) add the following to the application .pro file
# link to the lib:
LIBS += -L../mylib -lmylib
# make the app find the libs:
QMAKE_RPATHDIR = @executable_path/Frameworks
# deploy the libs:
mylib.files = $$OUT_PWD/mylib/libmylib.1.dylib
mylib.path = Frameworks
QMAKE_BUNDLE_DATA += mylib
回答2:
I came up with a workaround for that, in case it could help anyone.
Build your library statically instead of dynamically (replace
CONFIG += shared
byCONFIG += staticlib
Now, compiler will generate
*.a
files instead of*.dylib
, You must use this extension when linking libraries (replaceLIBS += myLib.dylib
byLIBS += myLib.a
)If your library was only linked by a program, you are done
If your library, let's call it (A), was used by another library (B), then (B) should not link with it anymore (No
LIB
flag in B.pro). Only the top level program will link with all your static libraries.
With this approach, I could deploy a program using 15 libraries on an iPhone with QtCreator.
来源:https://stackoverflow.com/questions/32890320/qtcreator-for-ios-how-to-deploy-a-dylib-shared-library-with-my-application