Sign in Join
Wiki copytemporary

Lazarus Resources: what changed

Revision 1 to 2. Removed lines have a minus sign; added lines have a plus sign.

OldNewLine
11## Introduction
22
33Resource 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.
44
55Before 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.
66
77Standard Delphi-compatible resources are now recommended for current FPC **(including all recent Lazarus versions)**. Please see FPC resources below.
88
99Alternatively, you can include resources in your application from within the Lazarus IDE by using the [[IDE Window: Project Options|IDE Resources Dialog]].
1010
1111## FPC resources
1212
1313Starting 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"](http://www.freepascal.org/docs-html/prog/progch13.html)
1414
1515To 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.
1616
1717Use
1818
1919- {\$R filename.rc} to compile a resource script and include the resulting resource file or
2020- {\$R filename.res} directive to include a compiled resource file
2121
2222into the executable.
2323
2424FPC RTL provides both low-level functions as well as high-level classes to access resources.
2525
2626The low-level functions are:
2727
2828- EnumResourceTypes
2929- EnumResourceNames
3030- EnumResourceLanguages
3131- FindResource
3232- FindResourceEx
3333- LoadResource
3434- SizeofResource
3535- LockResource
3636- UnlockResource
3737- FreeResource
3838
3939They are compatible with the Windows API functions: \[<http://msdn.microsoft.com/en-us/library/ff468902(VS.85>).aspx\]
4040
4141The 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.
4242
4343### Adding resources to your program
4444
4545Let'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.
4646
4747First 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:
4848
4949``` pascal
5050MYDATA RCDATA "mydata.dat"
5151```
5252
5353Here 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.
5454
5555Let's instruct the compiler to include the resource into your project:
5656
5757``` pascal
5858program mydata;
5959
6060{$R mydata.rc}
6161begin
6262end.
6363```
6464
6565Behind 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}`.
6666
6767### Use the -FF parameter in FPC 3.3.1
6868
6969FPC 3.3.1 can use fpcres instead of windres as RC to RES compiler. To enable it, pass the -FF parameter to the compiler. In that case you won't have to install windres.
7070
7171Edit your fpc.cfg and add lines at the end in order to enable the parameter by default
7272
7373``` c
7474# Use fpcres as resource compiler
7575-FF
7676```
7777
7878### Checking you have windres
7979
8080On Linux/FreeBSD/macOS, you might need to make sure you have the *windres* resource compiler, which is part of the GNU binutils project.
8181
8282#### Linux
8383
8484On Debian systems you could run (FIXME : this work for a 64B version, for 32B systems you will must probably change w64 to w32) :
8585
8686``` bash
8787sudo apt install mingw-w64 mingw-w64-tools
8888```
8989
9090or, if you do not need full mingw :
9191
9292``` bash
9393sudo apt install binutils-mingw-w64-x86-64
9494```
9595
9696Next 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")
9797
9898``` c
9999# MS Windows .rc resource compiler
100100#IFDEF CPUAMD64
101101-FCx86_64-w64-mingw32-windres
102102#ENDIF
103103#IFDEF cpui386
104104-FCi386-w64-mingw32-windres
105105#ENDIF
106106```
107107
108108#### FreeBSD
109109
110110Even 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.
111111
112112When 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:
113113
1141141\. From the /usr/ports/devel/binutils directory, cd work/binutils-2.xx/binutils
115115
1161162\. Copy the *windres* binary into your /usr/local/bin/ directory, or into your \$HOME/bin/ directory.
117117
118118**Note:** The *windres* utility is hardcoded to use *gcc* but [FreeBSD 10.0](https://www.freebsd.org/releases/10.0R/relnotes.html#userland) (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.
119119
120120#### macOS
121121
122122##### Using binutils source
123123
124124As of December 2021, the latest version is binutils-2.37 but it changes regularly. Substitute the latest version in any command below.
125125
126126- Download the latest binutils source from <https://ftp.gnu.org/gnu/binutils/>
127127- Uncompress the binutils-2.37.tar.gz archive (I used *The Unarchiver* free utility from the Mac App Store)
128128- Open an Applications \> Utilities \> Terminal and type the following commands:
129129
130-`cd binutils-2.34`\
131-`./configure`\
132-`make`\
133-`cd binutils`\
134-`make windres`\
135-`sudo cp windres /usr/local/bin/`\
136-`cd doc`\
137-`gzip windres.1`\
138-`sudo cp windres.1.gz /usr/local/share/man/man1/`
130+```text
131+cd binutils-2.34
132+./configure
133+make
134+cd binutils
135+make windres
136+sudo cp windres /usr/local/bin/
137+cd doc
138+gzip windres.1
139+sudo cp windres.1.gz /usr/local/share/man/man1/
140+```
139141
140142If you execute `windres` you will get a disappointing error message:
141143
142-`windres: Can't detect architecture.`
144+```text
145+windres: Can't detect architecture.
146+```
143147
144148To 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:
145149
146-`$ diff  ~/tmp/windres.c windres.c`\
147-`1100c1100,1101`\
148-`<   def_target_arch = NULL;`\
149-`---`\
150-`>   //def_target_arch = NULL;`\
151-`>   def_target_arch = "mach-o-x86-64";`
150+```text
151+$ diff ~/tmp/windres.c windres.c
152+1100c1100,1101
153+< def_target_arch = NULL;
154+---
155+> //def_target_arch = NULL;
156+> def_target_arch = "mach-o-x86-64";
157+```
152158
153159The 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:
154160
155-`make windres`\
156-`sudo cp windres /usr/local/bin/`
161+```text
162+make windres
163+sudo cp windres /usr/local/bin/
164+```
157165
158166For detailed help you can consult the man page by opening an Applications \> Utilities \> Terminal and typing the following command:
159167
160-`man windres`
168+```text
169+man windres
170+```
161171
162172Alternatively, you can display a usage summary by opening an Applications \> Utilities \> Terminal and typing the following command:
163173
164-`windres --help`
174+```text
175+windres --help
176+```
165177
166178#### Windows
167179
168180On Windows, windres and the gorc resource compiler should be provided by the FPC and Lazarus installers.
169181
170182### Using resources in your program
171183
172184Now let's extract the stored resource into a file, e.g. mydata.dat:
173185
174186``` pascal
175187program mydata;
176188uses
177189 SysUtils, Classes, LCLType;
178190{$R mydata.res}
179191var
180192 S: TResourceStream;
181193 F: TFileStream;
182194begin
183195 // create a resource stream which points to our resource
184196 S := TResourceStream.Create(HInstance, 'MYDATA', RT_RCDATA);
185197 // Please ensure you write the enclosing apostrophes around MYDATA,
186198 // otherwise no data will be extracted.
187199 try
188200 // create a file mydata.dat in the application directory
189201 F := TFileStream.Create(ExtractFilePath(ParamStr(0)) + 'mydata.dat', fmCreate);
190202 try
191203 F.CopyFrom(S, S.Size); // copy data from the resource stream to file stream
192204 finally
193205 F.Free; // destroy the file stream
194206 end;
195207 finally
196208 S.Free; // destroy the resource stream
197209 end;
198210end.
199211```
200212
201213Many classes (at least in Lazarus trunk/development version) also support loading directly from FPC resources, e.g.
202214
203215``` pascal
204216procedure exampleproc;
205217var
206218 Image: TImage
207219begin
208220 Image := TImage.Create;
209221 Image.Picture.LoadFromResourceName(HInstance,'image'); // note that there is no need for the extension
210222end;
211223```
212224
213225## Lazarus resources
214226
215227> **Warning:** As mentioned above, using "normal"/Windows resources is now possible. Lazarus has also switched to this format since ver. 1.4; see [[Lazarus 1.4.0 release notes]]
216228
217229In order to use your files as Lazarus resources, they must be included as a resource file.
218230
219231You can create LRS files with [LRS explorer](https://sourceforge.net/projects/lrsexplorer/) or using *lazres* with the command line.
220232
221233Lazres 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.
222234
223235Then you can compile Lazarus resource files (*.lrs) via the command line. The syntax for lazres is:
224236
225237 <nowiki>lazres <filename of resource file> <files to include (file1 file2 file3 ...)></nowiki>
226238
227239Example:
228240
229241```dos
230242lazres mylazarusresource.lrs image.jpg
231243```
232244
233245Alternatively you can compile and execute glazres (C:\Lazarus\Tools\glazres) for a GUI version of lazres.
234246
235247To use a Lazarus resource file in your project, include the file with the \$I compiler directive in the **initialization** section of your unit.
236248
237249You 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.
238250
239251Example:
240252
241253``` pascal
242254uses ...LResources...;
243255
244256...
245257procedure exampleproc;
246258var
247259 Image: TImage
248260begin
249261 Image := TImage.Create;
250262 Image.Picture.LoadFromLazarusResource('image'); // note that there is no need for the extension
251263end;
252264
253265initialization
254266 {$I mylazarusresource.lrs}
255267```
256268
257269This 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.
258270
259271Every class that is derived from [[TGraphic]] contains the [[LoadFromLazarusResource]] procedure.
260272
261273### Lazarus Resource Form File
262274
263275Lazarus generates .LRS files from .LFM form files.
264276
265277When a LRS form file is missing, FPC reports the following error: `ERROR: unit1.pas(193,4) Fatal: Can't open include file "unit1.lrs"`
266278
267279To solve it you can either:
268280
269281- use lazres: c:\lazarus\tools\lazres.exe unit1.lrs unit1.lfm
270282- (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.
271283
272284### Getting the raw data of an lrs resource
273285
274286You can retrieve the data of the resource with:
275287
276288``` pascal
277289uses ...LResources...;
278290
279291...
280292procedure TForm1.FormCreate(Sender: TObject);
281293var
282294 r: TLResource;
283295 Data: String;
284296begin
285297 r:=LazarusResources.Find('datafile1');
286298 if r=nil then raise Exception.Create('resource datafile1 is missing');
287299 Data:=r.Value;
288300 ...do something with the data...
289301end;
290302```
291303
292304## See also
293305
294306- [[fcl-res|FCL resource units]]
295307- [[lazres|Lazarus Resource compiler]]
296308- [[IDE Window: Project Options|IDE Project Options &gt; Resources]]
297309
298310## External links
299311
300312- [Free Pascal Programmer's Guide, Chapter 13 "Using Windows resources"](https://www.freepascal.org/docs-html/prog/progch13.html).
301313
302314---
303315*From the Free Pascal wiki, page "Lazarus Resources", as it stood on 2023-12-13 after a change by Coz, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*
304316Category: FPC
305317Category: Lazarus
306318Category: Tutorials

Back to history