什么聪明的解决方案在静态库中包含资源?

我有一个静态库Xcode 4项目,包括一个自制的渲染引擎,我在多个应用程序中重用这个引擎。 该引擎使用OpenGL ES 2.0,并通过扩展,使用着色器。 随着着色器变得更加复杂,我放弃了将它们作为NSStrings存储在源文件中,现在将它们存储为具有.vert和.frag扩展名的独立文本文件。

这适用于在自己的源中包含渲染引擎的应用程序; 着色器只是添加到应用程序的“复制包资源”构建阶段,并在运行时加载到NSStrings并编译,链接等。

如果加载这些着色器的渲染引擎位于静态库项目中,则此策略根本不起作用; 没有可以复制资源的包。 我目前不得不让静态lib渲染引擎的每个客户端项目在他们自己的“Copy Bundle Resources”构建阶段包含他们自己的着色器副本。 这是一个巨大的痛苦,并且首先打破了将渲染引擎变成静态库的大部分便利。

我想这是“静态库中的资源”这个更一般的问题的具体实例。 我能想到的最佳解决方案是将着色器文件的内容复制到头文件中的字符串中,然后将其包含在呈现引擎的源代码中。 我甚至可以通过一些“运行脚本”构建阶段魔法自动将.frag转换为.h,但遗憾的是它很复杂。

有什么我想念的吗?

您可以尝试创建一个框架,它似乎符合您的需求。 有关如何在此页面上为iOS创建此类框架的示例:

http://db-in.com/blog/2011/07/universal-framework-iphone-ios-2-0/

编写指南的人实际上使用这种技术来分发他自己的iOS 3D引擎项目 。

编辑:链接到较新版本的指南。

为了后代的利益,我将分享我最终使用的解决方案。 在较高的层次上,解决方案是将有问题的资源编译到应用程序二进制文件中,从而避免了将其复制到捆绑资源的需要。

我决定将任何文件数据编译到二进制文件中的通用且可靠的方法是将文件内容存储在头文件中的静态字节数组中。 假设已经创建了一个头文件并将其添加到静态lib目标中,我使用以下bash脚本来读取文件,并将其内容写为具有C语法的hex文字的字节数组。 然后,在“编译源代码”和“复制头”构建阶段之前 ,在“运行脚本”构建阶段运行脚本:

#!/bin/bash # Hexify.sh reads an input file, and hexdumps its contents to an output # file in C-compliant syntax. The final argument is the name of the array. infile=$1 outfile=$2 arrayName=$3 fileSize=$(stat -f "%z" $infile) fileHexString=$(hexdump -ve '1/1 "0x%.2x, "' $infile) prefix=$arrayName suffix="Size" variableName=$arrayName$suffix nullTermination="0x00" echo "//" > $headerFile echo "// This file was automatically generated by a build script." >> $headerFile echo "// Do not modify; the contents of this file will be overwritten on each build." >> $headerFile echo "//" >> $headerFile echo "" >> $headerFile; echo "#ifndef some_arbitrary_include_guard" >> $headerFile echo "#define some_arbitrary_include_guard" >> $headerFile echo "" >> $headerFile echo "static const int $variableName = $((fileSize+1));" >> $outfile echo "static const char $arrayName[$variableName] = {" >> $outfile echo -e "\t$fileHexString$nullTermination" >> $outfile echo "};" >> $outfile echo "#endif" >> $headerFile 

所以,例如,如果我有一个资源文件example.txt:

 Hello this is a file 

我要运行./Hexify.sh example.txt myHeader.h exampleArray ,标题看起来像这样:

 // // This file was automatically generated by a build script. // Do not modify; the contents of this file will be overwritten on each build. // #ifndef some_arbitrary_include_guard #define some_arbitrary_include_guard static const int exampleArraySize = 21; static const char exampleArray[exampleArraySize] = { 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x74, 0x68, 0x69, 0x73, 0x0a, 0x69, 0x73, 0x20, 0x61, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x00 }; #endif 

现在,在任何时候我都会从主包中加载所述资源,我可以改为引用该头文件中的字节数组。 请注意,我的脚本版本添加了一个空终止字节,这使得数据适合于创建字符串对象。 这可能并不适用于所有情况。

作为最后一个附录,我很抱歉,如果bash脚本让任何真正的bash程序员畏缩; 我几乎不知道我在用bash做什么。

我觉得你的痛苦伙伴,静态图书馆和资源并不顺利。 我认为最简单的方法是你已经提到的那个:写一个脚本来读取你的着色器,正确地转义它们并用C兼容的代码包装它们。

我不是专家,但也许你可以在连接时将着色器数据添加到Mach-O可执行文件的某些部分? 但这最终归结为与上面提到的相同的解决方案,唯一的缺点是你留下了丑陋的工作部分。

我会使用一些shell脚本来寻找字符串常量。 根据我的经验,PHP非常擅长做这种工作。 当然还有bash脚本,但我不太擅长。