Difference between revisions of "Lazarus Resources"

From Lazarus wiki
Jump to navigationJump to search
(→‎See also: Added related entries)
(47 intermediate revisions by 16 users not shown)
Line 1: Line 1:
 
{{Lazarus Resources}}
 
{{Lazarus Resources}}
  
Every win32 developer should know about resource files. They contain data which should be compiled into the exe file. That data could consist of images, string tables, version info, ... even an XP manifest and forms.
+
==Introduction==
  
Before FPC 2.4 it was not possible to use "normal" resource files (*.res) in Lazarus because they were win32 specific. In order to use your, you had to recreate them with lazres. Lazres can be found in the "Tools" directory (C:\Lazarus\Tools\ - You have to compile the lazres.lpi first)of your Lazarus installation folder (maybe you will first have to compile it).
+
Resource files contain data which should be compiled into the executable file. That data could consist of images, string tables, version info, ... even a Windows XP manifest and forms. This includes data that the programmer can retrieve in his code (accessing them as files). Using resources can be handy if you want to distribute self-contained executables.
 +
 
 +
Before FPC 2.4 it was not possible to use standard Delphi-compatible [[#FPC_resources|resource files]] (*.res) in Lazarus because they were Win32 specific. Please see [[#Lazarus_resources|Lazarus resources]] (*.lrs) below.
 +
 
 +
Standard Delphi-compatible resources are now recommended for current FPC '''(including all recent Lazarus versions)'''. Please see [[#FPC_resources|FPC resources]] below.
 +
 
 +
Alternatively, you can include resources in your application from within the Lazarus IDE by using the [[IDE_Window:_Project_Options#Resources|IDE Resources Dialog]].
 +
 
 +
== FPC resources ==
 +
 
 +
Starting from FPC 2.4 you can use standard .rc (resource script) and .res (compiled resource) files in your project to include resources. To turn a .rc script used in the sources into a binary resource (.res file), FPC runs the appropriate external resource compiler (windres or GoRC). Therefore that resource compiler needs to be installed and present in the PATH environment variable.
 +
For more details, see: [http://www.freepascal.org/docs-html/prog/progch13.html FPC Programmer's guide, chapter 13 "Using Windows resources"]
 +
 
 +
To simplify the compiling process, it is possible to use only the compiled resources in the .res files. You can precompile the resources by any available resource compiler - windres (available both on unixes and windows), GoRC (windows only), Microsoft resource compiler (rc.exe included in Visual Studio), Borland resource compiler (brcc32.exe included in Delphi, C++ Builder or Rad Studio products) or any other.
 +
 
 +
Use
 +
* {$R filename.rc} to compile a resource script and include the resulting resource file or
 +
* {$R filename.res} directive to include a compiled resource file
 +
into the executable.
 +
 
 +
FPC RTL provides both low-level functions as well as high-level classes to access resources.
 +
 
 +
The low-level functions are:
 +
* EnumResourceTypes
 +
* EnumResourceNames
 +
* EnumResourceLanguages
 +
* FindResource
 +
* FindResourceEx
 +
* LoadResource
 +
* SizeofResource
 +
* LockResource
 +
* UnlockResource
 +
* FreeResource
 +
 
 +
They are compatible with the Windows API functions: [http://msdn.microsoft.com/en-us/library/ff468902(VS.85).aspx]
 +
 
 +
The main class used to work with resources is TResourceStream. LCL uses it to load embedded bitmaps, icons and form streams. Look at TGraphic.LoadFromResourceID or TIcon.LoadFromResourceHandle to see how it is used inside LCL.
 +
 
 +
=== Adding resources to your program ===
 +
 
 +
Let's review the situation when you need to store some data inside your executable and during the program run you want to extract this data from it.
 +
 
 +
First we need to tell the compiler what files to include in the resource. We do this in a .rc (resource script) file:
 +
mydata.rc file:
 +
 
 +
<syntaxhighlight lang="pascal">
 +
MYDATA        RCDATA "mydata.dat"
 +
</syntaxhighlight>
 +
 
 +
Here MYDATA is the resource name, RCDATA is the type of resource (look here http://msdn.microsoft.com/en-us/library/ms648009(VS.85).aspx for explanation of possible types) and "mydata.dat" is your data file.
 +
 
 +
Let's instruct the compiler to include the resource into your project:
 +
 
 +
<syntaxhighlight lang="pascal">
 +
program mydata;
 +
 
 +
{$R mydata.rc}
 +
begin
 +
end.
 +
</syntaxhighlight>
 +
 
 +
Behind the scenes, the FPC compiler actually instructs the resource compiler distributed with FPC to follow the .rc script to compile your data files into a binary .res resource file. The linker will then include this into the executable. Though this is transparent to the programmer, you can, if you want to, create your own .res file with e.g. the Borland resource compiler. Instead of using <syntaxhighlight lang="pascal" inline>{$R mydata.rc}</syntaxhighlight> you'd use <syntaxhighlight lang="pascal" inline>{$R mydata.res}</syntaxhighlight>.
 +
 
 +
=== Checking you have windres ===
 +
 
 +
On Linux/FreeBSD/macOS, you might need to make sure you have the ''windres'' resource compiler, which is part of the GNU binutils project.
 +
 
 +
==== Linux ====
 +
 
 +
On Debian systems you could run (FIXME : this work for a 64B version, for 32B systems you will must probably change w64 to w32) :
 +
<syntaxhighlight lang="bash">
 +
sudo apt install mingw-w64 mingw-w64-tools
 +
</syntaxhighlight>
 +
or, if you do not need full mingw :
 +
<syntaxhighlight lang="bash">
 +
sudo apt install binutils-mingw-w64-x86-64
 +
</syntaxhighlight>
 +
Next 2 windres compilers will be installed (in /usr/bin) x86_64-w64-mingw32-windres and i386-w64-mingw32-windres.
 +
But FPC search "windres" (worst the path can be "Select manually"). You must edit /etc/fpc.cfg and add lines at the end (delete the old "-FC")
 +
<syntaxhighlight lang="c">
 +
# MS Windows .rc resource compiler
 +
#IFDEF CPUAMD64
 +
-FCx86_64-w64-mingw32-windres
 +
#ENDIF
 +
#IFDEF cpui386
 +
-FCi386-w64-mingw32-windres
 +
#ENDIF
 +
</syntaxhighlight>
 +
 
 +
==== FreeBSD ====
 +
 
 +
Even if you install the ''binutils'' package via the ports collection, the ''windres'' binary is not installed - it is probably considered too Windows centric. So you have to manually add ''windres'' yourself.
 +
 
 +
When you build the ''binutils'' package via ports, the ''windres'' binary is actually built, but it is not installed by default. So, after building and installing the package:
 +
 
 +
1. From the /usr/ports/devel/binutils directory, cd work/binutils-2.xx/binutils
 +
 
 +
2. Copy the ''windres'' binary into your /usr/local/bin/ directory, or into your $HOME/bin/ directory.
 +
 
 +
'''Note:''' The ''windres'' utility is hardcoded to use ''gcc'' but [https://www.freebsd.org/releases/10.0R/relnotes.html#userland FreeBSD 10.0] (January 2014) replaced ''gcc'' with ''clang'', so you will also need to install ''gcc'' from ports to be able to use ''windres'' if you are using a version of FreeBSD that is not end-of-life.
 +
 
 +
==== macOS ====
 +
 
 +
===== Using binutils source =====
 +
 
 +
As of June 2020, the latest version is binutils-2.34 but it may change. Substitute the latest version in any command below.
 +
 
 +
* Download the latest binutils source from https://mirror.freedif.org/GNU/binutils/
 +
* Uncompress the binutils-2.34.tar.xz archive (I used ''The Unarchiver'' free utility from the Mac App Store)
 +
* Open an Applications > Utilities > Terminal and type the following commands:
 +
 
 +
cd binutils-2.34
 +
./configure
 +
make
 +
cd binutils
 +
make windres
 +
sudo cp windres /usr/local/bin/
 +
cd doc
 +
gzip windres.1
 +
sudo cp windres.1.gz /usr/local/share/man/man1/
 +
 
 +
If you execute <tt>windres</tt> you will get a disappointing error message:
 +
 
 +
windres: Can't detect architecture.
 +
 
 +
To fix this you should be able to pass the <tt>--target=mach-o-x86-64</tt> argument to <tt>windres</tt> on the command line, but this still gives the same error message. My ultimate fix was to change the <tt>windres.c</tt> file as follows:
 +
 
 +
$ diff  ~/tmp/windres.c windres.c
 +
1100c1100,1101
 +
<  def_target_arch = NULL;
 +
---
 +
>  //def_target_arch = NULL;
 +
>  def_target_arch = "mach-o-x86-64";
 +
 
 +
The above diff indicates I changed line 1100 in the <tt>windres.c</tt> file by commenting it out, then added a new line which assigns the correct architecture to the ''def_target_arch'' variable. You then need to again:
 +
 
 +
make windres
 +
sudo cp windres /usr/local/bin/
 +
 
 +
For detailed help you can consult the man page by opening an Applications > Utilities > Terminal and typing the following command:
 +
 
 +
man windres
 +
 
 +
Alternatively, you can display a usage summary by opening an Applications > Utilities > Terminal and typing the following command:
 +
 
 +
windres --help
 +
 
 +
==== Windows ====
 +
 
 +
On Windows, windres and the gorc resource compiler should be provided by the FPC and Lazarus installers.
 +
 
 +
=== Using resources in your program ===
 +
Now let's extract the stored resource into a file, e.g. mydata.dat:
 +
 
 +
<syntaxhighlight lang="pascal">
 +
program mydata;
 +
uses
 +
  SysUtils, Classes, Windows {needed for RT_RCDATA, could be omitted};
 +
{$R mydata.res}
 +
var
 +
  S: TResourceStream;
 +
  F: TFileStream;
 +
begin
 +
  // create a resource stream which points to our resource
 +
  S := TResourceStream.Create(HInstance, 'MYDATA', RT_RCDATA);
 +
  // Replace RT_RCDATA with ??? with what?
 +
  // Please ensure you write the enclosing apostrophes around MYDATA,
 +
  // otherwise no data will be extracted.
 +
  try
 +
    // create a file mydata.dat in the application directory
 +
    F := TFileStream.Create(ExtractFilePath(ParamStr(0)) + 'mydata.dat', fmCreate);
 +
    try
 +
      F.CopyFrom(S, S.Size); // copy data from the resource stream to file stream
 +
    finally
 +
      F.Free; // destroy the file stream
 +
    end;
 +
  finally
 +
    S.Free; // destroy the resource stream
 +
  end;
 +
end.</syntaxhighlight>
 +
 
 +
Many classes (at least in Lazarus trunk/development version) also support loading directly from FPC resources, e.g.
 +
 
 +
<syntaxhighlight lang="pascal">
 +
procedure exampleproc;
 +
var
 +
  Image: TImage
 +
begin
 +
  Image := TImage.Create;
 +
  Image.Picture.LoadFromResourceName(HInstance,'image'); // note that there is no need for the extension
 +
end;
 +
</syntaxhighlight>
 +
 
 +
 
 +
==Lazarus resources==
 +
 
 +
{{Warning|As mentioned above, using "normal"/Windows resources. Lazarus has also switched to this format since ver. 1.4; see [[Lazarus_1.4.0_release_notes]] }}
 +
 
 +
In order to use your files as Lazarus resources, they must be included as a resource file.
 +
 
 +
You can create LRS files with [https://sourceforge.net/projects/lrsexplorer/ LRS explorer] or using ''lazres'' with the command line.
 +
 
 +
Lazres can be found in the "Tools" directory (C:\Lazarus\Tools\ - you may need to compile it from lazres.lpi project) of your Lazarus installation folder.
 +
 
 +
Then you can compile Lazarus resource files (*.lrs) via the command line. The syntax for lazres is:
 +
 
 +
<pre><nowiki>lazres <filename of resource file> <files to include (file1 file2 file3 ...)></nowiki></pre>
  
Then you can compile Lazarus resource files (*.lrs) via command line. The syntax for lazres is:
 
:<pre><nowiki>lazres <filename of resource file> <files to include (file1 file2 file3 ...)></nowiki></pre>
 
 
Example:
 
Example:
:<pre><nowiki>lazres mylazarusresource.lrs image.jpg</nowiki></pre>
+
<syntaxhighlight lang="dos">lazres mylazarusresource.lrs image.jpg</syntaxhighlight>
 +
 
 +
Alternatively you can compile and execute glazres (C:\Lazarus\Tools\glazres) for a GUI version of lazres.
  
To use a lazarus resource file in your projects include the file with the $I compiler directive in the '''initialization''' section of your unit.
+
To use a Lazarus resource file in your project, include the file with the $I compiler directive in the '''initialization''' section of your unit.
  
You can access the data in the resources directly or with the LoadFromLazarusResource method of the variables which will hold the file contents afterwards. LoadFromLazarusResource requires one string parameter which indicades which object should be loaded from the resource file.
+
You can access the data in the resources directly or with the LoadFromLazarusResource method of the variables which will hold the file contents afterwards. LoadFromLazarusResource requires a string parameter that indicates which object should be loaded from the resource file.
  
 
Example:
 
Example:
<pre>procedure exampleproc;
+
 
 +
<syntaxhighlight lang="pascal">
 +
uses ...LResources...;
 +
 
 +
...
 +
procedure exampleproc;
 
var
 
var
 
   Image: TImage
 
   Image: TImage
Line 25: Line 236:
 
initialization
 
initialization
 
   {$I mylazarusresource.lrs}
 
   {$I mylazarusresource.lrs}
</pre>
+
</syntaxhighlight>
 +
 
 
This code includes the file mylazarusresource.lrs into the project. In the procedure exampleproc an icon object is created and loaded from the object "image" out of the resource. The file which was compiled into the resource was probably named image.jpg.
 
This code includes the file mylazarusresource.lrs into the project. In the procedure exampleproc an icon object is created and loaded from the object "image" out of the resource. The file which was compiled into the resource was probably named image.jpg.
  
Every class that is derived from TGraphic contains the LoadFromLazarusResource procedure.
+
Every class that is derived from [[TGraphic]] contains the [[LoadFromLazarusResource]] procedure.
 +
 
 +
=== Lazarus Resource Form File ===
  
== Lazarus Resource Form File ==
+
Lazarus generates .LRS files from .LFM form files.  
Lazarus generate .LRS file from .LFM Form files.  
 
  
 
When a LRS form file is missing, FPC reports the following error:
 
When a LRS form file is missing, FPC reports the following error:
ERROR: unit1.pas(193,4) Fatal: Can't open include file "unit1.lrs"
+
<code>ERROR: unit1.pas(193,4) Fatal: Can't open include file "unit1.lrs"</code>
 
 
To solve it you must use lazres: c:\lazarus\tools\lazres.exe unit1.lrs unit1.lfm
 
  
The easiest way to recreate a .lrs file to make a trivial change in the form design, revert it and save the form, no need to use lazres. [[User:Vincent|Vincent]] 09:47, 6 January 2009 (CET)
+
To solve it you can either:
 +
* use lazres: c:\lazarus\tools\lazres.exe unit1.lrs unit1.lfm
 +
* (easier): make a trivial change in the form design, revert it and save the form; this will recreate the .lrs file without needing to run lazres.
  
==Getting the raw data of a lrs resource==
+
===Getting the raw data of an lrs resource===
  
 
You can retrieve the data of the resource with:
 
You can retrieve the data of the resource with:
  
<Delphi>
+
<syntaxhighlight lang="pascal">
 
uses ...LResources...;
 
uses ...LResources...;
  
Line 58: Line 271:
 
   ...do something with the data...
 
   ...do something with the data...
 
end;
 
end;
</Delphi>
+
</syntaxhighlight>
 
 
== FPC resources ==
 
 
 
Starting from FPC 2.4 you can use regular .rc and .res files in your project to include resources. FPC runs the appropriate external resource compiler (windres or GoRC) when .rc file is used in the sources and therefore it is required to have that resource compiler to be installed and present in the PATH environment variable. To simplify the compiling process better to use only the compiled resources in the .res files. You can precompile the resources by any available resource compiler - windres (available both on unixes and windows), GoRC (windows only), Microsoft resource compiler (rc.exe included into Visual Studio), Borland resource compiler (brcc32.exe included into Delphi, C++ Builder or Rad Studio products) or any other.
 
 
 
Use {$R filename.rc} or {$R filename.res} directive to include a resource file into the executable. FPC RTL provides both low-level functions as well as high-level classes to access resources.
 
  
The low-level functions are: EnumResourceTypes, EnumResourceNames, EnumResourceLanguages, FindResource, FindResourceEx, LoadResource, SizeofResource, LockResource, UnlockResource, FreeResource. They are compatible to the windows api functions: http://msdn.microsoft.com/en-us/library/ff468902(VS.85).aspx
+
== See also ==
  
The main class to work with resources is TResourceStream. LCL uses it to load embedded bitmaps, icons and form streams. Look at TGraphic.LoadFromResourceID or TIcon.LoadFromResourceHandle to see how it is used inside LCL.
+
* [[fcl-res|FCL resource units]]
 +
* [[lazres|Lazarus Resource compiler]]
 +
* [[IDE_Window:_Project_Options#Resources|IDE Project Options > Resources]]
  
Let's review the situation when you need to store some data inside your executable and during the program run you want to extract this data from it.
+
== External links ==
  
We need to create the .res file. We can first prepare a .rc and then compile it.
+
* [https://www.freepascal.org/docs-html/prog/progch13.html Free Pascal Programmer's Guide, Chapter 13 "Using Windows resources"].
mydata.rc file:
 
:<pre><nowiki>MYDATA        RCDATA "mydata.dat"</nowiki></pre>
 
Where MYDATA is the resource name, RCDATA is the type of resource (look here http://msdn.microsoft.com/en-us/library/ms648009(VS.85).aspx for types exaplanation) and "mydata.dat" is a your data file. Let's compile it using the borland resource compiler:
 
:<pre><nowiki>brcc32 mydata.rc</nowiki></pre>
 
 
 
Res file is ready. Let's include it into your project:
 
<delphi>
 
project mydata;
 
 
 
{$R mydata.res}
 
begin
 
end.
 
</delphi>
 
 
 
Now let's extract the stored resource into the mydata.dat file:
 
<delphi>
 
project mydata;
 
uses
 
  SysUtils;
 
{$R mydata.res}
 
var
 
  S: TResourceStream;
 
  F: TFileStream;
 
begin
 
  S := TResourceStream.Create(HInstance, 'MYDATA', RT_RCDATA); // create a resource stream which points to our resource
 
  try
 
    F := TFileStream.Create(ExtractFilePath(ParamStr(0)) + 'mydata.dat', fmCreate); // create a file mydata.dat in the application directory
 
    try
 
      F.CopyFrom(S, S.Size); // copy data from the resource stream to file stream
 
    finally
 
      F.Free; // destroy the file stream
 
    end;
 
  finally
 
    S.Free; // destroy the resource stream
 
  end;
 
end.
 
</delphi>
 
  
== Authors and Contributors ==
+
[[Category:Tutorials]]
[[User:JayK|JayK]] 21:35, 4 Nov 2005 (CET)
+
[[Category:Lazarus]]
[[User:Paul Ishenin|Paul Ishenin]]
+
[[Category:FPC]]

Revision as of 03:59, 13 August 2020

Deutsch (de) English (en) español (es) français (fr) 한국어 (ko) русский (ru)

Introduction

Resource files contain data which should be compiled into the executable file. That data could consist of images, string tables, version info, ... even a Windows XP manifest and forms. This includes data that the programmer can retrieve in his code (accessing them as files). Using resources can be handy if you want to distribute self-contained executables.

Before FPC 2.4 it was not possible to use standard Delphi-compatible resource files (*.res) in Lazarus because they were Win32 specific. Please see Lazarus resources (*.lrs) below.

Standard Delphi-compatible resources are now recommended for current FPC (including all recent Lazarus versions). Please see FPC resources below.

Alternatively, you can include resources in your application from within the Lazarus IDE by using the IDE Resources Dialog.

FPC resources

Starting from FPC 2.4 you can use standard .rc (resource script) and .res (compiled resource) files in your project to include resources. To turn a .rc script used in the sources into a binary resource (.res file), FPC runs the appropriate external resource compiler (windres or GoRC). Therefore that resource compiler needs to be installed and present in the PATH environment variable. For more details, see: FPC Programmer's guide, chapter 13 "Using Windows resources"

To simplify the compiling process, it is possible to use only the compiled resources in the .res files. You can precompile the resources by any available resource compiler - windres (available both on unixes and windows), GoRC (windows only), Microsoft resource compiler (rc.exe included in Visual Studio), Borland resource compiler (brcc32.exe included in Delphi, C++ Builder or Rad Studio products) or any other.

Use

  • {$R filename.rc} to compile a resource script and include the resulting resource file or
  • {$R filename.res} directive to include a compiled resource file

into the executable.

FPC RTL provides both low-level functions as well as high-level classes to access resources.

The low-level functions are:

  • EnumResourceTypes
  • EnumResourceNames
  • EnumResourceLanguages
  • FindResource
  • FindResourceEx
  • LoadResource
  • SizeofResource
  • LockResource
  • UnlockResource
  • FreeResource

They are compatible with the Windows API functions: [1]

The main class used to work with resources is TResourceStream. LCL uses it to load embedded bitmaps, icons and form streams. Look at TGraphic.LoadFromResourceID or TIcon.LoadFromResourceHandle to see how it is used inside LCL.

Adding resources to your program

Let's review the situation when you need to store some data inside your executable and during the program run you want to extract this data from it.

First we need to tell the compiler what files to include in the resource. We do this in a .rc (resource script) file: mydata.rc file:

MYDATA         RCDATA "mydata.dat"

Here MYDATA is the resource name, RCDATA is the type of resource (look here http://msdn.microsoft.com/en-us/library/ms648009(VS.85).aspx for explanation of possible types) and "mydata.dat" is your data file.

Let's instruct the compiler to include the resource into your project:

program mydata;

{$R mydata.rc}
begin
end.

Behind the scenes, the FPC compiler actually instructs the resource compiler distributed with FPC to follow the .rc script to compile your data files into a binary .res resource file. The linker will then include this into the executable. Though this is transparent to the programmer, you can, if you want to, create your own .res file with e.g. the Borland resource compiler. Instead of using {$R mydata.rc} you'd use {$R mydata.res}.

Checking you have windres

On Linux/FreeBSD/macOS, you might need to make sure you have the windres resource compiler, which is part of the GNU binutils project.

Linux

On Debian systems you could run (FIXME : this work for a 64B version, for 32B systems you will must probably change w64 to w32) :

sudo apt install mingw-w64 mingw-w64-tools

or, if you do not need full mingw :

sudo apt install binutils-mingw-w64-x86-64

Next 2 windres compilers will be installed (in /usr/bin) x86_64-w64-mingw32-windres and i386-w64-mingw32-windres. But FPC search "windres" (worst the path can be "Select manually"). You must edit /etc/fpc.cfg and add lines at the end (delete the old "-FC")

# MS Windows .rc resource compiler
#IFDEF CPUAMD64
-FCx86_64-w64-mingw32-windres
#ENDIF
#IFDEF cpui386
-FCi386-w64-mingw32-windres
#ENDIF

FreeBSD

Even if you install the binutils package via the ports collection, the windres binary is not installed - it is probably considered too Windows centric. So you have to manually add windres yourself.

When you build the binutils package via ports, the windres binary is actually built, but it is not installed by default. So, after building and installing the package:

1. From the /usr/ports/devel/binutils directory, cd work/binutils-2.xx/binutils

2. Copy the windres binary into your /usr/local/bin/ directory, or into your $HOME/bin/ directory.

Note: The windres utility is hardcoded to use gcc but FreeBSD 10.0 (January 2014) replaced gcc with clang, so you will also need to install gcc from ports to be able to use windres if you are using a version of FreeBSD that is not end-of-life.

macOS

Using binutils source

As of June 2020, the latest version is binutils-2.34 but it may change. Substitute the latest version in any command below.

  • Download the latest binutils source from https://mirror.freedif.org/GNU/binutils/
  • Uncompress the binutils-2.34.tar.xz archive (I used The Unarchiver free utility from the Mac App Store)
  • Open an Applications > Utilities > Terminal and type the following commands:
cd binutils-2.34
./configure
make
cd binutils
make windres
sudo cp windres /usr/local/bin/
cd doc
gzip windres.1
sudo cp windres.1.gz /usr/local/share/man/man1/

If you execute windres you will get a disappointing error message:

windres: Can't detect architecture.

To fix this you should be able to pass the --target=mach-o-x86-64 argument to windres on the command line, but this still gives the same error message. My ultimate fix was to change the windres.c file as follows:

$ diff  ~/tmp/windres.c windres.c
1100c1100,1101
<   def_target_arch = NULL;
---
>   //def_target_arch = NULL;
>   def_target_arch = "mach-o-x86-64";

The above diff indicates I changed line 1100 in the windres.c file by commenting it out, then added a new line which assigns the correct architecture to the def_target_arch variable. You then need to again:

make windres
sudo cp windres /usr/local/bin/

For detailed help you can consult the man page by opening an Applications > Utilities > Terminal and typing the following command:

man windres

Alternatively, you can display a usage summary by opening an Applications > Utilities > Terminal and typing the following command:

windres --help

Windows

On Windows, windres and the gorc resource compiler should be provided by the FPC and Lazarus installers.

Using resources in your program

Now let's extract the stored resource into a file, e.g. mydata.dat:

program mydata;
uses
  SysUtils, Classes, Windows {needed for RT_RCDATA, could be omitted};
{$R mydata.res}
var
  S: TResourceStream;
  F: TFileStream;
begin
  // create a resource stream which points to our resource
  S := TResourceStream.Create(HInstance, 'MYDATA', RT_RCDATA);
  // Replace RT_RCDATA with ??? with what?
  // Please ensure you write the enclosing apostrophes around MYDATA, 
  // otherwise no data will be extracted.
  try
    // create a file mydata.dat in the application directory
    F := TFileStream.Create(ExtractFilePath(ParamStr(0)) + 'mydata.dat', fmCreate); 
    try
      F.CopyFrom(S, S.Size); // copy data from the resource stream to file stream
    finally
      F.Free; // destroy the file stream
    end;
  finally
    S.Free; // destroy the resource stream
  end;
end.

Many classes (at least in Lazarus trunk/development version) also support loading directly from FPC resources, e.g.

procedure exampleproc;
var
  Image: TImage
begin
  Image := TImage.Create;
  Image.Picture.LoadFromResourceName(HInstance,'image'); // note that there is no need for the extension
end;


Lazarus resources

Warning-icon.png

Warning: As mentioned above, using "normal"/Windows resources. Lazarus has also switched to this format since ver. 1.4; see Lazarus_1.4.0_release_notes

In order to use your files as Lazarus resources, they must be included as a resource file.

You can create LRS files with LRS explorer or using lazres with the command line.

Lazres can be found in the "Tools" directory (C:\Lazarus\Tools\ - you may need to compile it from lazres.lpi project) of your Lazarus installation folder.

Then you can compile Lazarus resource files (*.lrs) via the command line. The syntax for lazres is:

lazres <filename of resource file> <files to include (file1 file2 file3 ...)>

Example:

lazres mylazarusresource.lrs image.jpg

Alternatively you can compile and execute glazres (C:\Lazarus\Tools\glazres) for a GUI version of lazres.

To use a Lazarus resource file in your project, include the file with the $I compiler directive in the initialization section of your unit.

You can access the data in the resources directly or with the LoadFromLazarusResource method of the variables which will hold the file contents afterwards. LoadFromLazarusResource requires a string parameter that indicates which object should be loaded from the resource file.

Example:

uses ...LResources...;

...
procedure exampleproc;
var
  Image: TImage
begin
  Image := TImage.Create;
  Image.Picture.LoadFromLazarusResource('image'); // note that there is no need for the extension
end;

initialization
  {$I mylazarusresource.lrs}

This code includes the file mylazarusresource.lrs into the project. In the procedure exampleproc an icon object is created and loaded from the object "image" out of the resource. The file which was compiled into the resource was probably named image.jpg.

Every class that is derived from TGraphic contains the LoadFromLazarusResource procedure.

Lazarus Resource Form File

Lazarus generates .LRS files from .LFM form files.

When a LRS form file is missing, FPC reports the following error: ERROR: unit1.pas(193,4) Fatal: Can't open include file "unit1.lrs"

To solve it you can either:

  • use lazres: c:\lazarus\tools\lazres.exe unit1.lrs unit1.lfm
  • (easier): make a trivial change in the form design, revert it and save the form; this will recreate the .lrs file without needing to run lazres.

Getting the raw data of an lrs resource

You can retrieve the data of the resource with:

uses ...LResources...;

...
procedure TForm1.FormCreate(Sender: TObject);
var
  r: TLResource;
  Data: String;
begin
  r:=LazarusResources.Find('datafile1');
  if r=nil then raise Exception.Create('resource datafile1 is missing');
  Data:=r.Value;
  ...do something with the data...
end;

See also

External links