有哪些聪明的解决方案可以将资源包含在静态库中?
我有一个静态库 Xcode 4 项目,其中包含一个自制的渲染引擎,并且我在多个应用程序中重复使用该引擎。该引擎使用 OpenGL ES 2.0 以及扩展的着色器。随着着色器变得更加复杂,我不再将它们存储为源文件中的 NSString,现在将它们存储为带有 .vert 和 .frag 扩展名的独立文本文件。
这对于在自己的源代码中包含渲染引擎的应用程序来说效果很好;着色器只是添加到应用程序的“复制捆绑资源”构建阶段,并在运行时加载到 NSStrings 中并进行编译、链接等。
如果加载这些着色器的渲染引擎位于静态库中,则此策略根本不起作用项目;没有可以复制资源的包。目前,我被迫让静态库渲染引擎的每个客户端项目在自己的“复制捆绑资源”构建阶段包含自己的着色器副本。这是一个巨大的痛苦,并且首先破坏了将渲染引擎变成静态库的大部分便利性。
我想这是“静态库中的资源”这个更普遍的问题的具体实例。我能想到的最佳解决方案是将着色器文件的内容复制到头文件中的字符串中,然后将其包含在渲染引擎的源代码中。我什至可以使用一些“运行脚本”构建阶段魔法自动从 .frag 到 .h 的转换,但不幸的是它看起来很复杂。
我有什么遗漏的吗?
I have a static library Xcode 4 project that includes a home-brewed rendering engine, and I re-use this engine in multiple apps. This engine uses OpenGL ES 2.0, and by extension, shaders. As shaders got more complicated, I moved away from storing them as NSStrings in a source file, and now store them as standalone text files with the .vert and .frag extensions.
This works fine for apps that include the rendering engine in their own source; the shaders are simply added to the app's "Copy Bundle Resources" build phase, and loaded at runtime into NSStrings and compiled, linked, etc.
This strategy doesn't work at all if the rendering engine that loads these shaders is in a static library project; there is no bundle into which to copy resources. I'm currently forced to have every client project of the static lib rendering engine include their own copies of the shaders in their own "Copy Bundle Resources" build phase. This is a giant pain, and defeats a large part of the convenience of making the render engine into a static lib in the first place.
I suppose this is specific instance of the more general problem of "Resources in a Static Library". The best solution I can think of is copying the shader files' contents into strings in a header file, which are then included in the rendering engine's source. I may even be able to automate the conversion from .frag to .h with some "Run Scripts" build phase magic, but it seems unfortunately complicated.
Is there anything I'm missing?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
为了后代的利益,我将分享我最终使用的解决方案。从较高层面来看,解决方案是将相关资源编译到应用程序二进制文件中,从而避免将其复制到捆绑资源中的需要。
我决定将任何文件数据编译为二进制文件的通用且可靠的方法是将文件内容存储在头文件中的静态字节数组中。假设已经创建了一个头文件并将其添加到静态 lib 目标中,我制作了以下 bash 脚本来读取文件,并使用 C 语法将其内容写入十六进制文字的字节数组。然后,我在编译源和复制头构建阶段之前的“运行脚本”构建阶段中运行脚本:
因此,例如,如果我有一个资源文件 example.txt:
我要运行 < code>./Hexify.sh example.txt myHeader.h exampleArray,标题将如下所示:
现在,在我从主包加载所述资源的任何时间点,我可以改为参考该头文件中的字节数组。请注意,我的脚本版本添加了一个空终止字节,这使得数据适合创建字符串对象。这可能并不适用于所有情况。
作为最后的附录,如果 bash 脚本让任何真正的 bash 程序员感到畏缩,我深表歉意;我几乎不知道我在用 bash 做什么。
For the benefit of posterity, I'll share the solution I ended up using. At a high level, the solution is to compile the resource in question into the application binary, thus obviating the need to also copy it to bundle resources.
I decided a generic and reliable way to compile any file data into the binary would be to store the file contents in a static byte array in a header file. Assuming there is already a header file created and added to the static lib target, I made the following bash script to read a file, and write its contents as a byte array of hex literals with C syntax. I then run the script in "Run Script" build phase before the Compile Sources and Copy Headers build phases:
So, for example, if I have a resource file example.txt:
And I were to run
./Hexify.sh example.txt myHeader.h exampleArray
, the header would look like this:Now, at any point in time that I would have loaded said resource from the main bundle, I can instead refer to the byte array in that header file. Note that my version of the script adds a null terminated byte, which makes the data suitable for creating string objects. That may not apply in all cases.
As one final addendum, I apologize if that bash script makes any real bash programmers cringe; I have almost no idea what I'm doing with bash.
我觉得你的痛苦伙伴,静态库和资源不能很好地结合在一起。我认为最简单的方法就是您已经提到的方法:编写一个脚本来读取着色器,正确转义它们并将它们包装在符合 C 的代码中。
我不是专家,但也许您可以在链接时将着色器数据添加到 Mach-O 可执行文件的某些部分?但这最终归结为与上面提到的相同的解决方案,唯一的缺点是你留下了工作中丑陋的部分。
我会使用一些 shell 脚本来获取字符串常量。根据我的经验,PHP 非常擅长完成此类工作。当然还有 bash 脚本,但我不太擅长。
I feel your pain buddy, static libraries and resources don't go well together. I think the easiest way to do this is the one you already mentioned: Write a script that reads your shaders, escapes them properly and wraps them in C-compliant code.
I'm no expert, but maybe you could add the shader data to some section of your Mach-O executable upon linkage? But this eventually boils down to the same solution as mentioned above, with the only disadvantage that you're left with the ugly part of the job.
I'd go for the string constants using some shell script. PHP in my experience is pretty good at doing this kind of work. And of course bash scripts, but I'm not too good at that.
您可以尝试创建一个框架,它似乎适合您的需求。此页面上有一个关于如何为 iOS 创建此类框架的示例:
http://db-in.com/blog/2011/07/universal-framework-iphone-ios-2-0/
编写该指南的人实际上使用这种技术来分发<一href="http://nineveh.gl/" rel="nofollow">他自己的 iOS 3D 引擎项目。
编辑:链接到新版本的指南。
You could try to create a framework, it seems to fit your needs. There's an example on how to create such a framework for iOS on this page:
http://db-in.com/blog/2011/07/universal-framework-iphone-ios-2-0/
The guy that wrote the guide actually uses this technique to distribute his own iOS 3D engine project.
Edit: linked to newer version of the guide.