Build a GResource Bundle with glib-compile-resources
glib-compile-resources turns an XML manifest and a folder of files into a single binary bundle your application loads at runtime. This walks through compiling a small GResource manifest into a .gresource file, generating the equivalent C source when a build needs that instead, and reading the files that control rebuilds. The examples use glib-compile-resources 2.86.4 from Ubuntu package libglib2.0-dev-bin 2.80.0-6ubuntu3.9.
The route
Jump straight to the step you need, or tick off Done means at the end.
Allow about fifteen minutes. You need a shell, the command itself, and a directory holding an XML resource description plus the files it names. The normal workflow is unprivileged: do not reach for sudo unless your chosen input or output directory is deliberately restricted, and even then fix its ownership or permissions instead, if that is your system to administer.
1. Check the installed command
Confirm which executable is on your path and record its version. This changes nothing:
$ command -v glib-compile-resources
/usr/bin/glib-compile-resources
$ glib-compile-resources --version
2.86.4
$ dpkg-query -W -f='${Package} ${Version}\n' libglib2.0-dev-bin
libglib2.0-dev-bin 2.80.0-6ubuntu3.9
Checkpoint
If the command is missing, stop here and install the development-bin package through your normal package-management process. The rest of this guide assumes the version and package lookup both succeed.
2. Create a resource description
A resource description is XML. Its <file> entries name files that will be placed in the bundle, while prefix controls the resource path the application will use. Put this manifest and its input file in one working directory:
<?xml version="1.0" encoding="UTF-8"?>
<gresources>
<gresource prefix="/example">
<file>message.txt</file>
</gresource>
</gresources>
Save it as resources.gresource.xml, and create a sibling file called message.txt. The file name resolves against the current directory unless you supply --sourcedir, which is the first common trap here: the XML file's own location does not make every relative input path valid.
Checkpoint
Make sure the exact input exists before you compile anything:
$ test -r message.txt && echo 'message.txt is readable'
message.txt is readable
$ test -r resources.gresource.xml && echo 'manifest is readable'
manifest is readable
3. Compile a binary bundle
Use --target to choose the output explicitly. With --generate, the target's extension picks the output format, and a .gresource target is a binary resource bundle:
$ glib-compile-resources \
--generate \
--target=resources.gresource \
resources.gresource.xml
$ file resources.gresource
resources.gresource: GVariant Database file, version 0
The command writes no progress message on success. A zero exit status and a non-empty target are the checks that matter. No shell redirection is involved here, but the target is still a state-changing write: pick a new name, or make a backup, before replacing a bundle that another build or application still uses.
If the input files live somewhere else, make that explicit:
$ glib-compile-resources \
--generate \
--sourcedir=/path/to/resource-files \
--target=/path/to/build/resources.gresource \
/path/to/resource-files/resources.gresource.xml
Both the manifest and every referenced file must be readable. The command creates no missing source directories and invents no missing files. If compilation fails, keep the previous target and fix the path or XML before trying again.
4. Generate C source for linking
Some applications compile the resource data straight into their executable or library instead of installing a separate bundle. Select a .c target with --generate:
$ glib-compile-resources \
--generate \
--target=resources.c \
--c-name=app_resources \
resources.gresource.xml
$ sed -n '1,8p' resources.c
#include <gio/gio.h>
#if defined (__ELF__) && ( __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 6))
# define SECTION ...
The generated file carries the resource bytes and registration code. Treat it as a build artefact, not something to hand-edit. --c-name supplies the prefix for the generated C identifiers, so pick a stable name that will not collide with another resource compiled into the same program.
--generate-sourceis the explicit equivalent when you want C source regardless of the target's extension.--generate-headeradds the header your C build needs alongside that generated source.--manual-registergenerates functions your application code must call during initialisation and uninitialisation, for the uncommon compilers without constructor support. Do not add it unless your compiler or integration actually requires it.
5. Track dependencies in the build
Ask the compiler for the files named by the manifest before wiring them into a build rule:
$ glib-compile-resources \
--generate-dependencies \
--sourcedir=. \
resources.gresource.xml
message.txt
That output is meant for build systems. For a dependency file in the style of gcc -M -MF, combine normal generation with --dependency-file:
$ glib-compile-resources \
--generate \
--target=resources.gresource \
--dependency-file=resources.d \
resources.gresource.xml
$ sed -n '1,4p' resources.d
resources.gresource: resources.gresource.xml message.txt
Exact quoting and line wrapping in a dependency file can vary, so inspect it rather than matching one line byte for byte. --generate-phony-targets adds phony targets when you use --dependency-file and need make-style missing-file handling.
6. Diagnose failures without changing the system
A missing referenced file normally produces an error naming that file and a non-zero exit status. Check the path from the same directory and source directory the build actually uses:
$ glib-compile-resources --generate \
--sourcedir=. \
--target=/tmp/check.gresource \
resources.gresource.xml
$ printf 'exit status: %s\n' "$?"
exit status: 0
Use a temporary target for a diagnostic build when you do not want to overwrite the real artefact. If the XML names message.txt but it lives elsewhere, either fix the manifest or point --sourcedir at the right place. Do not solve a path error by running the build as root.
Preprocessing options in the XML can call external tools. The command looks for xmllint through PATH, or uses the full path in XMLLINT; the same lookup rules apply to gdk-pixbuf-pixdata and json-glib-format for their respective preprocessing options. Keep those tools in the build environment, and record the chosen paths when reproducibility matters.
Done means
- Confirmed the installed command and package version.
- Verified the XML manifest and every referenced file are readable from the selected source directory.
- Built a binary
.gresourcetarget and checked it without overwriting an unverified artefact. - Used a deliberate identifier prefix for the C output mode, treating it as generated code.
- Generated dependency output for the build system, and can chase a missing-file error without elevated privileges.