Sign in Join
Wiki copytemporary

Lazarus Packages: what changed

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

OldNewLine
11## Overview of the Lazarus Package System
22
33For other meanings of **Package** in the combined FPC/Lazarus projects see [[packages(disambiguation)|Packages(disambiguation)]].
44
55![](/wiki-images/5/52/Packagegraph1.png)
66
77## What is a Lazarus package?
88
99A Lazarus package is a collection of units and components, containing information how they can be compiled and how they can be used by projects or other packages or the IDE. The IDE automatically compiles packages if some of its files are modified. In contrast to Delphi, packages are not limited to libraries and they can be OS independent. ([[packages|Library Packages]] are specially compiled libraries used by applications, the IDE or both. Delphi/Library packages require in-compiler support, which FPC is not capable of at the moment and of course this magic is OS dependent.)
1010
1111Currently the [[Free Pascal]] compiler only supports static packages, not dynamic packages. Therefore you must compile and restart the IDE, each time a package is installed or uninstalled.
1212
1313A lazarus package is identified/distinguished by the name and its version.
1414
1515Packages are ideal for sharing code between projects.
1616
1717Here is a typical directory layout of a Lazarus package:
1818
1919 /home/user/pascal/pkg1/ - an arbitrary directory, often it is named similar to the package name
2020 pkg1.lpk - the package file
2121 pkg1.pas - this unit is automatically created by the IDE and is only needed for compiling
2222 apackageunit.pas - your shared unit, choose a unique name that do not clash with other sources/packages
2323 aform.pas - your shared form
2424 aform.lfm - the form file of your shared form
2525 lib/i386-linux/ - the output directory of the package. The directory and its content is automatically created.
2626 pkg1.compiled - the state file containing the parameters how the package was compiled the last time.
2727 pkg1.ppu
2828 pkg1.o
2929 apackageunit.ppu
3030 apackageunit.o
3131 aform.ppu
3232 aform.o
3333 aform.lfm
3434
3535## Coming from Delphi
3636
3737If you are familiar with Delphi packages then read the following paragraph, because there are some important differences between a Delphi and a Lazarus package.
3838
3939- Lazarus packages are not only a dynamic library. They are used to share units between projects and modularize big projects.
4040- Sometimes the Delphi main file of a package is called "Package Project". This term makes no sense under Lazarus.
4141- Many Delphi packages provide one "package project" per compiler version. This is hardly needed under Lazarus. But you can do that for Delphi compatibility. Lazarus packages have version information and projects can define that they require at least or at most a specific version of a package. Lazarus will automatically load the right version.
4242- If a unit can not be found, under Delphi you are used to add the directory to the global search path. This has many drawbacks when sharing code. That's why this is not supported by Lazarus. Use packages instead.
4343
4444## FAQ
4545
4646**Q:** Do I need to install a package?\
4747**A:** You **only** need to install a package, if it contains designtime items, like components for the IDE component palette. If you don't use those items, you don't need to install the package. If you only want to use a package in your project, don't install it. Use the project inspector and add a requirement.
4848
4949**Q:** I installed a package, but the IDE does not find the units\
5050**A:** Installing a package means that the package is integrated into the IDE, not in your project. These are separate things. To use a package in your project, use Project -\> Project Inspector -\> Add -\> New Requirement. And uninstall the package, if it does not contain any IDE goodies.
5151
5252## Quick Start
5353
5454To see the packagesystem in action and to get used to it, do the following:
5555
5656### Creating a new package
5757
5858- Package-\>New Package... or File-\>New... -\> Package -\> Package
5959- A package editor opens
6060
6161![](/wiki-images/3/37/How_to_write_lazarus_component_package_maker.png)
6262
6363- A window titled "Save Package NewPackage 0.0(*.lpk)" opens. Choose a directory and a name for your new package. The name must be a valid Pascal identifier with the extension *.lpk*.
6464- Use the *Save* button at the bottom right to save the package in the directory and name you've chosen.
6565- Depending on your 'naming' setting in the 'environment options', the IDE will ask you to save the file lowercase. Say yes.
6666
6767Congratulations: You have just created your first package!
6868
6969### Adding a new component
7070
7171- Use the Add button -\> New component
7272- Choose a component in the ancestor type combobox. For instance: TBevel.
7373- Click Ok
7474- The file will be added to the package and opened in the editor
7575- Install the package by clicking the 'install' button in the top of the package editor.
7676- Lazarus will save the package and ask you, if the IDE should be rebuilt. Say yes.
7777- The packages are statically linked, so a restart of the IDE is needed.
7878- Restart Lazarus and see your new component in the component palette (For example: A TBevel1 will be on the 'Additional' page).
7979- If you do not see your new component in the component palette, it is most likely that you are not running the re-compiled version of Lazarus. You can set where Lazarus builds to in: Tools -\> Options -\> Environment options -\> Files -\> Lazarus directory. Instead of calling lazarus directly, you also can use [[startlazarus]], which starts the newly created lazarus, for example the lazarus executable in the ~/.lazarus directory, if you don't have write access to the directory lazarus was installed into.
8080
8181Congratulations: You have just installed your first package with your first package component.
8282
8383### Add a component icon
8484
8585Component icons can use Lazarus resources or FPC resources.
8686
8787#### Using Lazarus resources
8888
8989Also page exists here: [[How to add icons my package components]].
9090
9191The idea is to create a png, convert that into a lrs include file using the [[lazres]] tool and include that. Since 0.9.29 there is a button on the new component page to do that automatically.
9292
9393Here are the details:
9494
9595- Size of PNG file should be 24x24
9696- Name of png must be the *class name* of the new component, case does not matter (e.g. *tmyComponent.png* for *TMyComponent*).
9797
9898To create the lrs file run (where *TMyComponent* is the class name of your component and *yourunit* is the unit name):
9999
100-`~/lazarus/tools/lazres yourunit.lrs TMyComponent.png`
100+```text
101+~/lazarus/tools/lazres yourunit.lrs TMyComponent.png
102+```
101103
102104- You may need to compile *lazres* at first use. Simply open the *lazres.lpi* in the IDE and at the menu click run \> build.
103105
104106Hint: You can add more than one image to the lrs file by appending the image filename at the end. For example
105107
106-`~/lazarus/tools/lazres yourunit.lrs TMyComponent.png TMyOtherCom.png ...`
108+```text
109+~/lazarus/tools/lazres yourunit.lrs TMyComponent.png TMyOtherCom.png ...
110+```
107111
108112Following is a sample of the resulting *yourunit.lrs* file.
109113
110114``` pascal
111115LazarusResources.Add('TMyComponent','PNG',[
112116 #137'PNG'#13#10#26#10#0#0#0#13'IHDR'#0#0#0#24#0#0#0#24#8#2#0#0#0'o'#21#170#175
113117 +#0#0#0#4'gAMA'#0#0#177#143#11#252'a'#5#0#0#0'|IDAT8O'#237#212#209#10#192' '#8
114118 +#5'P'#247#231#251's'#215#138#133#164#166'\'#220#195'`'#209'c'#157'L'#173#131
115119 +#153#169'd4'#168'dP'#137'r_'#235'5'#136'@Zmk'#16'd9'#144#176#232#164'1'#247
116120 +'I'#8#160'IL'#206'C'#179#144#12#199#140'.'#134#244#141'~'#168#247#209'S~;'#29
117121 +'V+'#196#201'^'#10#15#150'?'#255#18#227#206'NZ>42'#181#159#226#144#15'@'#201
118122 +#148#168'e'#224'7f<@4'#130'u_YD'#23#213#131#134'Q]'#158#188#135#0#0#0#0'IEND'
119123 +#174'B`'#130
120124]);
121125```
122126
123127- Click the Add button again, goto the Add File tab and browse to the yourunit.lrs file and click Ok. This is needed, so that the IDE checks this file for changes and will recompile your package.
124128
125129- Add an include directive to yourunit:
126130
127131``` pascal
128132unit YourUnit;
129133...
130134uses
131135 ..., LResources;
132136...
133137implementation
134138...
135139initialization
136140 {$I yourunit.lrs}
137141end.
138142```
139143
140144Note: You can include more than one lrs file, but each only once.
141145
142146- That's all. Compile or install your package
143147
144148#### Using FPC resources
145149
146150Create a 24x24 16 color bitmap for each component. This format won't support PNG files. Then create an rc file as follows:
147151
148-`TMYCOMPONENT1NAME  BITMAP  "pathtobitmap1//bitmap1.bmp"`\
149-`TMYCOMPONENT2NAME  BITMAP  "pathtobitmap2//bitmap2.bmp"`\
150-`....`\
151-`TMYCOMPONENTnNAME  BITMAP  "pathtobitmapn//bitmapn.bmp"`
152+```text
153+TMYCOMPONENT1NAME BITMAP "pathtobitmap1//bitmap1.bmp"
154+TMYCOMPONENT2NAME BITMAP "pathtobitmap2//bitmap2.bmp"
155+....
156+TMYCOMPONENTnNAME BITMAP "pathtobitmapn//bitmapn.bmp"
157+```
152158
153159Note that double slashes (Linux) and double backslashes (Windows) are used in the bitmap path. It is advisable for the file's name to be the same as the package name with an extension of rc, ie MyPackageName.rc
154160
155161Let windres (Binutils) create the actual resource:
156162
157-`pathToWindres/windres -J rc -O res "MyPackageName.rc" "MyPackageName.dcr"`
163+```text
164+pathToWindres/windres -J rc -O res "MyPackageName.rc" "MyPackageName.dcr"
165+```
158166
159167Alternatively, you can use the lazres tool to create a .res file:
160168
161-`pathToLazarus/tools/lazres MyPackageName.res bitmap.bmp bitmap_150.bmp bitmap_200.bmp`
169+```text
170+pathToLazarus/tools/lazres MyPackageName.res bitmap.bmp bitmap_150.bmp bitmap_200.bmp
171+```
162172
163173Add to the registration unit of the package {\$R *.dcr} or {\$R *.res} right after the implementation keyword, and compile/install the package.
164174
165175### Creating a package for your common units
166176
167177Let's say you have some units, that you want to use in your projects. Put the units in a separate directory, for instance *C:\MySharedUnits*.
168178
169179- Package-\>New Package or File-\>New... -\> Package -\> Standard Package
170180- A package editor opens
171181- Use the Save button at top left. Choose *C:\MySharedUnits\MySharedUnits.lpk*. The package name must not conflict with any existing unit.
172182- Depending on your 'naming' setting in the 'environment options', the IDE will ask you to save the file lowercase. Say *yes*.
173183- Now you have a package with the name *MySharedUnits* stored as *C:\MySharedUnits\mysharedunits.lpk*.
174184- Adding the units: *Add-\>Add Files-\>Add directory*.
175185- A dialog will appear with the directory *C:\MySharedUnits* and some include and exclude filters. Click *Ok* to add all units.
176186- The units will now be listed. Click *Add files to package*.
177187- The files are now added to the package. Click *Save*.
178188- If your units only require the standard FPC units you can now simply press *Compile*. Otherwise see below.
179189
180190### Adding the LCL as dependency
181191
182192If your package contains forms or any other GUI LCL unit, then it requires the LCL package.
183193
184194- In the package editor of your package click *Add -\> New Requirement*
185195- Choose as *package name* *LCL*
186196- Click *Ok*.
187197- The LCL is now added under Required Packages. Click *Save*.
188198
189199You can see the what the LCL does, by clicking in the package editor of your package *Compiler Options / Inherited*.
190200
191201If you only use non-GUI LCL components such as [[fileutil]], you can add a dependency to *LCLBase*
192202
193203### Use your package in your project
194204
195205You need to add a dependency from the project to your new package. There are several ways to do this:
196206
197207- Open your package. For example via *Package / Open recent package*. On the package editor of your package click *More ... / Add to project*.
198208- Or you can use the project inspector:
199209 - *Project / Project Inspector*.
200210 - Click on the *Add* button with the plus.
201211 - Select the page *New Requirement*
202212 - Choose as package name your package
203213 - Click Ok
204214
205215## The IDE menu items for packages
206216
207217- Package -\> New Package **or** File-\>New... -\> Package -\> Standard Package
208218 - Creates a new package.
209219- Project -\> Project Inspector
210220 - Here you can see, what packages are required by the currently open project.
211221 - You can add new dependencies and remove unneeded ones.
212222- Run -\> Compiler options -\> Inherited
213223 - Here you can see what compiler options are inherited from which package.
214224- Package
215225 - **Open package**: A dialog shows all open packages with their state.
216226 - **Open package file**: Open a .lpk file
217227 - **Open package of current unit**: Open the .lpk file, that belongs to the file in the source editor
218228 - **Open recent package**: Open a recently open package file (lpk file)
219229 - **Add active unit to a package**: Adds the unit in the source editor to a package
220230 - **Package Graph**: The package graph shows all open packages and their dependencies.
221231 - **Configure installed packages**: Edit the list of packages installed in the IDE. Install or uninstall several packages at once.
222232
223233### Removing Packages
224234
225235- To remove installed components, on the IDE menu, click Package \> Configure installed packages. The following image shows the Installed Packages tool.
226236
227237![](/wiki-images/0/0e/How_to_write_lazarus_component_installed_components.png)
228238
229239- Select the package you want to uninstall and click Uninstall selection.
230240
231241If something goes wrong with a package (for instance a package directory is deleted without first uninstalling it), Lazarus may not allow you to uninstall packages. To fix the problem, at the IDE menu click Tools \> Build Lazarus. Lazarus will rebuild all packages and restart. You should now be able to uninstall problematic packages.
232242
233243## The theory
234244
235245Each Lazarus package has a .lpk file. A package is identified by its name and its version. The name must correspond to the lpk filename. For example:
236246
237247Name: Package1, Version: 1.0, Filename: /home/.../package1.lpk.
238248
239249- The IDE automatically creates the main source file (package1.pas). See below. The lpk file contains information about the required packages, the files it uses, how to compile them, and what is needed to use the package by other packages/projects. The directory where the lpk file is, is called the "package directory".
240250- The IDE maintains a list of all package files (\<config directory\>/packagelinks.xml). Every time a package is opened in the IDE it will be added to this list. When a package is opened, the IDE automatically opens all required packages via this list.
241251- Normally a package has a source directory with some pascal units. And normally the lpk file will be there too. A package has also an output directory. Default is the subdirectory 'lib/\$(TargetCPU)-\$(TargetOS)/' in the package directory.
242252- Before a package is compiled the IDE checks all required packages and if they need update and have the auto update flag, they are compiled first. Then the IDE creates the package main source file. If the lpk file was package1.lpk, then the main source file is package1.pas. This file contains all units in the uses section plus a [[Register (package)|'Register' procedure]], which is called in the initialization section.
243253
244254For example:
245255
246256``` pascal
247257{ This file was automatically created by Lazarus. Do not edit!
248258 This source is only used to compile and install
249259 the package GTKOpenGL 1.0.
250260}
251261unit GTKOpenGL;
252262
253263interface
254264
255265uses GTKGLArea, GTKGLArea_Int, NVGL, NVGLX, LazarusPackageIntf;
256266
257267implementation
258268
259269procedure Register;
260270begin
261271 RegisterUnit('GTKGLArea', @GTKGLArea.Register);
262272end;
263273
264274initialization
265275 RegisterPackage('GTKOpenGL', @Register);
266276end.
267277```
268278
269279- Then the compiler is called and the package is compiled to the output directory.
270280- The IDE compares the current compiler options with the last one, which are stored in the .compiled file. If they differ the IDE cleans up the output directory and compiles the package with -B, telling the compiler to recompile everything it can. Differences in search paths and verbosity options do not trigger a clean up. Since 0.9.31 the IDE removes all files in the unit output directory on clean up if the output directory does not contain source files (listed in the package editor) and is not shared with required packages.
271281- After compilation (successful or not) the state file is created. The state file is put into the output directory. It has the name \<packagename\>.compiled and contains the information, how the package was compiled and if the compilation succeeded. This state file is used by the IDE to check if update is needed and if a full recompile (-B) is needed.
272282
273283For example: gtkopengl.compiled:
274284
275285``` xml
276286<?xml version="1.0"?>
277287<CONFIG>
278288 <Compiler Value="/usr/bin/ppc386" Date="781388725"/>
279289 <Params Value=" -Rintel -S2cgi -CD -Ch8000000 -OG1p1
280290 -Tlinux -gl -vewnhi -l -Fu../../../lcl/units
281291 -Fu../../../lcl/units/gtk -Fu../../../packager/units
282292 -Fu. -FElib/ gtkopengl.pas"/>
283293</CONFIG>
284294```
285295
286296- The IDE opens all needed packages automatically. This means, it opens all installed packages, all packages marked for installation (auto install), all packages with an open Editor, all packages required by the project and all packages required by one of the other packages. Unneeded packages are automatically unloaded, when the IDE becomes idle.
287297- The IDE never opens two packages with the same name at the same time. When the user opens another package file with the same name the IDE will ask if it should replace the old one.
288298- The IDE maintains two extra sets of packages: The 'installed' packages and the 'auto install' packages. The auto install packages will be linked into the IDE on next compile. It creates two new files in the config directory: staticpackages.inc and idemake.cfg. Then it calls 'make ide OPT=@/path/to/your/config/idemake.cfg' to compile itself.
289299
290300## Package states
291301
292302A package can have none, one or several of the following states:
293303
294304- **used** - a package can be **used** by a project or package, i.e. it is required and listed in Project inspector or Package Editor respectively. When you open a project or package all **used** packages are automatically **loaded** by the IDE.
295305- **loaded** - When the IDE opens a .lpk file the package is loaded. The IDE knows its settings and files. The IDE automatically loads all **used** packages of a project and its **installed** packages. This does not load the package code, as the compiler and IDE do not support dynamic packages yet.
296306- **marked for installation** - To run the package code inside the IDE, you need to rebuild the IDE and restart it. That means the first step is to **mark** the package **for installation**. Then rebuild the IDE and finally restart it.
297307- **installed** - The compiled code of the package is loaded and registered in the currently running IDE. If the IDE was able to locate the .lpk file it will be **loaded**.
298308- **uninstall on next start** - The package is **installed**, but will not be compiled into a new IDE. That means, when you rebuild the IDE and restart it, the package will no longer be **installed**. Keep in mind, that a package can be required indirectly by an installed package and thus will be installed as well.
299309
300310## Hints and Tips
301311
302312Please add any hints, tips or gotchas here.
303313
304314- To rename a package, use 'save as'.
305315- You can add to every dependency the default filename. For instance you provide an example project for your package. When another programmer opens your example for the first time, the IDE does not know where the lpk file is. Simply right click on the dependency in the project inspector and 'Store file name as default for this dependency'. The file name is stored relative to the project. You can do the same for package dependencies.
306316- Use package: to use all units of the package in the project, enable the **Add package unit to uses section** on package editor / Options / Usage. When the package is added to a project, the lpr uses section is extended with the package main unit. For example if the package implements a new graphic type, it only has initialization sections, but the no project code use it directly.
307317
308318## Adding existing components to a Package
309319
310320If you want to add a file that contains a component to an existing package, you can do the following:
311321
312322- Open the package file
313323- Click on the 'Add' file to add a new item to the package.
314324- Select the unit tab in the 'Add to package' dialog.
315325- Choose the file to add.
316326- Check the 'Has register procedure' if the unit contains a Register procedure. If you do not do this, the component(s) will not be shown on the component palette.
317327- Click 'Add unit'.
318328- Recompile and install the package.
319329
320330That's it. The component should now show on the component palette.
321331
322332## Create a package with a unit that has the same name as the package
323333
324334Normally the IDE auto creates the registration code into a unit with the same name as the package. If you want to name your package the same as an existing unit, for example because the package has only one unit, then you need at least Lazarus 0.9.29 and use this:
325335
326336- Make a backup of your unit *mypackage.pas*.
327337- Create the package *mypackage.lpk* normally and do not add the unit yet.
328338- Add a new unit, for example *mypackageall.pas*.
329339- Select the unit *mypackageall.pas* in the package editor and right click for the popup menu.
330340- Change *File type* to *Main Unit*.
331341- Now restore your unit *mypackage.pas* and add it to the package.
332342
333343## File Type
334344
335345Select a file in the package editor, right click for the popup menu. File Type:
336346
337347- Unit - A .pas or .pp file (or .p in mode macpas)
338348- Virtual Unit - Placeholder for a unit not in the package folders. For example the package FCL contains some virtual units for some FPC units.
339349- Main Unit - this unit contains the autogenerated code to compile the package. There can only be one per package.
340350- Issues xml file [[IDE Window: Restriction Browser|see here]]
341351
342352## The Register procedure
343353
344354To show a component on the component palette, it must be registered in Lazarus. This is done in the 'Register' procedure. This is a procedure that must appear in the interface section of the unit it is in, and must issue one or more RegisterComponent calls, as well as install property and component editors for the components.
345355
346356One or more Register procedures can be present in a package: in the package editor, you must indicate the units that have a 'register' procedure, so Lazarus knows which procedures it must call when the package is installed.
347357
348358There are 2 ways to mark a unit as having a register procedure:
349359
350360- You can do this while adding the units to the package (see the 'Adding existing components to a package' section),
351361- or you can select the unit in the package dialog, and set the 'Register' checkbox in the details panel.
352362
353363Do not forget to recompile and install the package after changing the properties.
354364
355365## Search paths
356366
357367All search paths are stored relative to the directory of the .lpk file. If you use an absolute path you have either not understood packages or you don't care.
358368
359369Each package has two types of search paths:
360370
361371- Paths in the *Options / Compiler Options* are used to compile the package itself.
362372- Paths in the [[IDE Window: Package Options|Options / Package Options / Usage]] are used by packages and projects that require this package. In other words these paths are added to the search paths of the project (or requiring package). Keep in mind that if project uses package A and that uses package B, the *Usage* options of B are appended to A **and** the project.
363373
364374Since 0.9.29 you can specify compiler options depending on the target platform.
365375
366376## Your package provides a library, how to extend the linker search path in all your projects
367377
368378A package can define search paths that are added to packages and projects using it. See [[IDE Window: Package Options|Options / Package Options / Usage]].
369379
370380## Design Time vs Run Time package
371381
372382There are four different types of packages.
373383
3743841. A **design and runtime** package can be installed in the IDE and can be used normally by projects. This is the default.
3753852. A **design time** package can be installed in the IDE and provides IDE extensions like new components, new file or project types, new menu items, new component or property editors, etc. Projects can use *design time* packages (i.e. they are listed in the project inspector requirements), but by default a design time package is not compiled into the project. That means project units cannot use units of the *design time* package. When a project uses such a package the IDE warns before opening a form of the project, so the user can install it first. To test a design time package outside the IDE you may want to use it in a test project. For this case you can change this in *Project Options / Miscellaneous / Use design time packages*.
3763863. A **run time** package can be used by projects. A user cannot install such a package directly (it is not listed). It cannot register things in the IDE. It can be used by *design time* packages, so it can be installed indirectly.
3773874. A **run time only** package can only be used by projects. It cannot be installed in the IDE, not even indirectly. For example if the package is incompatible with the core IDE packages like the LCL. Since 0.9.31.
378388
379389### Typical scenario for a run time and design time package
380390
381391You have a component library called *Awesome* and you want to write some IDE editors for some special properties. For example a property editor for the property Datafile which shows a TOpenDialog to let the user select a file. You can put the components into one run time package named *AwesomeLaz.lpk*' and create another directory *design* for the design time package *AwesomeIDELaz.lpk*. Move all units containing the IDE editors and registering stuff into the *design* directory. Add a dependency in AwesomeIDELaz to AwesomeLaz. Make sure they do not share units or search paths. For an example see *components/turbopower_ipro/*: The run time package is *turbopoweripro.lpk* and the design time package is *design/turbopoweriprodsgn.lpk*.
382392
383393### For Delphians: I can not install a run time package, why not?
384394
385395**Installing a package** means compiling the whole code into the IDE. A **run time** package does not contain code for the IDE or maybe even bites it. In order to use a package in your project, simply open the package, right click on the package editor for the popup menu and click **Add to project**. Alternatively you can use *View / Project Inspector*. The project inspector shows what packages are used by your project, you can add dependencies or delete them.
386396
387397### Examples
388398
389399Example for extending the Usage / Units path.
390400
391401The tiOPF framework has the following directory layout, due to the fact that it compiles for FPC, Delphi 5-7, D2005 and D2006:
392402
393403 Source <= full path \Programming\3rdParty\tiOPF\Source
394404 \Compilers
395405 \Delphi7 <= Delphi 7 package files live here
396406 \D2005
397407 \FPC <= the tiOPF.lpk lived here
398408 \Core <= core unit files
399409 \Options <= optional unit file for extra features
400410 \GUI
401411
402412Using this example, the following paths are included in the "Options - Usage - Units" editbox:
403413
404-`"$(PkgOutDir);..\..\Core;..\..\Options;..\..\GUI" `
414+```text
415+"$(PkgOutDir);..\..\Core;..\..\Options;..\..\GUI"
416+```
405417
406418This search path will be added to whatever project uses this package. The default is \$(PkgOutDir), which would add only the ppu files to the project. Adding more search paths has the effect that the .pas source files are found by the compiler a second time - once when compiling the package and once when compiling your project. Since package and project use different settings the compiler might create a second version of the ppu, which is put into your project's output directory. Then you have two ppu for one unit and then you can get strange errors. To avoid the duplication disable the compilation of the package, by setting it to compile only manually.
407419
408420## Platform specific units
409421
410422There are various ways to deal with separating platform-specific code:
411423
412424### One unit per platform, several units with same name
413425
414426For example the unit *myconnect.pas* has two versions, one for Windows and one for Unix/Linux/macOS/BSD. The idea is to put the units into different sub directories and use macros in search paths.
415427
416428- Create two sub directories: **win** and **unix**.
417429- Add to the package options / Compiler options / Paths / Other unit files the path **\$(SrcOS)**. SrcOS is a [[IDE Macros in paths and filenames|macro]], that translates to *win* under Windows and *unix* under Linux/macOS/BSD.
418430- Create a new package unit (package / Add / New file / Pascal unit) and save it under **win/myconnect.pas**.
419431- If the unit is not selected in the package editor, select it.
420432- Disable **use unit**.
421433- Create a second package unit (package / Add / New file / Pascal unit) and save it under **unix/myconnect.pas**.
422434- Keep the **use unit** enabled. It should be used once.
423435
424436### One unit for only one platform / conditional unit
425437
426438For example: the unit *mywin.pas* should only be used under Windows, i.e. it should only be used and compiled if the flag **Windows** is defined.
427439
428440The idea is to use the unit indirectly using IFDEFs. The following example shows how the unit **mywin.pas** is only used and compiled when the flag **Windows** is defined.
429441
430442- Create a new package unit (package / Add / New file / Pascal unit) and save it under **mywin.pas**.
431443- If the unit is not selected in the package editor, select it.
432444- Disable **use unit**.
433445- Create a new package unit (package / Add / New file / Pascal unit) and save it under **mypkgcompile.pas**.
434446- Add to the uses section of **mypkgcompile.pas**:
435447
436448``` pascal
437449uses
438450 Classes
439451 {$IFDEF Windows}
440452 ,mywin
441453 {$ENDIF}
442454 ;
443455```
444456
445457Note: mypkgcompile will be compiled under all platforms. mywin will only be compiled under Windows. You don't need to use the unit mypkgcompile in your project.
446458
447459## Different versions of a package
448460
449461If you work with different versions of a package, you can open at any time the other package file. The old package will be closed and the new one will be opened. Registered items will be transferred to the new package. For example the component palette still shows the components of the old package, with which the IDE was built. But right clicking on a component will show a menu item to open the recently used package.
450462
451463You can specify the minimum, maximum version required. When the project is opened and there are multiple .lpk files the IDE will automatically open the one with the right version.
452464
453465If you work with different projects that require different versions of a package (for example with different branches of the same package), you can define the preferred one in the dependencies. In the project inspector right click on the dependency and click on *Set file name as preferred for this dependency*. When the project is opened, the preferred package will be opened. If there is already a package with the same name it will be replaced. This feature exists since 0.9.29.
454466
455467![](/wiki-images/c/c8/SetDefaultPkDependency1.png)
456468
457469[[IDE Window: Project Inspector|Project Inspector]]
458470
459471### Example library with multiple lpk
460472
461473A library has two lpk files, *main.lpk* and *sub.lpk*. *main* depends on *sub*. The library has two version *1.0* and *2.0*.
462474
463475 trunk/
464476 main.lpk version 2.0, requires sub
465477 sub.lpk version 2.0
466478 fixes/
467479 main.lpk version 1.0, requires sub
468480 sub.lpk version 1.0
469481
470482When you open *main.lpk 1.0* for the first time, the IDE searches the package *sub* in its database and then it searches *sub.lpk* in the current folder. It finds *sub.lpk 1.0* and loads it.
471483
472484When you then open *main.lpk 2.0*, the IDE knows already a *sub.lpk*, the version 1.0 and loads it. It does not load the *sub.lpk 2.0*.
473485
474486There are two solutions:
475487
476488#### Using minimum, maximum version
477489
478490You can set for each dependency the minimum and maximum version. When you set the minimum and maximum version of the dependency the following will happen: The *main 1.0* and *sub 1.0* is open. You open *main 2.0* which requires *sub \>=2.0 and \<=2.0*. The IDE unloads *main 1.0*, loads *main 2.0*. The *sub 1.0* does not fit, so the IDE searches for *sub 2.0*. Again it first searches in its database and then in the current folder. It finds *sub.lpk* and loads *sub 2.0*.
479491
480492#### Using preferred file name
481493
482494If the two lpk files are always distributed together you can use instead of minimum and maximum versions the **preferred** option. Open from trunk the *main.lpk* and *sub.lpk* to make sure that the right versions are loaded. Then right click on the dependency from *main* to *sub* and choose *preferred file name*. The file name will appear to the right of the dependency. Repeat this step with the lpk files from version *2.0*. The IDE will now always open the right *sub.lpk*.
483495
484496## Build modes
485497
486498You can add build modes to your package. See here for the various ways to achieve this:
487499
488500[[Macros and Conditionals|Build modes for packages]]
489501
490502## Compiling a package via make
491503
492504The IDE can create a simple **Makefile** for a package via *Package editor / More ... / Create Makefile*. The IDE creates the file **Makefile.fpc** and calls **fpcmake**, which creates the Makefile. Since 0.9.29 the IDE also creates the file **Makefile.compiled**. If you are using a version control system like svn or git, add all three files to the repository:
493505
494-`Makefile`\
495-`Makefile.fpc`\
496-`Makefile.compiled`
506+```text
507+Makefile
508+Makefile.fpc
509+Makefile.compiled
510+```
497511
498512You can now run **make** (e.g. open a console, cd to the package directory with the Makefile) to compile the package. This will compile the package and after successful compilation copy the **Makefile.compiled** to the unit output directory.
499513
500514**Notes:**
501515
502516- The Makefile uses fixed paths, so it will **not** automatically adapt to changes as the IDE or lazbuild.
503517- The IDE can recreate the Makefile on every compile. Enable the option *Package editor / Options / Compiler Options / Compilation / Create Makefile*.
504518- The Makefile does not contain the logic for conditionals and build macros, it contains the settings at the time of creation.
505519- The macros \$(TargetOS), \$(TargetCPU) and \$(LCLWidgetType) are replaced by %TargetOS%, %TargetCPU% and %LCLPlatform%. The Makefile has somelogic to set some default values. You can override them (e.g. make LCLPlatform=qt).
506520- The Makefile.compiled file is copied by the Makefile after successful compilation to \<PkgOutDir\>/\<PkgName\>.compiled and is checked by the IDE (and lazbuild) if a package needs a recompile. For example the Lazarus binaries (Windows Installer, deb and rpm packages, OS X dmg package) are compiled via **make** and when the IDE is started and compiles a program it will not recompile used packages, unless the user set some extra flags. For example when the user changes the *IDEBuildOptions* via the *Configure Build Lazarus dialog* the IDE will detect the difference and recompile the package on next compile.
507521- If you forget to add the Makefile.compiled to svn you will get on make the error: /bin/cp: cannot stat \`Makefile.compiled': No such file or directory
508522
509523## Creating a closed sourced package
510524
511525Goal: you want to publish a package, but you want to keep the source closed.
512526
513527At the moment many IDE functions require the source; the IDE warns if the source of a unit is missing. Therefore you must publish the interface parts of the units, and the files the compiler creates (ppu and o files).
514528
515529Steps:
516530
517531- Create a copy of the package folder and change this copy as follows.
518532- In the package editor / Options / IDE integration, set **Update / Rebuild** to **Manual compilation**.
519533- Compile it once.
520534- Delete the implementation sections of all units (i.e. everything after the implementation keyword of each unit including the initialization and finalization, only keeping the "end."). You can also remove the private section.
521535- Optional: You can use the publish package tool (Package Editor / More... / Publish Package) to create a zip of the package.
522536- You can delete the .compiled file, Makefile, rst files, lrt files. All other files in the output directory like .ppu, .o, .lfm files are needed by the compiler. The IDE needs the .lpk and the stripped .pas and .inc files.
523537
524538There is a command line utility **sourcecloser** which alters the lpk and removes implementation sections. You can find it under *lazarus/components/codetools/examples/sourcecloser.lpi*.
525539
526540See also:
527541
528542- this article about FPC closed source units: [[Releasing units without source code]]
529543- Prezi: <http://prezi.com/vpuyxca-qboq/how-to-create-a-closed-source-package-with-lazarus/>
530544
531545## Parallel Compilation
532546
533547The IDE and lazbuild compile packages in parallel (since 1.3). Each package is still compiled with one call of fpc (single threaded).
534548
535549You can set the maximum number of parallel processes in *Tools / Options / Messages Window*. By default it tries to guess the amount of cpu cores with the function *GetSystemThreadCount* in unit *UTF8Process*.
536550
537551## See also
538552
539553- [[How To Write Lazarus Component]] - a tutorial about creating a new component.
540554- [[Install IDE packages without the IDE]]
541555
542556---
543557*From the Free Pascal wiki, page "Lazarus Packages", 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).*

Back to history