Sign in Join
Wiki copytemporary

Code Conversion Guide: what changed

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

OldNewLine
11This page is about how to port or convert existing Delphi or Kylix code to work with the [[Free Pascal]] Compiler and Lazarus IDE. While Lazarus and the Free Pascal Compiler have aspects in common with Delphi and Kylix, they are not clones. There are a number of library call and convention differences... and in some areas, FPC is enhanced and can be more demanding about correct syntax. Please see the [[Lazarus For Delphi Users]] guide for a description of some of the functional differences.
22
33The purpose of this guide is to document some of the specific differences that are frequently encountered during the code conversion process when translating existing code from Delphi to Lazarus.
44
55This document was placed into the wiki knowledge-base area so it could be easily extended by anyone who had encountered a unique problem and would like to post it for others to be aware of.
66
77## Selecting a component or library for conversion
88
99### Where to find code to convert
1010
1111There is a LOT of code available on the net that can be converted for use with FPC and Lazarus. Here is a [[Page Of Code Sites]] that is just a start. Please add to it if you know of any other good locations. TurboPower Software has recently released their entire commercial offering under the MPL. A list of available packages can be found [here](http://sourceforge.net/users/tpsfadmin/).
1212
1313To avoid duplicating effort, packages that have already been converted are listed on the [[Components and Code examples]] page. If you've converted a package or are working on one, please add a note on the [[Current conversion projects]] page.
1414
1515### Licensing
1616
1717Licenses for existing code range from freeware/public domain to restrictive versions that prohibit modification, re-distribution and commercial use. Before converting any package, it's a good idea to examine its licensing and make sure it's going to be compatible with Lazarus and the Free Pascal Compiler. License selection is especially important with components since dropping one on a form can impose an unwanted or incompatible license on an entire application.
1818
1919When converting components, please respect the wishes of the original author and retain all copyright and licensing headers along with email addresses and url's. It's courteous and often useful to inform the author that their component is being converted... especially if the component is under a restrictive license. New interest in an old or forgotten component can sometimes inspire authors to revise their original and overly restrictive licensing.
2020
2121In general, Public Domain (freeware), and the LGPL/MPL are the the most flexible for distributing components. For more information, the [Open Source Definition](http://www.opensource.org/docs/definition.php) is a good place to start. There are also several comparisons available to help clarify how the various types of licenses work and what impact they'll have on code they're linked to. Search for "open source license comparison"
2222
2323### Dependencies
2424
2525Another step before starting to work on a conversion is to verify that the code doesn't have deep dependancies on other packages that might not be available or represent a considerable conversion challenge. Some freeware offerings are bound to or extend proprietary packages that are frequently no longer available or come with inappropriate licenses.
2626
2727### Compiler Issues
2828
2929See:
3030
3131- [Known problems](http://www.freepascal.org/probs.html)
3232- [Unfixed bugs](https://gitlab.com/freepascal.org/fpc/source/-/issues)
3333
3434### Platform and OS Issues
3535
3636Lazarus and the Free Pascal Compiler are cross-platform and cross-architecture development tools. In contrast, most existing Delphi code was specifically designed to run on an Intel processor under Win32. If your candidate component has a lot of Win32 specific code, it might be wise to try and find a less platform dependant alternative. But don't let this stop you... it's genuinely amazing what the LCL supports!
3737
3838## Doing the conversion
3939
4040### Setting up the Lazarus environment for a conversion project
4141
4242#### Create a test project
4343
4444- Place code to be converted into a subdirectory (ie: convertdir)
4545- Bring up Lazarus
4646- File-\>Save All to the convertdir subdirectory. Meaningful names for the Project and default unit are optional.
4747- Open the "main" unit to be converted in convertdir
4848- Add it to the project: Project-\>Add Active Unit to Project
4949- Run Tools-\>Quick Syntax Check or Run Build All to get started.
5050
5151#### Delphi VCL, Kylix CLX Sources in Lazarus
5252
5353When converting Delphi/Kylix sources, it is often useful to do a find declaration to see, what a specific function is doing. The Lazarus IDE can parse the Delphi/Kylix sources. To do this it needs some searchpaths and compiler settings. You can easily setup this in Environment-\>CodeTools Defines Editor-\>Insert Template
5454
5555### Conversion problems and solutions
5656
5757#### Delphi / Kylix file equivalents in Lazarus
5858
5959**Delphi / Kylix**
6060
6161**Description**
6262
6363**Lazarus**
6464
6565**Description**
6666
6767.pas
6868
6969.dfm/.xfm,
7070
7171.dcu/.dpu,
7272
7373.dpr(main project file),
7474
7575.res,
7676
7777.dof/.kof
7878
7979---
8080
8181---
8282
8383---
8484
8585Delphi Source File, Delphi Form,
8686
8787Delphi Compiled Unit,
8888
8989Delphi Project,
9090
9191Windows Resource File,
9292
9393Delphi Option File
9494
9595.pas, .pp .lfm,
9696
9797.o,
9898
9999.lpr
100100
101101---
102102
103103---
104104
105105.lrs,
106106
107107.lpi(main project file),
108108
109109.ppu
110110
111111Pascal unit file,
112112
113113Form data file,
114114
115115Compiled unit file,
116116
117117Project file,
118118
119119Resource file,
120120
121121Project options file,
122122
123123Lazarus resource file,
124124
125125Lazarus project information file,
126126
127127FPC unit description file
128128
129129So a Delphi .dcu file roughly corresponds to a FPC .o and .ppu together in one file. The .PPU is mostly the header(interface) part, the .o mostly the implementation part. Main exceptions are inlined functions, that in to-be-inlined form are in the .ppu.
130130
131131#### Converting Delphi projects/forms/units to Lazarus
132132
133133Use the Delphi converter in new Lazarus version to convert automatically. It does most of the things explained later on this page. More information here: [[Delphi Converter in Lazarus]]
134134
135135The following text explains the differences between Delphi and Lazarus and how to convert manually.
136136
137137#### Selecting the right compiler mode
138138
139139The [[Free Pascal]] Compiler supports 5 different pascal modes. For example TP for turbo pascal, lets you compile turbo pascal units. There is also a DELPHI compatibility mode that can be set to make existing code easier to convert. Lazarus prefers the OBJFPC mode, which almost equals the DELPHI mode, but is less ambiguous than the Delphi syntax. Here are the important points:
140140
141141The mode can be selected at command line or at the start of the source. Using the command line has the advantage, that you don't need to change the source, but the disadvantage, that others must be told.
142142
143143Most Delphi units can be compiled by the [[Free Pascal]] compiler by adding:
144144
145145``` pascal
146146{$IFDEF FPC}
147147 {$MODE DELPHI}
148148{$ENDIF}
149149```
150150
151151right after the unit name.
152152
153153For more details about [[Free Pascal]] modes see the [Free Pascal Documentation](http://www.freepascal.org/docs-html/prog/progap4.html#progse62.html)
154154
155155#### Cross-Platform considerations
156156
157157- Inline assembler is always a problem because it will bind the code to the Intel architecture. Some developers do algorithm prototypes in Pascal and ifdef the their optimized assembler. Fortunately TurboPower did this in numerous places with their code. If this is the case with the package you're converting, throw the switch back to Pascal.
158158- Don't reference specific memory location like the BIOS data area. Find out what the code needs and try to find a cross platform alternative.
159159- Don't do processor specific tricks (like using the Intel TSC) without enclosing your code in an ifdef for the platform the code needs... and providing an alternative for environments that don't have the hardware capability.
160160- If you need some OS specific code, then you can use IFDEFs. See below for a list of macros.
161161
162162#### Useful compiler variables / defines / macros
163163
164164To write code, that behaves on different systems differently, you can use the
165165
166166{\$IFDEF Name}
167167
168168directives.
169169
170170- {\$IfDef FPC}
171171
172172This variable is defined, when using the FPC compiler. Useful to write code, that works with FPC and Delphi. For compatibility reasons FPC defines the DELPHI macro in mode Delphi. So you can **not use {\$IFNDEF DELPHI}**.
173173
174174- {\$IfDef FPC_OBJFPC}
175175
176176This variable is defined when using mode OBJFPC and can be a substitute for {\$IFNDEF Delphi} for e.g. the @ differences
177177
178178- {\$IfDef LCL}
179179
180180This variable is defined, when using the LCL package. Useful to write code, that works with the LCL and Delphi.
181181
182182- {\$IfDef LCLGtk}
183183
184184 ,
185185
186186 {\$IfDef LCLWin32}
187187
188188 ,
189189
190190 {\$IfDef LCLQt}
191191
192192 , ...
193193
194194This variable is defined, when using the LCL package and the specific [[Widgetset|widgetset]] is currently used. Useful to write code, that works with the LCL on a specific platform.
195195
196196- {\$IfDef Unix} // for Linux, BSD, macOS, Solaris
197197
198198 ,
199199
200200 {\$IfDef Win32}
201201
202202 ,
203203
204204 {\$IfDef Linux}
205205
206206 // for Linux,
207207
208208 {\$IfDef Darwin}
209209
210210 // macOS,
211211
212212 {\$IfDef WinCE}
213213
214214 // for WinCE,...
215215
216216Defined by FPC for the current Target OS. Delphi defines "Linux", "Win32" and "MSWindows". [[Free Pascal]] runs on much more platforms and so it is recommended to use the more general items. For example "Unix" is defined for Linux, FreeBSD, NetBSD and OpenBSD, where Lazarus already runs. Use for code that should work with Delphi and FPC:
217217
218218``` pascal
219219{$IFDEF Linux}
220220 {$DEFINE Unix}
221221{$ENDIF}
222222```
223223
224224to work around this for Kylix.
225225
226226- {\$IfDef ENDIAN_BIG}
227227
228228This macro is defined on big endian processors such as the PowerPC as used, a.o., in older Apple computers. Their byte order is the reverse of that of Intel compatible processors.
229229
230230- {\$IfDef ENDIAN_BIG}
231231
232232For more details see the [Free Pascal Documentation](http://www.freepascal.org/docs-html/prog/prog.html#QQ2-23-21).
233233
234234#### 32bit / 64 bit support
235235
236236Pointers under 64bit need 8 bytes instead of 4 on 32bit. The 'Integer' type remains for compatibility 32bit. This means you can no longer typecast pointers into integers and back. FPC defines two new types: PtrInt and PtrUInt. PtrInt is a 32bit signed integer on 32 bit platforms and a 64bit signed integer on 64bit platforms. The same for PtrUInt, but *unsigned* integer instead. Use for code that should work with Delphi and FPC:
237237
238238``` pascal
239239{$IFNDEF FPC}
240240type
241241 PtrInt = integer;
242242 PtrUInt = cardinal;
243243{$ENDIF}
244244```
245245
246246Replace all **integer(SomePointerOrObject)** with **PtrInt(SomePointerOrObject)**.
247247
248248For more information see [[Multiplatform Programming Guide]].
249249
250250#### Finding a missing identifier
251251
252252There are differences in how the LCL is organized when compared to the Delphi VCL. If you get a "not found" compiler error about a major class or identifier, the chances are good that it's in a different unit. A complete cross reference can be found by grep'ing lazarus/docs/xml or the lcl subdirectory.
253253
254254For example the commonly used tbutton typically throws an error in Delphi code because it's located in a unit named buttons.pp. The following command finds the correct unit very quickly (in the lazarus source directory):
255255
256256``` bash
257257grep -in ' tbutton =' lcl/*
258258```
259259
260260#### Major unit differences between Lazarus and Delphi
261261
262262**Please add to this topic!**
263263
264264- Windows-\>Interfaces, LCLIntf, LCLType, LCLProc, ...)
265265
266266As the LCL is not windows specific, the code that is in the Delphi Windows unit for directly accessing the Win32 API is abstracted into separate interfaces, which can be accessed from the LCLIntf unit. Keep in mind, that Lazarus does not emulate win32, so many functions are missing and some do not work as their win32 counterparts. These functions only exist for Delphi compatibility and should only be used for quick & dirty porting. LCL also breaks out many of the types, so often LCLType is required. LCLProc also contains a few functions which can be useful for lower level handling such as "FreeThenNil" as is in Delphi 5 and higher, "DeleteAmpersands" to remove additional ampersands from a string for controls(& vs && etc). The Interfaces unit needs to be included in the .lpr file to initialize the appropriate widgetset.
267267
268268- Messages-\>LMessages
269269
270270TControl Messages for win32 event callbacks of the format WM_CALLBACK and the structs associated with them are often found in the Messages unit in Delphi. In the LCL these types of messages and there structs are usually found in LMessages, usually with name changes of WM to LM, so for instance WM_MOUSEENTER becomes LM_MOUSEENTER, and TWMMouse becomes TLMMouse.
271271
272272- Graphics, Controls-\>GraphType, GraphMath, Graphics, Controls
273273
274274To simplify some things and break complexity of circles between units, a few types have been abstracted into a shared unit called GraphType, which includes things, which in Delphi are located in Graphics or Controls, for instance the bvNone etc of panels. So sometimes you have to include it. Also a unit which, although incompatible with Delphi, adds other useful functionality is GraphMath, which adds a TFloatPoint for precision, misc routines for dealing with beziers, lines, and arcs, as well as some operator overloading for use with TPoints and TRect, such as for instance Point1 := Point2 + Point3, and comparing two rects like if (rect1 = rect2) then ...
275275
276276- Mask-\>MaskEdit
277277
278278For more intelligent naming considerations, the unit for TMaskEdit is called \[MaskEdit\|\] instead of the slightly more nebulous Mask as in many versions of Delphi.
279279
280280- StdCtrls-\>StdCtrls,Buttons
281281
282282In many version of Delphi TButton is located in StdCtrls, while TSpeedButton and TBitBtn are in Buttons. For consistency and simplicity the LCL puts all button types in Buttons, which can occasionally break code conversion, so it is always a good idea to include.
283283
284284#### Property and method differences Delphi -\> FPC/LCL
285285
286286- TBitmap contains a canvas in the LCL
287287- [[Lazarus Faq|Lazarus_Faq#Why are TForm.ClientWidth.2FClientHeight the same as TForm.Width.2FHeight]]
288288
289289#### Semantical differences
290290
291291##### Order of parameter evaluation
292292
293293Delphi guarantees that all parameters are evaluated from left to right. FPC makes no such guarantee, and can evaluate parameters in any order it wants in order to generate optimal code.
294294
295295##### Nested procedures/functions as procedural variables
296296
297297Delphi passes the framepointer of the parent procedure always on the stack, and has the caller remove it again. This means that as long as you do not access variables from a parent procedure, you can pass the address of a nested function to another function which then can call it like any other procedural variable.
298298
299299FPC on the other hand always passes the framepointer of the parent procedure as a hidden first parameter according to the current calling convention, which means that if you call a nested procedure like a regular procedural variable, all parameters will be "shifted" one position.
300300
301301In short, do not call nested procedures via procedural variables.
302302
303303##### Ref count release
304304
305305Documented behaviour in both Delphi and FPC is that temporary variables stay allocated till after the statement of last use. (so if an interface is used in a parameter declaration, it is earliest released after that whole procedure/method call statement has finished).
306306
307307However in practice FPC often indeed decreases the refcount the very next statement, while Delphi tends to wait till the end of procedures. Or, in very large procedures, till the end of a large block.
308308
309309Both are valid choices though, and fixating this behaviour would hem in the codegeneration and optimizer too much, and it won't changed.
310310
311311This can occasionally cause apparently working Delphi code that mixes object and interface references to fail, and is a typical case of seemingly working code not being correct and depending on implementation choices. The Delphi documentation doesn't make any such guarantees.
312312
313313#### Syntax differences
314314
315315**Please add to this topic!**
316316
317317Because of the inherent strictness in FPC, some syntax changes are necessary, even though
318318
319319{\$Mode Delphi}
320320
321321does allow more laziness like Delphi does. For this reason complying as much with the syntax rules of
322322
323323{\$Mode ObjFPC}
324324
325325as possible is highly recommended, even when the codebase is still going to be shared between Delphi and the LCL. Some of these are simply better coding practices, and sometimes because Delphi mode is not entirely accurate, or in a few instances Delphi acceptible code does not function as expected with FPC, even though it might compile. To that end even though not all such are strictly required, the following list of changes should be considered mandatory :
326326
327327##### When assigning an event handling entry point, prefix it with an "@"
328328
329329For instance, you might assign a button [[callback]] manually.
330330
331-```
331+```text
332332With the Delphi code compiled under Lazarus You will get the error message
333333"Wrong number of parameters specified for call to "SomeFunction" "
334334```
335335
336336**Delphi**
337337
338338**OBJFPC**
339339
340340**both**
341341
342342``` pascal
343343begin
344344 if not Assigned(MyButton.OnClick) then
345345 MyButton.OnClick:= SomeFunction;
346346 //@ not required
347347 //more code...
348348end;
349349```
350350
351351``` pascal
352352begin
353353 if not Assigned(MyButton.OnClick) then
354354 MyButton.OnClick:= @SomeFunction;
355355 //@ IS required
356356 //more code...
357357end;
358358```
359359
360360\|
361361
362362``` pascal
363363begin
364364 if not Assigned(MyButton.OnClick) then
365365 MyButton.OnClick:= {$IFDEF FPC_OBJFPC}@{$ENDIF}SomeFunction;
366366 //@ is only required under mode OBJFPC - but not allowed under Delphi
367367 //more code...
368368end;
369369```
370370
371371Note that this behavior of the compiler can also be influenced using the CLASSICPROCVARS modeswitch.
372372
373373##### When calling a procedure variable use this syntax: theprocname()
374374
375375In Delphi there is no difference between a function result and a variable, however there is in FPC, so to call a function, even if it has no parameters, you must append parenthesis.
376376
377377``` pascal
378378With the Delphi code compiled under Lazarus You will get the error message
379379"Incompatible types: got "<procedure variable type of function:DWord;StdCall>" expected "LongWord" "
380380```
381381
382382**Delphi**
383383
384384**OBJFPC**
385385
386386**both**
387387
388388``` pascal
389389With (SomeObject) do
390390begin
391391 If Assigned(OnMyCallback) then
392392 OnMyCallback;
393393 //parenthesis not required
394394end;
395395```
396396
397397``` pascal
398398With (SomeObject) do
399399begin
400400 If Assigned(OnMyCallback) then
401401 OnMyCallback();
402402 //parenthesis required
403403end;
404404```
405405
406406\|
407407
408408``` pascal
409409Simply use the OBJFPC way, with brackets:
410410
411411 OnMyCallback();
412412
413413Delphi accepts this, too.
414414```
415415
416416##### When accessing values in a pointer to a record you must dereference first
417417
418418In Delphi it is not required to de-reference a pointer to a record to access values within it, it can, in fact, be treated just like the record itself, or any other object. In FPC it must be first de-referenced.
419419
420-```
420+```text
421421With the Delphi code compiled under Lazarus You will get the following messages :
422422"Error: Illegal qualifier"
423423"Hint: may be pointer dereference is missing"
424424```
425425
426426**Delphi**
427427
428428**OBJFPC**
429429
430430**both**
431431
432432``` pascal
433433Function GetSomeValue(ARecord: PMyRecord):Integer;
434434begin
435435 If Assigned(ARecord) then
436436 Result:=ARecord.SomeValue
437437 else
438438 Result:=0;
439439end;
440440```
441441
442442``` pascal
443443Function GetSomeValue(ARecord: PMyRecord):Integer;
444444begin
445445 If Assigned(ARecord) then
446446 Result:=ARecord^.SomeValue
447447 else
448448 Result:=0;
449449end;
450450```
451451
452452\|
453453
454454``` pascal
455455Simply use the OBJFPC way, with ^ :
456456
457457 Result:=ARecord^.SomeValue
458458
459459Delphi accepts this, too.
460460```
461461
462462Note that the behavior of the compiler with regards to (auto) de-referencing pointers can also be influenced using the AUTODEREF modeswitch.
463463
464464##### When accessing chars of an indexed string Property of an object, it must be enclosed in parentheses
465465
466466With Delphi it is possible to treat a Property exactly like some other const or var, e.g. even up to accessing individual chars of a string directly, while this is not always possible in FPC, specifically for indexed properties. Instead it must be enclosed in parentheses, to make distinct. While this may not always hold true it is probably a good practice to consider anyway. For example
467467
468468**Delphi**
469469
470470**OBJFPC**
471471
472472``` pascal
473473Type TSomeComponent=class(TComponent)
474474 //More code...
475475Published
476476Property MyString:String index 3 read GetMyString;
477477//More code...
478478End;
479479
480480var
481481 MyChar:char;
482482begin
483483 If Length(MyString)>2 then
484484 //no parenthesis needed
485485 MyChar:= MyString[3];
486486 //More code...
487487end;
488488```
489489
490490``` pascal
491491Type TSomeComponent=class(TComponent)
492492//More code...
493493Published
494494Property MyString:String index 3 read GetMyString;
495495//More code...
496496End;
497497
498498var
499499 MyChar:char;
500500begin
501501 If Length(MyString)>2 then
502502 //parenthesis sometimes needed
503503 MyChar:= (MyString)[3];
504504 //More code...
505505end;
506506```
507507
508508##### You must typecast pointers to actual type when using with var or function of that type
509509
510510Sometimes in Delphi you will have a null pointer variable representing an object. While it might seem a complex situation, it is oddly quite common especially in large component packs as a method of preventing too many circular includes between objects in different units. In Delphi it is then possible to send this null pointer to a function expecting that object, without bothering to typecast to actual type, in fpc you must typecast.
511511
512512For example -
513513
514514**Delphi**
515515
516516**OBJFPC**
517517
518518``` pascal
519519Unit 1
520520 Type
521521 TSomeObject=class(TComponent)
522522 //More code...
523523 End;
524524
525525 Procedure DoSomething(Value: TSomeObject);
526526 Function GetSomeObject: TSomeObject;
527527
528528Unit 2
529529 Type
530530 TSomeComponent=class(TComponent)
531531 //More code...
532532 Published SomeObject: Pointer;
533533 //More code...
534534 End;
535535
536536Application
537537var
538538 MyComponent: TSomeComponent;
539539begin
540540 MyComponent.SomeObject:=GetSomeObject;
541541 //More code...
542542 DoSomething(MyComponent.SomeObject);
543543end;
544544```
545545
546546``` pascal
547547Unit 1
548548 Type
549549 TSomeObject=class(TComponent)
550550 //More code...
551551 End;
552552
553553 Procedure DoSomething(Value: TSomeObject);
554554 Function GetSomeObject: TSomeObject;
555555
556556Unit 2
557557 Type TSomeComponent=class(TComponent)
558558 //More code...
559559 Published SomeObject: Pointer;
560560 //More code...
561561 End;
562562
563563Application
564564var
565565 MyComponent: TSomeComponent;
566566begin
567567 MyComponent.SomeObject:=Pointer(GetSomeObject);
568568 //More code...
569569 DoSomething(TSomeObject(MyComponent.SomeObject));
570570end;
571571```
572572
573573#### Resources
574574
575575> **Note:** The section below may not be necessary. Any recent version of Lazarus directly supports .res files. The Windows Lazarus installer includes a resource compiler which supports .rc files. On *nix, please make sure windres is installed so you can use .rc files. See <http://wiki.lazarus.freepascal.org/Lazarus_Resources#FPC_resources>
576576
577577Delphi resource files are win32 specific and not compatible with Lazarus, so you'll have to recreate and compile them using the lazres tool. Lazres can be found in the lazarus/tools subdirectory. If you've downloaded the Lazarus sources, you'll need to compile it first.
578578
579579- cd lazarus/tools
580580- make install
581581
582582To add a resource to your application:
583583
584584- lazres myresource.lrs mypix.xpm anotherpix.xpm
585585- Add the LResources unit to your Uses clause
586586- Include the .lrs file you created under the initialization block
587587
588588Example:
589589
590590``` pascal
591591function TForm1.LoadGlyph(const GlyphName: String): TBitMap;
592592begin
593593 Result:= TPixmap.Create;
594594 Result.LoadFromLazarusResource(GlyphName);
595595end;
596596//More code...
597597begin
598598 Speedbutton1.glyph:= LoadGlyph('mypix');
599599 //More code...
600600end;
601601
602602initialization
603603{$I unit1.lrs}
604604{$I myresource.lrs}
605605end.
606606```
607607
608608### Another method to convert a Delphi or Kylix project to Lazarus
609609
610610- Rename or copy all .dfm or .xfm files to .lfm (Very old Delphi versions do not produce a text-based .dfm file. The convert utility, if present in the \bin folder can be used to covert the .dfm first))
611611- Rename or copy .dpr file to .lpr
612612- Make all necessary changes to .lpr file:
613613
6146141. Add {\$mode delphi}{\$H+} or {\$mode objfpc}{H+} directives
6156152. Add 'Interfaces' to uses clause
6166163. Comment out or delete {\$R *.res} or directive if needed
617617
618618- Make necessary changes to all .pas unit files:
619619
6206201. Add {\$mode delphi}{\$H+} or {\$mode objfpc}{H+} directives
6216212. Add 'LResources' - to do: check if this is still needed for any vaguely new Lazarus version
6226223. If the form has buttons, add 'Buttons' to uses clause
6236234. Comment out or delete {\$R *.dfm} or {\$R *.xfm} directive
6246245. Add 'Initialization' section at the end of each unit file, and add {\$I unitname.lrs} directive in it
625625
626626- Select Project-\>New Project from file
627627- Select the .lpr file
628628- In the 'Create a new project' window, choose 'Application'
629629- Build project and make further necessary corrections to get proper compilation. At this point the .lpi file is generated automaticaly. You may get 'Error reading Form' messages, click on 'Continue Loading' if you do.
630630- Save all, and you have a Lazarus project :-)
631631
632632## Getting Help
633633
634634If you encounter a problem during conversion that you just can't solve, there are a wide variety of places to get help.
635635
636636### Documentation
637637
638638For pure Object Pascal and FPC issues
639639
640640The best place to start is the Free Pascal [Documentation](http://www.freepascal.org/docs-html/) by Michaël Van Canneyt and Florian Klämpfl.
641641
642642For more Lazarus oriented problems
643643
644644The Lazarus Project Documentation in the Lazarus-CCR Knowledgebase [[Main Page]] is the next place to look.
645645
646646### Peer support
647647
648648Mailing lists
649649
650650You can post a question on any of the [mailing lists for the Free Pascal Compiler](http://www.freepascal.org/maillist.html) or the [FPC/Lazarus forums](http://forum.lazarus.freepascal.org/index.php?action=forum) where a lot of experts are subscribed.
651651
652652If you have access to IRC:
653653
654654On irc.freenode.net: [\#fpc](irc://irc.freenode.net/fpc) for FPC, or [\#lazarus-ide](irc://irc.freenode.net/lazarus-ide) for Lazarus
655655
656656### Knowledge bases
657657
658658There are some outstanding search and knowledge bases online that can also be a great help for learning new techniques and solving problems:
659659
660660- Tamarack Associates operates a fast \[ <http://codenewsfast.com/> search\] engine specifically for the Borland usenet archives.
661661- Mer Systems Inc. provides a similar search [engine](http://www.mers.com/searchsite.html).
662662- Another outstanding source of information along with a sitewide [search](http://www.efg2.com/Lab/search.htm) capability is Earl F. Glynn's Computer Lab and Reference [Library](http://www.efg2.com/).
663663
664664## Packaging and Releasing your component
665665
666666### Creating a Lazarus package for your component(s)
667667
668668Creating a package makes installing the code you've converted a much easier process... especially if you're providing more than one component. Mattias Gärtner has written an overview of [[Lazarus Packages]] that should be read before beginning this process.
669669
670670### Documentation
671671
672672The purpose of this site and the wiki format is to make the generation of professional documentation an easy and quick process. The wiki also makes it possible to see the results of your posting immediately and make any changes you'd like in real time.
673673
674674Using the Lazarus-CCR wiki to create nice looking documentation is very easy. If you've never used wiki markup before, you can get familiar with it in the [[Sand Box]] practice area.
675675
676676### Creating a Code Release Page
677677
678678The Code Release Page contains vital information about your component that a potential downloader will need to know, such as license, intended platform, status (alpha, beta, stable...), where to download it, who wrote it, is support available... etc.
679679
680680The following procedure will let you create a Code Release Page with your browser:
681681
682682- Go to the [[Release new component]]
683683- Type the name of your component in the textbox and click on *Create Article*
684684- Fill in the template and hit save.
685685- Edit the [[Components and Code examples]] page and add the link to your newly created page to the "Released Components" section. Save the modified page.
686686
687687### Submitting the component
688688
689689If you're a release technician on the project, upload your component to the SourceForge File Release System and add it to the list of release packages. Otherwise send it to one of the project administrators (Tom Lisjac or Vincent Snijders) and we'll add it to the repository. Before we upload it to SourceForge, you have to create a *Code Release Page* to describe your component. You can use the [[Release new component]] page, to start creating such a page.
690690
691691If you think you need to continue to develop on the component, we can also put it into SVN so you'll continue to have access to it. If we get tired from committing your patches, we will give you write access to the SVN, so you can commit your patches yourself. For details see [[Using the Lazarus-ccr SVN repository]].
692692
693693## See also
694694
695695- [[Lazarus For Delphi Users]]
696696- [[Delphi language features missing from the Free Pascal Compiler]]
697697
698698---
699699*From the Free Pascal wiki, page "Code Conversion Guide", as it stood on 2023-11-06 after a change by Bart, 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