Как кросс-платформенно встроить двоичные ресурсы в программу?

Мы разрабатываем приложения на C++ для Windows, Mac и Linux. В приложении много двоичных ресурсов, и по какой-то причине нам нужно упаковать их в исполняемый двоичный файл, а не размещать их в каталогах (или в пакете приложений Apple).

В настоящее время мы используем сценарий для преобразования этих ресурсов в константы массива C++, а затем компилируем и связываем их. Однако у этого подхода так много недостатков:

  • Вы должны скомпилировать исходный код ресурса, это требует времени и не является необходимым.
  • Исходные коды ресурсов будут проанализированы IDE. Поскольку они большие, аналитика кода сильно замедляется.
  • MSVC имеет ограничение на размер исходного кода, поэтому большие ресурсы (несколько МБ) должны быть разделены на множество частей, а затем объединены во время выполнения.

После некоторого изучения я нашел несколько решений:

  • В Windows я могу использовать файлы .rc и связанный с ними WinAPI.
  • В Linux я могу напрямую конвертировать произвольный двоичный файл в файл объект через objcopy.

Однако остаются еще несколько вопросов:

  • Использование WinAPI для извлечения ресурсов требует множества функций для доступа к одному ресурсу. Есть ли в винде более простые способы?
  • Как это сделать на Mac?

Когда-то был похожий вопрос SO: Как включить в программу файлы объектов данных (изображения и т. д.) И получить доступ к символам?, где я предложил довольно простую для реализации альтернативу: Встраивать двоичное содержимое в переменные.

Scheff's Cat 26.10.2018 08:05

@Scheff Это то же самое, что мы сейчас используем.

jiandingzhe 26.10.2018 09:47

Я должен был полностью прочитать твой вопрос. ;-) Насчет повторной компиляции я не особо боюсь. Если все сделано правильно, это касается только двоичных данных. (Код может использовать его с переменными extern - перекомпиляция этого кода не требуется.) Я пропустил часть с (несколько МБ) - да, это проблема именно с MSVC. (Обычно у нас нет таких больших данных.)

Scheff's Cat 26.10.2018 09:56
0
3
62
1

Ответы 1

Довольно распространенный прием, наиболее часто используемый для самораспаковывающихся архивов или языка сценариев для исполняемых компиляторов, заключается в добавлении ресурсов в конец исполняемого файла.

Окна:

copy app.exe+all-resources app-with-resources.exe

Linux:

cp executable executable-with-resources
cat all-resources >>executable-with-resources

Затем вы можете прочитать свой собственный исполняемый файл, например, с помощью fopen(argv[0]). Чтобы перейти в правильную позицию, то есть в начало ресурсов, одним из возможных решений является сохранение размера исполняемого файла без ресурсов в качестве последнего слова файла.

FILE* fp = fopen(argv[0], "rb");
fseek(fp, -sizeof(int), SEEK_END);
int beginResourcesOffset;
fread(&beginResourcesOffset, 1, sizeof(int), fp);
fseek(fp, beginResourcesOffset, SEEK_SET);

Будьте осторожны с этим решением, иногда антивирусу в Windows оно не нравится. Наверное, есть лучшие решения.

Другие вопросы по теме