Convert a .res File to a Linux Object with fpcres

Your Pascal build needs a resource file linked in, and the linker wants an object, not a .res. The fpcres tool turns an existing Free Pascal resource file into a relocatable Linux object, and this guide checks the output matches the target you need while the source stays untouched. The examples use fpcres from Debian package fp-compiler-3.2.2:amd64, FPC version 3.2.2. Allow about ten minutes if you already have a .res file.

This is a conversion step, not a resource design guide. You need a shell, read access to the input file and write access to the output directory. Nothing below needs elevated privileges in a directory you own.

Warning: do not use sudo to paper over an output path you have not checked.

1. Check the installed command

Start with the binary that will actually run. The installed manpage is only a stub: it says a .res file becomes an .o file and leaves the options section unfinished. The program's own help is the useful local reference for this package.

$ command -v fpcres
/usr/bin/fpcres
$ fpcres --version
fpcres - resource file converter, version 2.0 [2024/01/05], FPC 3.2.2
Host platform: Linux - x86_64

Checkpoint: if the version is not the one you meant to document or reproduce, stop here. A different FPC release can add formats, targets or parser behaviour. On this machine fpcres and x86_64-linux-gnu-fpcres-3.2.2 are aliases for the same resource compiler.

2. Inspect the input and pick an output path

fpcres takes one or more input files followed by an optional -o output name. The normal input is a compiled resource file, not a Pascal source file and not any file that merely ends in .res. Check it before converting:

$ file /path/to/resources.res
/path/to/resources.res: ...

The file description depends on the resource format, and the command rejects an unrecognised file. Keep the output apart from the input, especially when testing a new build. Overwriting an existing object can destroy a previously working build artefact, so use a new name first.

For a repeatable example, this guide uses an installed resource file and a temporary output. Swap in your own paths:

$ input='/usr/lib/x86_64-linux-gnu/fpc/3.2.2/units/x86_64-win64/fcl-base/fclel.res'
$ output='/tmp/fclel-linux.o'
$ test -r "$input"
$ test ! -e "$output"

Warning: the final test deliberately refuses to replace an existing file. If it fails, inspect the path, then either choose another output name or remove the old file once you are sure it is disposable. Removing a build artefact is destructive, even though rebuilding usually recovers it.

3. Convert to the default Linux target

On this x86_64 Linux installation the default output target is x86_64 - elf. Pass the input and output explicitly:

$ fpcres --output "$output" "$input"
$ file "$output"
/tmp/fclel-linux.o: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), not stripped

An exit status of zero and an ELF relocatable result are the checks that matter. The object is not an executable. It is input for a later link, normally inside a Free Pascal build. The original .res file is not altered.

Record the output path, then run these before handing the object to a build:

$ printf 'converter status: %s\n' "$?"
converter status: 0
$ readelf -h "$output" | grep -E 'Class:|Machine:|Type:'
  Class:                             ELF64
  Type:                              REL (Relocatable file)
  Machine:                          Advanced Micro Devices X86-64

Checkpoint: the readelf lines verify the generated file. They do not promise that every linker or ABI combination will accept it. If your compiler targets another architecture, convert for that target instead of relying on this default.

4. Pick another object format or architecture

The installed help lists five output formats: res, elf, coff, mach-o and external. Select one with -of. Select the architecture with --arch or -a, though valid names depend on the format. For example, x86_64 is listed for ELF, COFF and Mach-O. A real ELF selection looks like this:

$ fpcres -of elf -a x86_64 -o '/tmp/resources-x86_64.o' '/path/to/resources.res'

Tip: use --arch only once you know the consumer's target. An object for the wrong architecture can survive conversion and fail later at link time, which is a poor place to find the mistake. The --subarch option mostly matters for ARM variants; the help lists values such as v4t, v6 and v7.

5. Add diagnostics when conversion fails

Use --verbose for a trace of option parsing, resource recognition, the selected writer and the output file:

$ fpcres --verbose -o '/tmp/resources-x86_64.o' '/path/to/resources.res'
Debug: Chosen reader: .res resource reader
Debug: Reading resource information...
Debug: Writing output file /tmp/resources-x86_64.o...

Names, resource counts and elapsed time vary. Ask where the operation stopped:

The help also lists -I, -D and -U for RC-file include paths and symbols, plus @<file> for extra options. The local manpage does not document these, so treat them as version-specific and check fpcres --help on the machine that will run the build. In particular, do not assume an RC source file behaves like a compiled .res input without testing that exact release and format.

6. Clean up the temporary output

Once the object has been copied into the build workflow and verified, remove only the temporary path you created:

$ rm -- '/tmp/fclel-linux.o'
$ test ! -e '/tmp/fclel-linux.o'
removed: temporary object is absent

Destructive action: this is the only destructive command in the guide. Do not swap the quoted temporary path for a project directory, a wildcard or an unreviewed variable. If the object is part of a real build, keep it and let the build system own its cleanup.

Done means