2

I am trying to bundle together some resources (images, music and data files) into my binary application (written in C++).

I want to have everything contained in a single executable file (so that I could just ship the (large) executable file and it would work, no assets could be deleted).

I see Visual Studio and windows have something called resources files that look like they are designed to do just this.

However, I am interested if there is a cross platform way, or, if there is not, what the Linux equivalent to resource files is (if there is one, provided my any IDE or compiler).

I want to be able to have my entire program contained within one file and so I am not interested in a separate assets or resources directory.

I have found several older answers but find it hard to believe there is not a modern way to do this on Linux.

It seems like the solution is to:

A. Use resource files on Windows

B. Use something that converts the resource into a .c char array and load that on Linux.

Is this really what it takes and if so: what would be the most convenient way to include this process in a cross platform build cycle? Is there some function that CMAKE can run before a program is built?

Startec
  • 12,496
  • 23
  • 93
  • 160
  • 1
    Try Qt ? Qt can embed resource directly into the final executable. – llllllllll Jan 18 '18 at 16:47
  • What do you mean, "modern"? There's not a lot of bells and whistles you can put on packing a binary file into your executable... – Quentin Jan 18 '18 at 16:47
  • Your link mentions this: https://stackoverflow.com/questions/2627004/embedding-binary-blobs-using-gcc-mingw which seems like a great solution. – HolyBlackCat Jan 18 '18 at 16:47
  • @Quentin I think the way that Visual Studio and Windows handles it (within the IDE) actually does qualify as lots of "bells and whistles" when compared to using a linker and `objdump`. – Startec Jan 18 '18 at 16:49
  • You have provided links to two duplicate questions and summarized them here. I'm not sure what more can be said. Is your question specifically about cmake? If so, you should add a cmake tag. – interjay Jan 18 '18 at 16:55
  • Your analogy with resource files used by Windows does not seem right to me. Windows resource files are external files that need to be distributed along with the executable. They are not embedded in the executable. – R Sahu Jan 18 '18 at 16:55
  • @Startec oh, so you're looking for an IDE then. What exactly would a simple build step, where the linker packs your resource files into object files, be missing? – Quentin Jan 18 '18 at 16:56
  • 3
    @RSahu .rc files are text files which list arbitrary files to be packed into the executable by the Resource Compiler. In fact I'm knees deep in there right now, waiting for it to finish ;) – Quentin Jan 18 '18 at 16:58
  • @Quentin, thanks for the clarification. – R Sahu Jan 18 '18 at 17:00
  • @Quentin so the files are "packed into the executable" by the resource compiler? Do you need to include any file with the executable once the resource compiler is done? – Startec Jan 18 '18 at 17:13
  • 3
    @Startec I have oversimplified, my bad. The resource compiler reads in .rc files, locates the listed files and packs them into a .res file, which is passed to the linker along with the usual .obj files and then linked into the executable. Retrieving a resource is done via [`LoadResource`](https://msdn.microsoft.com/en-us/library/windows/desktop/ms648046(v=vs.85).aspx), which hands you back a `void*` to the beginning of the resource. – Quentin Jan 18 '18 at 17:18
  • @Quentin gotcha. So at that point, you can move your application around without worrying about breaking anything. There is no resource file nor text file that you need to include those resources? – Startec Jan 18 '18 at 17:21
  • 1
    @Startec indeed, the executable is then stand-alone. – Quentin Jan 18 '18 at 17:22
  • This needs to be created for Linux. – Startec Jan 18 '18 at 17:22
  • @Startec well, it's pretty much functionally identical to what [that](https://stackoverflow.com/questions/2627004/embedding-binary-blobs-using-gcc-mingw) Q&A does, except that you get a symbol instead of calling a function. It does not have the GUI-parsing stuff that RC does, but that is not portable anyway. Which leads to my question above: what more are you looking for? – Quentin Jan 18 '18 at 17:32
  • I closed as duplicate since you aren't answering questions about what you'd like to know that isn't answered by previous questions. – interjay Jan 18 '18 at 17:39
  • I wrote a tool that compiles header files with a list of resource paths directly to object files or static libraries: https://stackoverflow.com/a/52843063/6846474 –  Oct 16 '18 at 19:52

1 Answers1

3

I've seen people xxd|sed their binary resources into C const uint8_t arrays. It could be c++ifyed:

Resource1.h

#include <cstdint>
#include <array>
extern std::array<uint8_t, 1024> resource1;

Resource1.cc

#include "Resource1.h"
const std::array<uint8_t, 1024> resource1 = {
    0x42, 0x24, 0x18, ...
    ...
}

If you're not fond of regexp, here is a starting point:

hexdump file.bin | sed 's/^[0-9a-f]* \?//;s/ \?\([0-9a-f]\{2\}\) \?/0x\1, /g'

which outputs something like

0x5b, 0x6b, 0x32, 0x50, 0x69, 0x50, 0x53, 0x64, 0x61, 0x65, 0x63, 0x72, 0x52, 0x68, 0x73, 0x65, 
0x6f, 0x70, 0x73, 0x6e, 0x5d, 0x65, 0x3d, 0x20, 0x30, 0x20, 0x20, 0x0a, 0x20, 0x20, 0x20, 0x20, 
...
YSC
  • 38,212
  • 9
  • 96
  • 149
  • 1
    Above conversion code leaves some garbage lines and causes some missed data. I used the following (solution alluded to in OP): `cat resource.bin | xxd -p | sed -s 's/\(..\)/0x\1, /g'` – shellster Aug 14 '20 at 17:57