在 iOS 应用程序中嵌入文件 (C++/Qt/cmake)

Posted

技术标签:

【中文标题】在 iOS 应用程序中嵌入文件 (C++/Qt/cmake)【英文标题】:Embedding files in an iOS app (C++/Qt/cmake) 【发布时间】:2020-11-20 14:50:57 【问题描述】:

ios c++/Qt 应用程序中,我需要传送一些文件并将它们保存在它们的目录结构中。

对于 android 版本,我们在创建 QApplication 之前捆绑了一个解压到目标上的 zip。

在 iOS 上,CMake 似乎无法将文件捆绑在树中: https://cmake.org/cmake/help/latest/prop_tgt/RESOURCE.html#prop_tgt:RESOURCE https://cmake.org/cmake/help/latest/prop_sf/MACOSX_PACKAGE_LOCATION.html

我不确定这是 cmake 的限制还是 iOS 的全局限制。 来自docs about iOS bundles:

它使用相对扁平的结构,几乎没有多余的目录,以节省磁盘空间并简化对文件的访问。

首选的方法是什么?

    是否有直接从 CMake 发送文件的解决方案? 如果没有,我怎样才能做到这一点,以便在创建 QApplication 之前它们可用?

xcode 命令

感谢@Cy-4AH,我在 Xcode 中添加了文件夹,并且可以获得执行此操作的命令:

CpResource _PATH_TO_DIRECTORY_ _APP_BUNDLE_DIRECTORY_/_RESOURCE_DIR_NAME_
cd /Users/denis/opt/qfield/ios/QField
export PATH="....."
builtin-copy -exclude .DS_Store -exclude CVS -exclude .svn -exclude .git -exclude .hg -strip-debug-symbols -strip-tool /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/strip -resolve-src-symlinks _PATH_TO_DIRECTORY_ _APP_BUNDLE_DIRECTORY_

但是我怎样才能从 cmake 创建呢? builtin-copy是一个xcode命令。


简单的系统复制命令

从旧的 (2008) discussion 开始,我们可以使用简单的 cp 命令。 这适用于签名,但随后我收到错误unsealed contents present in the bundle root

从这个answer 看来,我不能简单地在资源目录中添加文件夹。来自文档anatomy of framework bundles:Nonlocalized resources reside at the top level of the Resources directory

【问题讨论】:

只需放入 app bundle ????‍♂️。您可以在 xcode 构建日志中查看它如何将文件复制到包中并使用 CMake 进行相同的调用 非常感谢@Cy-4AH,这让我更进一步。但问题仍然存在于如何在不实际在 xcode 中执行此操作的情况下从 cmake 触发此操作。 我不完全记得几年前我们是如何解决这个问题的,但我记得我在 CMake 的 source_group 下添加了文件。从objective-c,我只是在没有文件的情况下访问它,比如 [[NSBundle mainBundle] pathForResource:@"test" ofType:@"txt"]; 【参考方案1】:

(免责声明:我不是 CMake 用户,可能有更 CMake-ey 的方式来做到这一点)

如果您可以设置构建后操作,则以下终端脚本可以有效地将文件从其他位置同步到您的包中。我在我的游戏引擎中使用它,因为它只在后续构建时复制更新或新文件,并保留目录结构:

mkdir -p PATHTO/ORIGINFOLDERNAME
mkdir -p PATHTOBUILDFOLDER/PROJECTNAME.app/Contents/Resources/DESTINATIONFOLDERNAME
rsync -avu --delete --exclude=".*" PATHTO/ORIGINFOLDERNAME/ PATHTOBUILDFOLDER/PROJECTNAME.app/Contents/Resources/DESTINATIONFOLDERNAME

mkdir 命令仅用于确保在删除文件夹时生成文件夹。

【讨论】:

这实际上是 Xcode 在其内置副本背后所做的事情。这将是一个可接受的解决方案。但最后 cmake 命令正在使用目录。我给你赏金,因为这将是一个解决方案。谢谢! 天哪,谢谢你的赏金!这是我的荣幸!【参考方案2】:

显然 CMake 方法也适用于目录。

target_sources($QT_IOS_TARGET PRIVATE $_resource)
set_source_files_properties($_resource PROPERTIES MACOSX_PACKAGE_LOCATION Resources)

它只会被添加到包的根目录,而不是Resources

【讨论】:

【参考方案3】:

如果嵌入文件不是太大,你可以考虑:

在您的源代码树中,生成一个将该文件嵌入为常量数组的 C++ 文件。例如,如果您的文件仅包含带有新行的 hello, world,您可能会有类似

/// file contents.cc
const char file_contents[] = "hello, world\n";

并在程序的开头(可能在您的 main 函数中,在您的 QApplication 之前)调用一个写入此类文件的 C++ 函数(可能在 /tmp/ 中)。

在您的构建自动化中(例如您的 Makefile 或您的 qmake 东西),有一些东西可以生成来自真正来源的 C++ contents.cc 文件

这是从 POSIX/Linux 的角度出发,根据您的 iOS 调整我的答案

【讨论】:

这看起来很笨拙。类似的方法是在资源中加入一个 zip 文件并将其解压缩(嵌入多个文件和一个目录结构)。干杯。

以上是关于在 iOS 应用程序中嵌入文件 (C++/Qt/cmake)的主要内容,如果未能解决你的问题,请参考以下文章

在 iOS 应用程序中嵌入文件 (C++/Qt/cmake)

如何使用 Qt/C++ 创建/读取/写入文件并使用程序在本地存储设置

Qt / C++ - 如何存储配置数据

在 Windows 上部署 Qt (C++/QML) 应用程序

用 C++/Qt 编写的程序中的 RTF/doc/docx 文本提取

在textedit Qt C ++中读取文本文件