Details
-
Suggestion
-
Resolution: Unresolved
-
P2: Important
-
None
-
5.15.0, 6.2
-
-
adb91d6af (dev)
Description
It is possible to configure Qt with -shared flag for iOS and it does produce .dylib and iOS Frameworks.
But the Qt iOS platform plugin is still static (libqios.a), which makes the build not purely dynamic libs, but mostly dynamic libs with exception of a static libqios.a.
Note: linking with libqios.a also requires linking with libQt5FontDatabaseSupport.a, libQt5ClipboardSupport.a, libQt5GraphicsSupport.a, libqtfreetype.a and libqtlibpng.a to get rid of unresolved symbols, which makes the process quite cumbersome.
For example, it is possible to make a few modifications to Qt source code and change it to purely dynamic this way [tested in Qt 5.15.0]:
- Remove the line that forces libqios to be static from qtbase/src/plugins/platforms/ios/kernel.pro:
qtConfig(shared): CONFIG += static
- Extend existing qt_main_wrapper() in qtbase/src/plugins/platforms/ios/qioseventdispatcher.mm to have a third parameter, which is a pointer to the actual main(), that must be called when initialisation is complete:
@@ -213,8 +213,10 @@ void printUsage() using namespace QT_PREPEND_NAMESPACE(QtPrivate); --extern "C" int qt_main_wrapper(int argc, char *argv[])- +*int (*main_ptr)(int, char **) = 0;* +Q_EXTERN_C Q_DECL_EXPORT int qt_main_wrapper(int argc, char *argv[]*, int (*real_main_ptr)(int, char **)*) { + *main_ptr = real_main_ptr;* @autoreleasepool { size_t defaultStackSize = 512 * kBytesPerKiloByte; // Same as secondary threads @@ -251,7 +253,7 @@ void printUsage() kJumpedFromUserMainTrampoline, }; --extern "C" int main(int argc, char *argv[]);- + static void __attribute__((noinline, noreturn)) user_main_trampoline() { @@ -270,7 +272,7 @@ static void __attribute__((noinline, noreturn)) user_main_trampoline() qFatal("Could not convert argv[%d] to C string", i); } -- int exitCode = main(argc, argv);- + int exitCode = *main_ptr*(argc, argv); delete[] argv; logActivity.applicationDidFinishLaunching.enter();
- Add plugins/platforms/libqios.dylib to linked libraries and modify your project entrypoint to be main_wrapper() instead of main() in build options:
-Wl,-e,_main_wrapper
- In your main.cpp add this simple code, which will only work when building for iOS:
int main(int argc, char **argv) { Application app(argc, argv); return app.exec(); } <p></p> #if TARGET_OS_IPHONE *extern "C" int qt_main_wrapper(int argc, char *argv[], int (*f)(int, char **));* //this function is inside libqios.dylib extern "C" int main_wrapper(int argc, char **argv) { //this is the entry point *qt_main_wrapper*(argc, argv, *main*);//once finished, it will call into the real "main()" above } #endif
How this works:
- Your app starts executing in main_wrapper().
- main_wrapper() calls into libqios.dylib's qt_main_wrapper() and passes function pointer to the real main() function.
- qt_main_wrapper() executes some iOS custom ObjectiveC glue code and waits until
applicationDidFinishLaunching notification is received - Once applicationDidFinishLaunching is received (your app becomes operational), libqios.dylib executes main() in your app via a function pointer that we passed into qt_main_wrapper().
Please add a similar approach or some other solution to allow a purely dynamic build of Qt libraries for iOS.
Attachments
Issue Links
- is duplicated by
-
QTBUG-107857 Qt Shared Library project on iOS fails to build
- Closed
- relates to
-
QTBUG-42937 iOS, tvOS, watchOS: Add support for dynamic linking
- Open
-
QTBUG-62812 Provide Qt libraries on iOS as dynamically linked frameworks
- Open
- resulted from
-
QTBUG-109449 inlining QByteArray::isNull() causes BC break on static Qt builds
- Closed