diff --git a/mkspecs/features/ios/qt.prf b/mkspecs/features/ios/qt.prf index 80d4907acd..f89cb0c287 100644 --- a/mkspecs/features/ios/qt.prf +++ b/mkspecs/features/ios/qt.prf @@ -17,8 +17,60 @@ equals(TEMPLATE, app):contains(QT, gui(-private)?) { # need to generate an import for it. CONFIG -= import_qpa_plugin - # FIXME: Solve using 'ld -r -alias -unexported_symbol' instead - !no_main_wrapper: DEFINES += main=qt_user_main + !no_main_wrapper { + # Instead of messing with the user's main function we go the other + # way and change the application entry point to call our main wrapper. + # This entry point is the 'start' symbol, provided by crt1.o, so we + # make a copy of the file and rename the '_main' unresolved symbol + # to our wrapper function, '_qtmn', injecting ourselves into the app + # startup. Once Apple starts shipping the LLVM linker (lld) we may + # get rid of this step completely and just pass -e _qtmn to the + # linker, taking advantage of the new LC_MAIN load command. + + # We use xcodebuild to resolve the location of the crt1 object file + # as we know that it lives in the same location as the c library. + c_library_path = $$system("/usr/bin/xcodebuild -sdk $$QMAKE_MAC_SDK -find-library c 2>/dev/null") + + # We also know that iOS 3.1 and up uses crt1.3.1.o (technically not + # true for simulator, but the SDK has a symlink to the correct file). + original_crt_path = $$dirname(c_library_path)/crt1.3.1.o + + xcode_objects_path = "$(OBJECT_FILE_DIR_$(CURRENT_VARIANT))/$(CURRENT_ARCH)" + custom_crt_filename = "crt1_qt.o" + custom_crt_path = "$$xcode_objects_path/$$custom_crt_filename" + + EOC = $$escape_expand(\\n\\t) + create_custom_crt.commands = \ + # Copy original crt1 to build directory + "$$QMAKE_COPY_FILE $$original_crt_path $$custom_crt_path $$EOC" \ + # And rename all occurrences of _main to _qtmn + "strings -t d - $${custom_crt_path}" \ + "| sed -n 's/^\\([0-9]\\{1,\\}\\) _main\$\$/\1/p'" \ + "| while read offset; do" \ + "printf '_qtmn'" \ + "| dd of=$${custom_crt_path} bs=1 seek=\$\$offset conv=notrunc >/dev/null 2>&1" \ + "; done" + create_custom_crt.depends = $$original_crt_path + create_custom_crt.target = $$custom_crt_path + preprocess.depends = create_custom_crt + QMAKE_EXTRA_TARGETS += create_custom_crt preprocess + + clean_custom_crt.commands = "$$QMAKE_DEL_FILE $$custom_crt_path" + preprocess_clean.depends += clean_custom_crt + QMAKE_EXTRA_TARGETS += clean_custom_crt preprocess_clean + + # Prevent usage of new LC_MAIN load command, which skips start/crt1 + # and calls main from the loader. We rely on injecting into start. + QMAKE_LFLAGS += -Wl,-no_new_main + + # Explicitly link against our modified crt1 object + QMAKE_LFLAGS += -nostartfiles -l$${custom_crt_filename} + + # Workaround for QMAKE_PBX_LIBPATHS mangling the Xcode variables + lib_search_path.name = LIBRARY_SEARCH_PATHS + lib_search_path.value = $$xcode_objects_path + QMAKE_MAC_XCODE_SETTINGS += lib_search_path + } } load(qt) diff --git a/src/plugins/platforms/ios/ios.pro b/src/plugins/platforms/ios/ios.pro index 5a2129eb08..263577d43f 100644 --- a/src/plugins/platforms/ios/ios.pro +++ b/src/plugins/platforms/ios/ios.pro @@ -10,7 +10,6 @@ LIBS += -framework Foundation -framework UIKit -framework QuartzCore OBJECTIVE_SOURCES = \ plugin.mm \ qiosmain_wrapper.mm \ - qiosmain_dummy.mm \ qiosintegration.mm \ qioswindow.mm \ qiosscreen.mm \ diff --git a/src/plugins/platforms/ios/qiosapplicationdelegate.mm b/src/plugins/platforms/ios/qiosapplicationdelegate.mm index 52d94f38fb..d4fd613ae3 100644 --- a/src/plugins/platforms/ios/qiosapplicationdelegate.mm +++ b/src/plugins/platforms/ios/qiosapplicationdelegate.mm @@ -46,7 +46,7 @@ #include -extern int qt_user_main(int argc, char *argv[]); +extern "C" int main(int argc, char *argv[]); @implementation QIOSApplicationDelegate @@ -87,7 +87,7 @@ extern int qt_user_main(int argc, char *argv[]); strcpy(argv[i], [arg cStringUsingEncoding:[NSString defaultCStringEncoding]]); } - qt_user_main(argc, argv); + main(argc, argv); delete[] argv; } diff --git a/src/plugins/platforms/ios/qiosintegration.mm b/src/plugins/platforms/ios/qiosintegration.mm index 7fd6015a2f..cbf9dba862 100644 --- a/src/plugins/platforms/ios/qiosintegration.mm +++ b/src/plugins/platforms/ios/qiosintegration.mm @@ -65,10 +65,7 @@ QIOSIntegration::QIOSIntegration() << "Error: You are creating QApplication before calling UIApplicationMain.\n" << "If you are writing a native iOS application, and only want to use Qt for\n" << "parts of the application, a good place to create QApplication is from within\n" - << "'applicationDidFinishLaunching' inside your UIApplication delegate.\n" - << "If you instead create a cross-platform Qt application and do not intend to call\n" - << "UIApplicationMain, you need to link in libqtmain.a, and substitute main with qt_main.\n" - << "This is normally done automatically by qmake.\n"; + << "'applicationDidFinishLaunching' inside your UIApplication delegate.\n"; exit(-1); } diff --git a/src/plugins/platforms/ios/qiosmain_dummy.mm b/src/plugins/platforms/ios/qiosmain_dummy.mm deleted file mode 100644 index 28d7e59381..0000000000 --- a/src/plugins/platforms/ios/qiosmain_dummy.mm +++ /dev/null @@ -1,56 +0,0 @@ -/**************************************************************************** -** -** 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 - -/* - 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/qiosmain_wrapper.mm b/src/plugins/platforms/ios/qiosmain_wrapper.mm index d9b8c7311e..cb9a2c161e 100644 --- a/src/plugins/platforms/ios/qiosmain_wrapper.mm +++ b/src/plugins/platforms/ios/qiosmain_wrapper.mm @@ -41,18 +41,7 @@ #include "qiosapplicationdelegate.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[]) +extern "C" int qtmn(int argc, char *argv[]) { @autoreleasepool { return UIApplicationMain(argc, argv, nil, NSStringFromClass([QIOSApplicationDelegate class]));