One of the catches with storing data in source code (your Manifest.h
and .cpp
) is the size limit for literal data, which is dependent on the compiler.
My suggestion is to use ld
. It allows you to store arbitrary binary data in your ELF file (so does objcopy
). If you prefer to write your own solution, have a look at libbfd
.
Let us say we have a hello.cpp
containing the usual C++ "Hello world" example. Now we have the following make file (GNUmakefile
):
hello: hello.o hello.om
$(LINK.cpp) $^ $(LOADLIBES) $(LDLIBS) -o $@
%.om: %.manifest
ld -b binary -o $@ $<
%.manifest:
echo "$@" > $@
What I'm doing here is to separate out the linking stage, because I want the manifest (after conversion to ELF object format) linked into the binary as well. Since I am using suffix rules this is one way to go, others are certainly possible, including a better naming scheme for the manifests where they also end up as .o
files and GNU make can figure out how to create those. Here I'm being explicit about the recipe. So we have .om
files, which are the manifests (arbitrary binary data), created from .manifest
files. The recipe states to convert the binary input into an ELF object. The recipe for creating the .manifest
itself simply pipes a string into the file.
Obviously the tricky part in your case isn't storing the manifest data, but rather generating it. And frankly I know too little about your build system to even attempt to suggest a recipe for the .manifest
generation.
Whatever you throw into your .manifest
file should probably be some structured text that can be interpreted by the script you mention or that can even be output by the binary itself if you implement a command line switch (and disregard .so
files and .so
files hacked into behaving like ordinary executables when run from the shell).
The above make file doesn't take into account the dependencies - or rather it doesn't help you create the dependency list in any way. You can probably coerce GNU make into helping you with that if you express your dependencies clearly for each goal (i.e. the static libraries etc). But it may not be worth it to take that route ...
Also look at:
If you want particular names for the symbols generated from the data (in your case the manifest), you need to use a slightly different route and use the method described by John Ripley here.
How to access the symbols? Easy. Declare them as external (C linkage!) data and then use them:
#include <cstdio>
extern "C" char _binary_hello_manifest_start;
extern "C" char _binary_hello_manifest_end;
int main(int argc, char** argv)
{
const ptrdiff_t len = &_binary_hello_manifest_end - &_binary_hello_manifest_start;
printf("Hello world: %*s\n", (int)len, &_binary_hello_manifest_start);
}
The symbols are the exact characters/bytes. You could also declare them as char[]
, but it would result in problems down the road. E.g. for the printf
call.
The reason I am calculating the size myself is because a.) I don't know whether the buffer is guaranteed to be zero-terminated and b.) I didn't find any documentation on interfacing with the *_size
variable.
Side-note: the *
in the format string tells printf
that it should read the length of the string from the argument and then pick the next argument as the string to print out.