c++ - 通过 CMake 构建的 ios 上 Qt 应用程序的运行时错误

标签 c++ ios qt cmake qt5

如果我构建一个 Qt/qmake 示例项目(在我的例子中是“analog clock”示例)并将其部署到运行 iOS 7.1 的设备上,一切都会很顺利:应用程序在设备上完美执行。 Chapeau - 来自 digia 的人们做了一项艰巨的工作,将 ios 工具链集成到他们的 Qt 工作流程中。

但是,如果我将 qmake 项目转换为 CMake 项目,事情就不会那么顺利了。我附上了 Qt-5.3.1 版本(见下文)中的模拟时钟示例,我在其中添加了一个 CMakeLists.txt 和一个运行 CMake 的脚本以生成适用于 iOS 的 XCode 项目。该项目编译甚至链接(我不得不添加一些额外的链接库,请参阅 CMake 源文件)。是的。

但这就是陷阱:应用程序在运行时崩溃并显示以下错误消息:

Error: Failed to load platform plugin “ios”

作为 this 中的评论线程状态必须通过项目设置“强制加载”libqios。这样做并没有太大改善情况,它只是将错误消息更改为:

Error: You are creating QApplication before calling UIApplicationMain. If you are writing a native iOS application, and only want to use Qt for parts of the application, a good place to create QApplication is from within 'applicationDidFinishLaunching' inside your UIApplication delegate.

我有两个问题:

  • 有谁知道运行时错误的问题是什么?我知道 qmake(和相应的 ios mkspecs)有一些魔力。但是如何将其转换为 CMake?
  • 为什么我必须手动将几个库(harfbuzzng、qios、libpng 和几个 iOS 框架)链接到我的目标? find_package(Qt5 ...) 不应该为我完成这项工作吗?

Here是包含我的 Qt-CMake 项目的 zip 文件的链接。我使用的 Qt 版本是 Qt-5.3.1 for iOS。

编辑:我发现如果将 qmake 示例从 Qt 示例文件夹结构中删除,它不会像这样工作。直接看Qt例子:path/to/Qt/examples/widgets/widgets/analogclock。

最佳答案

经过几个小时的探索,我找到了一种方法来为我的 iOS 版 Qt 应用程序创建 CMake 项目。我通过谷歌和检查 qmake 生成的输出得到的关键提示。我找到了真正发挥全部魔力的脚本,并将其部分应用到我的 CMake 源代码中。

这是对我有用的食谱。为了完整起见,我还添加了我在发布上述问题时已经知道的步骤:

  • 将 CMake 引入 ios 工具链。请参阅我的示例项目的 cmake/toolchain/ios.toolchain.cmake。它设置了几个 CMake 属性并寻找必要的工具和框架。 (我不记得我从哪里得到那个文件了——但如果你用谷歌搜索它,它也被用于其他几个项目。)你必须将这个设置文件作为参数传递给 CMake(见下文)。

  • 设置可执行文件的多个目标属性,将其转换为 (iOS) 应用程序包。应该清楚。请注意,有一个模板 Info.plist.in 将由 CMake 完成。

  • 修复 1:在 CMake 中手动将缺失的库和框架链接到应用程序。出于某种原因,find_package(Qt5 ...)不返回完整的依赖项列表。不过,我很可能在这里遗漏了一些东西。

  • 修复 2:确保强制加载 libqios 以避免出现有关缺少 iOS 插件的错误消息。在 CMake 中:

    set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -force_load ${YOUR_QT_ROOT_PATH}/plugins/platforms/libqios.a" )

  • 修复 3:删除 Info.plist.in 中的 Storyboard 键。这一步我不是很了解。该方法的灵感来自 this在 stackoverflow 上发帖。

    <key>UIMainStoryboardFile</key> <string>main</string>

  • 修复 4:现在最重要的是:对于 iOS,您必须使用相应的“C”格式版本重命名 main() 函数。显然,Qt 自带了它自己的 main入口点并将您编写的那个重命名为 qtmn() .这个 qmake 魔术是由这个脚本执行的:your/qt/root/path/mkspecs/macx-ios-clang/rename_main.sh。我不详细了解这背后的完整机制。就我而言,我可以重命名 main 的函数签名:

    // Replace... int main(int argc, char *argv[])

    // ... with this line: extern "C" int qtmn(int argc, char *argv[])

Here再次是我在问题中提到的同一个项目,这次是从上面应用的修复程序。要构建此项目,只需调用 build_ios.sh ,然后打开在构建文件夹中创建的 xcodeproj 文件。

注意:工作假设是 XCode 的正确版本(在我的例子中是 5.1.1)可用并且您拥有有效的签名身份(在 CMakeLists.txt 中更改它!)。此外,在我的示例项目(见下文)中,我假设为 iOS 构建的 OpenCV 可用。我需要它来解决链接器问题:OpenCV 附带的 libpng 中缺少一些对象。

关于c++ - 通过 CMake 构建的 ios 上 Qt 应用程序的运行时错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25042916/

相关文章:

c++ - openMP - 与 for 循环和私有(private)并行化

ios - 如何在 Swift 中创建一组委托(delegate)协议(protocol)项?

c++ - 将 Objective-C 代码转换为 C++ 以检测 OS X 上的用户空闲时间

c++ - Visual Studio 中的 QRC 资源文件

c++ - 加速从 C++ 文件中读取整数

c++ - 从 SQLite 中的准备语句获取原始 SQL 查询

ios - tableRow 内的 tableView.dequeueReusableCell()(_ :heightForRowAt:) method

c++ - MongoDB适用于日志分析项目

c++ - 如何从 Qt 中的标准 C++ 函数中获取值

ios - 加载新的 ViewController 导致 EXC_BAD_ACCESS