summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTor Arne Vestbø <tor.arne.vestbo@digia.com>2013-06-06 13:48:36 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-06-12 12:35:02 +0200
commit5c8aa27111fd51c8dff78fd0a276648aea08d4c1 (patch)
tree07edb235ab9c733f8f20490b01289a53f804d374
parente99fc91c585d5a5a6ec9e9196874f18b69254a5a (diff)
iOS: Remove need for separate qtiosmain library
We can combine the hybrid and non-hybrid use-cases into a single static library if we are careful about which symbols are included in which object files. By limiting the main() and qt_user_main() functions to their own translation units, the linker will only pick them up if they are missing at link time (the user's program do not provide them). This technique is resilient to the -ObjC linker flag, which includes all object files that implement an ObjectiveC class or category, but will fail if the -all_load flag is passed to the linker, as we'll then have duplicate symbols for either main() or qt_user_main(). The latter should not happen unless the user provides the flag manually, and in the case he or she does, there's ways to work around it by providing less global flags such as -ObjC or -force_load. Change-Id: Ie2f8e10a7265d007bf45cb1dd83f19cff0693551 Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@digia.com> Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@digia.com>
-rw-r--r--mkspecs/features/ios/default_post.prf10
-rw-r--r--src/plugins/platforms/ios/ios.pro39
-rw-r--r--src/plugins/platforms/ios/plugin.pro36
-rw-r--r--src/plugins/platforms/ios/qiosapplicationdelegate.mm48
-rw-r--r--src/plugins/platforms/ios/qiosmain_dummy.mm56
-rw-r--r--src/plugins/platforms/ios/qiosmain_wrapper.mm (renamed from src/plugins/platforms/ios/qtmain.mm)56
-rw-r--r--src/plugins/platforms/ios/qtmain.pro8
7 files changed, 153 insertions, 100 deletions
diff --git a/mkspecs/features/ios/default_post.prf b/mkspecs/features/ios/default_post.prf
index 31efc4d418..fea5aea44d 100644
--- a/mkspecs/features/ios/default_post.prf
+++ b/mkspecs/features/ios/default_post.prf
@@ -28,14 +28,8 @@ gui_app {
# need to generate an import for it.
CONFIG -= import_qpa_plugin
- !no_main_wrapper {
- # We link the iosmain library manually as well, since it's not really a plugin
- lib_name = qiosmain
- lib_path_and_base = $$[QT_INSTALL_PLUGINS/get]/platforms/lib$${lib_name}$$qtPlatformTargetSuffix()
- LIBS += -L$$[QT_INSTALL_PLUGINS/get]/platforms -l$${lib_name}$$qtPlatformTargetSuffix()
- LIBS += $$fromfile($${lib_path_and_base}.prl, QMAKE_PRL_LIBS)
- DEFINES += main=qt_main
- }
+ # FIXME: Solve using 'ld -r -alias -unexported_symbol' instead
+ !no_main_wrapper: DEFINES += main=qt_user_main
}
contains(MAKEFILE_GENERATOR, XCODE) {
diff --git a/src/plugins/platforms/ios/ios.pro b/src/plugins/platforms/ios/ios.pro
index 842ff17f1c..6ce0ca748e 100644
--- a/src/plugins/platforms/ios/ios.pro
+++ b/src/plugins/platforms/ios/ios.pro
@@ -1,3 +1,38 @@
-TEMPLATE = subdirs
+TARGET = qios
-SUBDIRS += plugin.pro qtmain.pro
+PLUGIN_TYPE = platforms
+load(qt_plugin)
+
+QT += core-private gui-private platformsupport-private
+LIBS += -framework Foundation -framework UIKit -framework QuartzCore
+
+OBJECTIVE_SOURCES = \
+ plugin.mm \
+ qiosmain_wrapper.mm \
+ qiosmain_dummy.mm \
+ qiosintegration.mm \
+ qioswindow.mm \
+ qiosscreen.mm \
+ qioseventdispatcher.mm \
+ qiosbackingstore.mm \
+ qiosapplicationdelegate.mm \
+ qiosviewcontroller.mm \
+ qioscontext.mm \
+ qiosinputcontext.mm \
+ qiostheme.mm \
+ qiosglobal.mm
+
+HEADERS = \
+ qiosintegration.h \
+ qioswindow.h \
+ qiosscreen.h \
+ qioseventdispatcher.h \
+ qiosbackingstore.h \
+ qiosapplicationdelegate.h \
+ qiosviewcontroller.h \
+ qioscontext.h \
+ qiosinputcontext.h \
+ qiostheme.h \
+ qiosglobal.h
+
+#HEADERS = qiossoftwareinputhandler.h
diff --git a/src/plugins/platforms/ios/plugin.pro b/src/plugins/platforms/ios/plugin.pro
deleted file mode 100644
index 5f46ea7ef5..0000000000
--- a/src/plugins/platforms/ios/plugin.pro
+++ /dev/null
@@ -1,36 +0,0 @@
-TARGET = qios
-
-PLUGIN_TYPE = platforms
-load(qt_plugin)
-
-QT += core-private gui-private platformsupport-private
-LIBS += -framework Foundation -framework UIKit -framework QuartzCore
-
-OBJECTIVE_SOURCES = \
- plugin.mm \
- qiosintegration.mm \
- qioswindow.mm \
- qiosscreen.mm \
- qioseventdispatcher.mm \
- qiosbackingstore.mm \
- qiosapplicationdelegate.mm \
- qiosviewcontroller.mm \
- qioscontext.mm \
- qiosinputcontext.mm \
- qiostheme.mm \
- qiosglobal.mm
-
-HEADERS = \
- qiosintegration.h \
- qioswindow.h \
- qiosscreen.h \
- qioseventdispatcher.h \
- qiosbackingstore.h \
- qiosapplicationdelegate.h \
- qiosviewcontroller.h \
- qioscontext.h \
- qiosinputcontext.h \
- qiostheme.h \
- qiosglobal.h
-
-#HEADERS = qiossoftwareinputhandler.h
diff --git a/src/plugins/platforms/ios/qiosapplicationdelegate.mm b/src/plugins/platforms/ios/qiosapplicationdelegate.mm
index 10cbe529c4..571de9ffda 100644
--- a/src/plugins/platforms/ios/qiosapplicationdelegate.mm
+++ b/src/plugins/platforms/ios/qiosapplicationdelegate.mm
@@ -39,8 +39,11 @@
**
****************************************************************************/
-#import "qiosapplicationdelegate.h"
+#include "qiosapplicationdelegate.h"
+
+#include "qiosviewcontroller.h"
#include "qioswindow.h"
+
#include <QtCore/QtCore>
@implementation QIOSApplicationDelegate
@@ -93,4 +96,47 @@
@end
+extern int qt_user_main(int argc, char *argv[]);
+
+@implementation QIOSMainWrapperApplicationDelegate
+
+- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
+{
+ self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
+ self.qiosViewController = [[[QIOSViewController alloc] init] autorelease];
+ self.window.rootViewController = self.qiosViewController;
+
+#ifdef QT_DEBUG
+ self.window.backgroundColor = [UIColor cyanColor];
+#endif
+
+ [self.window makeKeyAndVisible];
+
+ // We schedule the main-redirection for the next eventloop pass so that we
+ // can return from this function and let UIApplicationMain finish its job.
+ [NSTimer scheduledTimerWithTimeInterval:.01f target:self
+ selector:@selector(runUserMain) userInfo:nil repeats:NO];
+
+ if ([QIOSApplicationDelegate instancesRespondToSelector:_cmd])
+ return [super application:application didFinishLaunchingWithOptions:launchOptions];
+ else
+ return YES;
+}
+
+- (void)runUserMain
+{
+ NSArray *arguments = [[NSProcessInfo processInfo] arguments];
+ int argc = arguments.count;
+ char **argv = new char*[argc];
+ for (int i = 0; i < argc; ++i) {
+ NSString *arg = [arguments objectAtIndex:i];
+ argv[i] = reinterpret_cast<char *>(malloc([arg lengthOfBytesUsingEncoding:[NSString defaultCStringEncoding]]));
+ strcpy(argv[i], [arg cStringUsingEncoding:[NSString defaultCStringEncoding]]);
+ }
+
+ qt_user_main(argc, argv);
+ delete[] argv;
+}
+
+@end
diff --git a/src/plugins/platforms/ios/qiosmain_dummy.mm b/src/plugins/platforms/ios/qiosmain_dummy.mm
new file mode 100644
index 0000000000..28d7e59381
--- /dev/null
+++ b/src/plugins/platforms/ios/qiosmain_dummy.mm
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/qglobal.h>
+
+/*
+ This file provides a dummy implementation of qt_user_main, so that
+ we don't get an undefined symbol in the hybrid use-case, where we
+ don't rename main() to qt_user_main(). As long as the linker is not
+ passed -all_load, this translation unit is only picked up and used
+ if qt_user_main is not defined by the user's code.
+*/
+
+int qt_user_main(int, char **)
+{
+ qFatal("Hit dummy qt_user_main, this should never happen!");
+ return 0;
+}
diff --git a/src/plugins/platforms/ios/qtmain.mm b/src/plugins/platforms/ios/qiosmain_wrapper.mm
index 19c98f2c59..4533add424 100644
--- a/src/plugins/platforms/ios/qtmain.mm
+++ b/src/plugins/platforms/ios/qiosmain_wrapper.mm
@@ -40,7 +40,17 @@
****************************************************************************/
#include "qiosapplicationdelegate.h"
-#include "qiosviewcontroller.h"
+
+/*
+ This file provides a wrapper implementation of main() for the non-
+ hybrid use-case. The user's main is renamed to qt_user_main by the
+ build rules, and we'll call out to that main at the appropriate time.
+
+ This file purposly only exports a single symbol, _main, so that
+ when the linker considers the translation unit for inclusion it
+ will discard it when main has already been defined in the user's
+ application for the hybrid use-case.
+*/
int main(int argc, char *argv[])
{
@@ -48,47 +58,3 @@ int main(int argc, char *argv[])
return UIApplicationMain(argc, argv, nil, NSStringFromClass([QIOSMainWrapperApplicationDelegate class]));
}
}
-
-extern int qt_main(int argc, char *argv[]);
-
-@implementation QIOSMainWrapperApplicationDelegate
-
-- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
-{
- self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
- self.qiosViewController = [[[QIOSViewController alloc] init] autorelease];
- self.window.rootViewController = self.qiosViewController;
-
-#ifdef QT_DEBUG
- self.window.backgroundColor = [UIColor cyanColor];
-#endif
-
- [self.window makeKeyAndVisible];
-
- // We schedule the main-redirection for the next eventloop pass so that we
- // can return from this function and let UIApplicationMain finish its job.
- [NSTimer scheduledTimerWithTimeInterval:.01f target:self
- selector:@selector(runUserMain) userInfo:nil repeats:NO];
-
- if ([QIOSApplicationDelegate instancesRespondToSelector:_cmd])
- return [super application:application didFinishLaunchingWithOptions:launchOptions];
- else
- return YES;
-}
-
-- (void)runUserMain
-{
- NSArray *arguments = [[NSProcessInfo processInfo] arguments];
- int argc = arguments.count;
- char **argv = new char*[argc];
- for (int i = 0; i < argc; ++i) {
- NSString *arg = [arguments objectAtIndex:i];
- argv[i] = reinterpret_cast<char *>(malloc([arg lengthOfBytesUsingEncoding:[NSString defaultCStringEncoding]]));
- strcpy(argv[i], [arg cStringUsingEncoding:[NSString defaultCStringEncoding]]);
- }
-
- qt_main(argc, argv);
- delete[] argv;
-}
-
-@end
diff --git a/src/plugins/platforms/ios/qtmain.pro b/src/plugins/platforms/ios/qtmain.pro
deleted file mode 100644
index cbcb272217..0000000000
--- a/src/plugins/platforms/ios/qtmain.pro
+++ /dev/null
@@ -1,8 +0,0 @@
-TARGET = qiosmain
-
-PLUGIN_TYPE = platforms
-load(qt_plugin)
-
-QT += gui-private
-
-OBJECTIVE_SOURCES = qtmain.mm