Build Lazarus Resource Files Safely with lazres-3.0
You will turn one or more ordinary files into a Lazarus resource source file that contains LazarusResources.Add entries. The examples use the installed lazres-3.0 from package lcl-utils-3.0, version 3.0+dfsg1-8build3. Allow about ten minutes if the input files are ready.
The route
Jump straight to the step you need, or tick off Done means at the end.
You need a shell, readable input files, and a writable working directory. This is a build step, not a system administration task: do not use sudo unless your input or output directory is deliberately restricted. The command does not install resources into the system or alter a Lazarus project by itself.
1. Check the installed command
Confirm which executable will run and read its short help:
$ command -v lazres-3.0
/usr/bin/lazres-3.0
$ lazres-3.0 -h
Usage: lazres resourcefilename filename1[=resname1] [filename2[=resname2] ... filenameN=resname[N]]
lazres resourcefilename @filelist
The first argument is the output resource filename. The remaining arguments are input files, unless you use one argument beginning with @ to name a file containing the inputs. The installed help also documents an optional resource name after =.
Checkpoint: if command -v finds a different lazres, use that command consistently and check its help. Lazarus tools from different installations can have different versions.
2. Build a resource file from a text input
Start with a new output path so that a failed or unexpected build cannot replace a resource file already used by your project. Here, messages.txt is an existing file in the current directory:
$ lazres-3.0 build/resources.lrs messages.txt
messages.txt ResourceName='messages' Type='TXT'
The command creates a text-based .lrs file. For a file named readme.txt with the contents hello resource, the installed command produced an entry like this:
LazarusResources.Add('readme','TXT',[
'hello resource'#10
]);
By default, the resource name is derived from the input basename, without its extension. The type shown in the generated entry is derived from the input extension in this example. These names are part of the resource interface your Pascal code will use, so choose stable filenames or set names explicitly rather than relying on an accidental rename.
Verify both the output file and its contents:
$ test -s build/resources.lrs && echo 'resource file is non-empty'
resource file is non-empty
$ sed -n '1,12p' build/resources.lrs
LazarusResources.Add('messages','TXT',[
The diagnostic line printed by lazres-3.0 is normal progress output. It tells you which input, resource name, and type were selected; it is not the generated resource data.
3. Assign an explicit resource name
Use input-file=resource-name when the Pascal code needs a name that should not change with the disk filename:
$ lazres-3.0 build/ui.lrs assets/app-icon.bin=APP_ICON
assets/app-icon.bin ResourceName='APP_ICON' Type='BIN'
$ grep -F "LazarusResources.Add('APP_ICON'" build/ui.lrs
LazarusResources.Add('APP_ICON','BIN',[
The resource name is metadata inside the generated file, not a destination filename and not a request to rename the input. Keep names simple and document them where the application loads the resource. If two inputs are given the same explicit name, the installed command writes two entries with that name. Do not depend on duplicate-name lookup behaviour unless your Lazarus code has been tested for it.
4. Build from a file list
For several files, put one input specification on each line and pass the list with @. A line can contain a plain path or the same optional =resname suffix:
$ sed -n '1,10p' resources.lst
assets/logo.txt
assets/app-icon.bin=APP_ICON
$ lazres-3.0 build/application.lrs @resources.lst
assets/logo.txt ResourceName='logo' Type='TXT'
assets/app-icon.bin ResourceName='APP_ICON' Type='BIN'
$ grep -c 'LazarusResources.Add' build/application.lrs
2
Use paths that are correct from the directory where you run lazres-3.0. A list is useful for repeatable builds, but it is another input that can become stale. Before rebuilding, inspect it and check that every referenced file exists:
$ while IFS= read -r path; do
case "$path" in
*=*) path=${path%%=*} ;;
esac
test -r "$path" || printf 'unreadable or missing: %s\n' "$path" >&2
done < resources.lst
This small check is deliberately separate from the build. It treats the part before the first = as the path, which matches the simple list used above. If your filenames themselves contain this separator, use a different naming scheme or validate those paths manually.
5. Catch the missing-input trap
Do not rely only on the exit status when checking a build. On this installed version, a missing input caused an ERROR: file not found line on standard output, returned status 0, and did not create the requested output file. That is an awkward interface for automation, so check the output explicitly and capture the command's output when a build matters:
$ output=build/application.lrs
$ log=$(mktemp)
$ lazres-3.0 "$output" @resources.lst >"$log"
$ status=$?
$ if [ "$status" -ne 0 ] || [ ! -s "$output" ] || grep -q '^ERROR:' "$log"; then
printf 'lazres failed; inspect %s\n' "$log" >&2
exit 1
fi
$ cat "$log"
assets/logo.txt ResourceName='logo' Type='TXT'
assets/app-icon.bin ResourceName='APP_ICON' Type='BIN'
This wrapper does not make the output atomic, so use a temporary output name when replacing a known-good file. The shell variable log points to a temporary diagnostic file; remove it after review with rm -- "$log" if it contains nothing you need. Removing that log is optional and irreversible, while the generated resource can always be rebuilt from the inputs.
6. Replace an existing resource only after checking it
Redirection is not involved here, but lazres-3.0 writes the named output file. Treat replacement as a build artefact change: keep the current file until the new one has been inspected and your normal Lazarus build accepts it.
$ cp --preserve=all build/application.lrs build/application.lrs.bak
$ lazres-3.0 build/application.lrs.new @resources.lst
$ test -s build/application.lrs.new
$ grep -F "LazarusResources.Add('APP_ICON'" build/application.lrs.new
LazarusResources.Add('APP_ICON','BIN',[
$ mv build/application.lrs.new build/application.lrs
If the new build is wrong, restore the previous file with mv build/application.lrs.bak build/application.lrs. Do not remove the backup until the application has compiled and loaded the resources successfully. No elevated privilege is needed for these operations in a normal project directory.
Done means
- The intended
lazres-3.0executable and package version were checked. - Every input path was readable, and the output contains the expected number of resource entries.
- Resource names are explicit where Pascal code depends on them.
- The output is non-empty and was inspected before replacing any known-good file.
- Automation checks the diagnostic output and output file, not just the exit status.