I've used
objcopy or
ld, and a simple Bash script to generate both the ELF object file and the header file:
#ifndef NAME_H #define NAME_H extern type name[count]; #endif /* NAME_Hwith
count derived from the file size (file size divided by size of
type); and
NAME,
name,
type, the size of
type, and the binary file name specified by command line parameters.
Then,
sizeof name yields the size of the binary object in bytes, and
(sizeof name / sizeof name[0]) == count yields the number of elements in the array, as usual. The C/C++ compiler also detects trivial array overrun errors then, because it too knows the exact size of the array.
If you have several of them, say icons or images, I'd modify the script to read the list of binaries and their properties from a plain text file, generating one object file for all of them, with the associated header (and C source file) describing each of their properties.
Sure, one could easily write a program to do this, because ELF files are easier to manipulate than one would think, except for a few historical warts like 64-bit Alpha and S390, which use nonstandard fields, but because of
Unix philosophy, I prefer the scripted easily adapted approach myself. (If you have lots of files, use the
stat -c '%Y' filename utility to obtain the last modification time of the file in seconds since Unix epoch, and only regenerate the file if any of the sources is newer than the already existing object file.)
There is one pattern I wish everyone who writes
sh-compatible scripts (including Bash scripts): Use an autodeleted temporary directory for your temporary files,
#!/bin/sh
export LANG=C LC_ALL=C
Work="$(/usr/bin/mktemp -d)" || exit 1
trap "rm -rf '$Work'" EXIT
# Use "$Work/filename" for temporary files, preferably with descriptive file names.
You want the script to work in a well-defined locale; the default (
C) is the obvious choice. This way, even if file names contain non-ASCII characters (using any character set), your script won't be confused, and just uses the file names as-is.
The temporary directory
$Work is always removed when the script exits, even if the script fails due to an error. The way the trap is set, the path to the temporary directory is expanded when the trap is set, so even if you manage to mangle the
Work shell variable somehow (say, set it to
/), the trap is not affected at all; the original temporary directory and all its contents will be removed.
(Both
mktemp and the
stat commands I described earlier are part of GNU coreutils, and always installed in Linux. They or their equivalents are obviously available for other operating systems as well.)
Another pattern is to use nul-separated file names (
find -print0,
xargs -0, Bash
read -d "", and so on), so that your scripts are not confused or do the wrong thing if a file name happens to contain a space or a newline. But in build environments, that's usually not an issue.