Is There Any Standard Way of Embedding Resources into Linux Executable Image

Is there any standard way of embedding resources into Linux executable image?

Make yourself an assembler file, blob.S:

    .global blob
.global blob_size
.section .rodata
blob:
.incbin "blob.bin"
1:
blob_size:
.int 1b - blob

Compile with gcc -c blob.S -o blob.o
The blob can now be accessed from within your C program with:

extern uint8_t blob[];
extern int blob_size;

Using a bin2c converter usually works fine, but if the blob is large, the incbin solution is much faster, and uses much less memory (compile time)

Embed resources (eg, shader code; images) into executable/library with CMake

One of the easiest ways to do this is to include a small, portable C program in your build that reads the resource and generates a C file that contains the length of the resource data and the actual resource data as an array of constant character literals. This will be entirely platform independent, but should only be used for resources that are reasonably small. For larger resources, you probably don't want to embed the files in your program.

For resource "foo", the generated C file "foo.c" would contain:

const char foo[] = { /* bytes of resource foo */ };
const size_t foo_len = sizeof(foo);

To access the resource from C++, you declare the following two symbols in either a header or the cpp file where they're used:

extern "C" const char foo[];
extern "C" const size_t foo_len;

To generate foo.c in the build, you need a target for the C program (call it embedfile.c), and you need to use the add_custom_command command to call this program:

add_executable(embedfile embedfile.c)

add_custom_command(
OUTPUT foo.c
COMMAND embedfile foo foo.rsrc
DEPENDS foo.rsrc)

Then, include foo.c on the source list of a target that requires the "foo" resource. You now have access to the bytes of "foo".

The program embedfile.c is:

#include <stdlib.h>
#include <stdio.h>

FILE* open_or_exit(const char* fname, const char* mode)
{
FILE* f = fopen(fname, mode);
if (f == NULL) {
perror(fname);
exit(EXIT_FAILURE);
}
return f;
}

int main(int argc, char** argv)
{
if (argc < 3) {
fprintf(stderr, "USAGE: %s {sym} {rsrc}\n\n"
" Creates {sym}.c from the contents of {rsrc}\n",
argv[0]);
return EXIT_FAILURE;
}

const char* sym = argv[1];
FILE* in = open_or_exit(argv[2], "r");

char symfile[256];
snprintf(symfile, sizeof(symfile), "%s.c", sym);

FILE* out = open_or_exit(symfile,"w");
fprintf(out, "#include <stdlib.h>\n");
fprintf(out, "const char %s[] = {\n", sym);

unsigned char buf[256];
size_t nread = 0;
size_t linecount = 0;
do {
nread = fread(buf, 1, sizeof(buf), in);
size_t i;
for (i=0; i < nread; i++) {
fprintf(out, "0x%02x, ", buf[i]);
if (++linecount == 10) { fprintf(out, "\n"); linecount = 0; }
}
} while (nread > 0);
if (linecount > 0) fprintf(out, "\n");
fprintf(out, "};\n");
fprintf(out, "const size_t %s_len = sizeof(%s);\n\n",sym,sym);

fclose(in);
fclose(out);

return EXIT_SUCCESS;
}

C/C++ with GCC: Statically add resource files to executable/library

With imagemagick:

convert file.png data.h

Gives something like:

/*
data.h (PNM).
*/
static unsigned char
MagickImage[] =
{
0x50, 0x36, 0x0A, 0x23, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20,
0x77, 0x69, 0x74, 0x68, 0x20, 0x47, 0x49, 0x4D, 0x50, 0x0A, 0x32, 0x37,
0x37, 0x20, 0x31, 0x36, 0x32, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,

....

For compatibility with other code you can then use either fmemopen to get a "regular" FILE * object, or alternatively std::stringstream to make an iostream. std::stringstream is not great for this though and you can of course just use a pointer anywhere you can use an iterator.

If you're using this with automake don't forget to set BUILT_SOURCES appropriately.

The nice thing about doing it this way is:

  1. You get text out, so it can be in version control and patches sensibly
  2. It is portable and well defined on every platform

ZipArchive with embedded ZIP concated to EXE

You could use an import expressions to embedded an arbitrary file, as a string literal, in the binary at build time.

SDL embed image inside program executable

Embedding a file in an executable is easy but there are some gotchas, there are several ways to do it including some portable and non-portable ways.

Using #embed

This will reportedly be part of C23. It may be on track to appear in C++26 as well. Check whether your compiler supports this feature. In the future, this may be the most portable and straightforward way to embed binary data.

static const unsigned char IMAGE_DATA[] = {
#embed "myimage.bmp
};

See WG14 n2592 for the feature proposal.

Advantages: simplest, easiest

Disadvantages: your compiler probably doesn’t support this yet

Convert the image to C code

Write a script to convert the image to a constant array in C. The script would look something like this in Python:

#!/usr/bin/env python3
print("static const unsigned char IMAGE_DATA[] = {{{}}};".format(
",".join(str(b) for b in open("myimage.bmp", "rb").read())))

Just pipe the output to a *.h file and include that file from one other file. You can get the size of the file with sizeof(IMAGE_DATA).

Advantages: portable

Disadvantages: requires Python to be installed, does not work if array is too large for compiler, requires adding a custom step to the build system

Convert the image to an object file

This is more platform-dependent. On platforms with GNU binutils toolchains (e.g. Linux) you can use objcopy, I think bin2obj works on Microsoft toolchains.

Advantages: works everywhere

Disadvantages: non-portable, requires adding a custom step to the build system, the custom step might be tricky to get right

On GNU binutils toolchains, with objcopy

The objcopy program lets you specify binary as the input format, but then you need to specify the architecture explicitly... so you will have to modify the command for i386 and x64 versions of your executable.

$ objcopy --input binary --output elf32-i386 --binary-architecture i386 \
myimage.bmp myimage.o

You can get the data from C by using the following declarations:

// Ignore the fact that these are char...
extern char _binary_myimage_bmp_start, _binary_myimage_bmp_end;

#define MYIMAGE_DATA ((void *) &_binary_myimage_bmp_start)
#define MYIMAGE_SIZE \
((size_t) (&_binary_myimage_bmp_end - &_binary_myimage_bmp_start))

Use an assembler directive

Paradoxically, embedding a static file is fairly easy in assembler. Assemblers often have directives like .incbin (which works with GAS and YASM).

Advantages: works everywhere

Disadvantages: non-portable, assembler syntax is different between platforms

(Windows) Embed the file as a resource

On Windows, you can embed resources in an EXE and then get the resources using library calls.

Advantages: probably easiest if you are on Windows

Disadvantages: only works on Windows

How to embed a file into an executable?

A portable way is to define a function like

typedef unsigned char Byte;

Byte const* pngFileData()
{
static Byte const data =
{
// Byte data generated by a helper program.
};
return data;
}

Then all you have to do is to write a little helper program that reads the PNG file as binary and generates the C++ curly braces initializer text. Edit: @awoodland has pointed out in comment to the question, that ImageMagick has such a little helper program…

Of course, for a Windows-specific program, instead use the ordinary Windows resource scheme.

Cheers & hth.,



Related Topics



Leave a reply



Submit