【问题标题】:QT IOS linker error entry point (_main) undefinedQT IOS 链接器错误入口点 (_main) 未定义
【发布时间】:2020-10-13 16:21:10
【问题描述】:

我目前正在尝试在 IOS 上编译一个基于 QT 的项目。 我正在使用 cmake 创建和配置 .xcodeproject 和 xcode 以在设备上运行应用程序。

我成功删除了所有以前的链接器错误,现在我正在处理入口点。

我的 main.cpp 看起来像这样

    int main(int argc, char **argv) {
        QApplication app(argc, argv);
        return app.exec();
     }

这给了我以下错误:

错误:您正在调用 UIApplicationMain 之前创建 QApplication。 如果您正在编写原生 iOS 应用程序,并且只想使用 Qt 对于应用程序的某些部分,创建 QApplication 的好地方是 从您的 UIApplication 内的“applicationDidFinishLaunching”中 委托。

我在这篇文章中发现你应该重命名 main 并且 qt 会为你完成这项工作并启动应用程序生命周期

Run-time error for Qt application on ios built via CMake

Qt XCode iOS entry point

#if defined(Q_OS_IOS)
extern "C" int qtmn(int argc, char** argv) {
#else
int main(int argc, char **argv) {
#endif
    QApplication app(argc, argv);
    return app.exec();
}

但现在我正在处理这个错误

ld:入口点 (_main) 未定义。用于架构 arm64

在第一篇文章中,他们说我应该有一个 your/qt/root/path/mkspecs/macx-ios-clang/rename_main.sh 脚本

我没有,在另一篇文章中,答案是:

重命名 main -> qtmn(源自 qt),重建 QT,并从我的 main() 调用 qt_main_wrapper。

但我不知道如何处理“重建并调用 qt_main_wrapper”

【问题讨论】:

  • 我从来没有听说过替换你的 main() 来让 iOS 工作。我有一个在 iTunes Store 上发布的应用程序,无需任何特殊处理(即 iOS、android 和 win32 的 main() 不需要#ifdefs),它肯定可以正常工作。我的主要看起来像这样: int main(...) { return my_singleton::run(args) };我的 my_singleton::run() 是静态函数,如下所示: int my_singleton::run() { singleton_ = new myQApplication(args) } 其中 myQApplication 是 QApplication 的直接后代。
  • @markus-nm 谢谢,我在这里更新了我的问题forum.qt.io/topic/82102/…,看起来 Qt 没有将我的 QApplication 包装在等效的 ObjectiveC 中

标签: ios xcode qt


【解决方案1】:

解决方法是添加链接器标志

set(CMAKE_EXE_LINKER_FLAGS ${CMAKE_EXE_LINKER_FLAGS} "-Wl,-e,_qt_main_wrapper")

Qt 需要一个 UIApplication 来实例化,它是在 UIKit 中定义的应用程序。您可以在其中归档 qt_main_wrapper 的定义: qtbase/src/plugins/platforms/ios/qioseventdispatcher.mm

-e 选项为您的程序指定另一个入口点,这将创建此 UIApplication。

如果你遵循 QApplication 的构造函数,它将在 ios 插件中结束,如果未设置“UIApplication”单例,则会启动错误。

最后,如果你的应用程序使用了一些 QML

set(CMAKE_EXE_LINKER_FLAGS ${CMAKE_EXE_LINKER_FLAGS} "-u _qt_registerPlatformPlugin")

您需要在 main.cpp 中加载所有不同的插件

Q_IMPORT_PLUGIN(QtQuick2Plugin)

并在您的 LD 标志中添加 .a 的路径,例如:

set (LINK_LIBRARIES ${LINK_LIBRARIES} "${USE_QT_DIR}/qml/QtQuick/Controls.2/libqtquickcontrols2plugin_debug.a")

对于 QtControls2,您还需要添加

set (LINK_LIBRARIES ${LINK_LIBRARIES} "${USE_QT_DIR}/lib/libQt5QuickControls2_debug.a")
set (LINK_LIBRARIES ${LINK_LIBRARIES} "${USE_QT_DIR}/lib/libQt5QuickTemplates2_debug.a")

这有点麻烦,但是你可以在你的项目上运行位于 Qt/5.7/ios/bin 中的qmlimportscanner

qmlimportscanner -rootPath path/to/app/qml/directory -importPath path/to/qt/qml/directory

它将为您提供一个包含项目使用的所有插件的 JSON。 这是qmake调用的脚本,如果我有时间我会添加一个脚本来添加不同的插件。

【讨论】:

  • 太棒了!直到现在我才找到入口点重命名技巧
【解决方案2】:

我刚刚使用 Qt 5.15.1 进行了测试,现在大多数 CMake iOS 构建问题似乎已得到修复。剩下的唯一临时项目设置是

set(CMAKE_EXE_LINKER_FLAGS ${CMAKE_EXE_LINKER_FLAGS} "-Wl,-e,_qt_main_wrapper")

https://bugreports.qt.io/browse/QTBUG-87060 作为 Qt 6 的一部分发布时,这个问题也将得到修复。

【讨论】:

    猜你喜欢
    • 2016-03-09
    • 1970-01-01
    • 2016-02-11
    • 2022-01-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多