Какие умные решения существуют для включения ресурсов в статическую библиотеку? - PullRequest
1 голос
/ 04 августа 2011

У меня есть проект статической библиотеки Xcode 4, который включает самодельный движок рендеринга, и я повторно использую этот движок в нескольких приложениях. Этот движок использует OpenGL ES 2.0 и, соответственно, шейдеры. Поскольку шейдеры усложнились, я перестал хранить их как NSStrings в исходном файле и теперь храню их как отдельные текстовые файлы с расширениями .vert и .frag.

Это прекрасно работает для приложений, которые включают движок рендеринга в своем собственном источнике; шейдеры просто добавляются в фазу сборки приложения «Копировать комплекты ресурсов», загружаются во время выполнения в строки NSS и компилируются, связываются и т. д.

Эта стратегия не работает вообще, если механизм рендеринга, который загружает эти шейдеры, находится в проекте статической библиотеки; нет пакета для копирования ресурсов. В настоящее время я вынужден включать в каждый клиентский проект движка статического рендеринга библиотек свои собственные копии шейдеров на своей собственной фазе сборки «Копировать комплект ресурсов». Это огромная боль, и в первую очередь она сводит на нет значительную часть удобства превращения движка рендеринга в статическую библиотеку.

Полагаю, это конкретный случай более общей проблемы "Ресурсы в статической библиотеке". Лучшее решение, которое я могу придумать, - это копирование содержимого файлов шейдеров в строки в заголовочном файле, которые затем включаются в источник движка рендеринга. Возможно, я даже смогу автоматизировать преобразование из .frag в .h с помощью некоторой магии фазы запуска «Run Scripts», но, к сожалению, это сложно.

Есть что-то, что я пропускаю?

Ответы [ 3 ]

3 голосов
/ 17 августа 2011

В интересах потомства, я поделюсь решением, которое я использовал в конечном итоге.На высоком уровне решение состоит в том, чтобы скомпилировать рассматриваемый ресурс в двоичный файл приложения, что устраняет необходимость также копировать его для объединения ресурсов.

Я решил, что общий и надежный способ компилировать любые данные файла в двоичный файл - это сохранить содержимое файла в статическом байтовом массиве в заголовочном файле.Предполагая, что уже есть заголовочный файл, созданный и добавленный к статической цели lib, я сделал следующий скрипт bash, чтобы прочитать файл и записать его содержимое в виде байтового массива шестнадцатеричных литералов с синтаксисом C.Затем я запускаю сценарий в фазе сборки «Run Script» перед фазами сборки «Исходники компиляции» и «Копии заголовков»:

#!/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

Так, например, если у меня есть пример файла ресурсов.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.

2 голосов
/ 04 августа 2011

Я чувствую, что твой приятель, статические библиотеки и ресурсы не подходят друг другу.Я думаю, что самый простой способ сделать это - тот, который вы уже упомянули: написать скрипт, который читает ваши шейдеры, экранирует их должным образом и оборачивает в C-совместимый код.

Я не эксперт, но, возможно, выМожно ли добавить данные шейдера в какой-либо раздел вашего исполняемого файла Mach-O при связывании?Но в конечном итоге это сводится к тому же решению, как упомянуто выше, с единственным недостатком, который у вас остался с уродливой частью работы.

Я бы пошел на строковые константы, используя какой-то сценарий оболочки.PHP по моему опыту довольно хорошо справляется с такой работой.И, конечно, скрипты bash, но я не слишком хорош в этом.

1 голос
/ 04 августа 2011

Вы можете попытаться создать фреймворк, который соответствует вашим потребностям. Вот пример того, как создать такую ​​платформу для iOS на этой странице:

http://db -in.com / блог / 2011/07 / универсальный-рамка-Iphone-КСН-2-0 /

Парень, который написал руководство, на самом деле использует эту технику для распространения своего собственного проекта 3D-движка iOS .

Редактировать: связано с более новой версией руководства.

...