Difference between revisions of "Delphi Converter in Lazarus"

From Lazarus wiki
Jump to navigationJump to search
m (→‎Type replacement: minor typo correction)
 
(32 intermediate revisions by 3 users not shown)
Line 20: Line 20:
 
* '''{$R *.DFM}''' is replaced with '''{$R *.lfm}''' if the form file is renamed and converted. Conditional compilation is used if the target is '''Lazarus and Delphi'''.
 
* '''{$R *.DFM}''' is replaced with '''{$R *.lfm}''' if the form file is renamed and converted. Conditional compilation is used if the target is '''Lazarus and Delphi'''.
  
* Unit names in Uses section and include file names are fixed to match the real case sensitive name found in the file system. This is needed for case sensitive file systems.
+
* Unit names in Uses section and include file names are fixed to match the real case sensitive names found in the file system. This is needed for case sensitive file systems.
  
 
* Some unit names in Uses section are either replaced or removed.
 
* Some unit names in Uses section are either replaced or removed.
Line 26: Line 26:
 
* Some Delphi types are replaced with "fall-back" LCL types (same as in form files).
 
* Some Delphi types are replaced with "fall-back" LCL types (same as in form files).
  
* Called function names are replaced.
+
* Some function names called in the code are replaced.
  
 
== Form file ==
 
== Form file ==
  
* Older Delphi versions used a binary format for .dfm form files. The converter always converts them to ascii text format.
+
* Older Delphi versions used a binary format for .dfm form files. They are always converted to ascii text format.
  
* .dfm form file is renamed or copied to .lfm and converted as needed. There is also an option to use the same Delphi form file directly. See paragraph '''Target''' below.
+
* .dfm form file is renamed or copied to .lfm and converted as needed. There is also an option to use the same Delphi form file directly. See section '''Target''' below.
  
 
* Unknown properties are removed.
 
* Unknown properties are removed.
Line 38: Line 38:
 
* Some Delphi types are replaced with "fall-back" LCL types (same as in unit files).
 
* Some Delphi types are replaced with "fall-back" LCL types (same as in unit files).
  
* Coordinate offset adjustment for controls inside visual containers.
+
* Top and Left coordinate offset adjustment for controls inside visual containers.
  
 
= Settings dialog =
 
= Settings dialog =
  
After selecting an entry from the Tools menu, and then selecting the unit / project / package to convert,
+
After selecting an entry from the Tools menu, and then selecting the unit / project / package to convert, the user is presented with a settings dialog.  
the user is presented with a settings dialog. It allows to configure many details of conversion.
+
All settings are saved in file '''delphiconverter.xml''' in local Lazarus configuration directory.
 +
The dialog allows to configure many details of conversion:
  
'''Project Path''' shows the selected path.
+
* '''Project Path''' shows the selected path.
  
'''Make backup of changed files''' saves the original files to directory ConverterBackup below the selected directory.
+
* '''Make backup of changed files''' saves the original files to directory ConverterBackup under the selected directory.
  
'''Keep converted files open in editor'''. When checked, the converted unit files remain open after conversion.
+
* '''Keep converted files open in editor'''. When checked, the converted unit files remain open after conversion.
  
 
Rest of the dialog settings are covered below.
 
Rest of the dialog settings are covered below.
  
  
[Pic]
+
[[Image:ConvertSettings.png|Picture of settings dialog of Delphi converter]]
  
 
== Target ==
 
== Target ==
Line 60: Line 61:
 
The conversion target is defined in settings dialog. It can be:
 
The conversion target is defined in settings dialog. It can be:
  
* '''Lazarus''' -- A one way conversion. The goal is to create a multi-platform Lazarus program which does not need to be Delphi compatible.
+
* '''Cross-platform''' -- Replace Windows specific units with their cross-platform equivalents.
  
* '''Lazarus for Windows only''' -- Convert for Lazarus but leave Windows dependent unit names and functions as they are.
+
* '''Support Delphi''' -- Tries to make units compatible with both Delphi and Lazarus by using {$IFDEF...} in Uses section. The Delphi form file .dfm is copied to Lazarus form file .lfm and converted.
  
* '''Lazarus and Delphi''' -- Tries to make the unit compatible with both Delphi and Lazarus by using {$IFDEF...} in Uses section and in form file include directive. The Delphi form file .dfm is copied to Lazarus form file .lfm and converted.
+
* '''Use the same DFM form file''' -- The Delphi form file .dfm is used also with Lazarus. It is not modified except for converting binary format to ascii text format when needed.
 
+
However maintaining the file later in both Delphi and Lazarus is problematic because components have slightly different properties.
* '''Lazarus and Delphi with same DFM file''' -- The Delphi form file .dfm is used also with Lazarus. It is not modified except for converting binary format to ascii text format.
 
  
 
== Unit name replacement and removal ==
 
== Unit name replacement and removal ==
Line 79: Line 79:
 
then replace with the saved part. In essence this removes 'Q' in the beginning.
 
then replace with the saved part. In essence this removes 'Q' in the beginning.
  
"Replace Automatically" switches between automatic and interactive unit replacement.
+
Replacement can be interactive or automatic. When interactive, the user can edit the replacements before they are applied.
When interactive, the user can edit the replacements before they are applied.
 
  
 
If there are still missing units after the replacement, the user will be asked about them in any case.
 
If there are still missing units after the replacement, the user will be asked about them in any case.
 
He can then choose to comment them out or search for their unit paths.
 
He can then choose to comment them out or search for their unit paths.
 +
 +
[[Image:ConvertUnitsNotFound.jpg|Picture of Units Not Found dialog of Delphi converter]]
  
 
== Unknown property removal ==
 
== Unknown property removal ==
  
Not all Delphi component properties are implemented in LCL components. These properties can be removed. There is a system in LCL where non-existent properties are registered and the form loader ignores them. The converter also removes them, automatically or interactively. It will become optional later.
+
Not all Delphi component properties are implemented in LCL components. These properties can be removed. There is a system in LCL where non-existent properties are registered and the form loader ignores them. The converter also removes them, automatically or interactively.
 +
The interactive removal currently happens in the same dialog that is used for component type replacements (see below). The property can be replaced, too, but that is usually not needed.
  
 
== Type replacement ==
 
== Type replacement ==
Line 96: Line 98:
 
It is configurable, too, see "Type Replacements" in settings dialog.
 
It is configurable, too, see "Type Replacements" in settings dialog.
  
The same regular expression syntax than for unit replacement is supported here.
+
The same regular expression syntax as used in unit name replacement is supported here.
 +
 
 +
The types are replaced in both the Pascal source file and the form file (.lfm).
 +
The replacement works also in a nested component structure where a component of replaced type has child components that must also be replaced.
  
The types are replaced in both the pascal source file and the form file (.lfm).
 
 
Different properties between the original component and the replacement component can cause problems after conversion.
 
Different properties between the original component and the replacement component can cause problems after conversion.
There is no easy solution for it.
+
There is no easy solution for this.
Best solution would be to make more Delphi compatible components and port all 3rd party components for Lazarus.
+
 
 +
The best solution would be to make more Delphi compatible components and port all 3rd party components to Lazarus.
 
Because of these potential problems the type conversion is always interactive.
 
Because of these potential problems the type conversion is always interactive.
  
== Function replacement ==
+
[[Image:ConvertFixLfm.jpg|Picture of Fix LFM dialog of Delphi converter]]
 +
 
 +
== Function call replacement ==
  
Some Windows-only function calls in the source code can be replaced with a functionally similar FPC / Lazarus library function.
+
Some Windows-only function calls in the source code can be replaced with a functionally similar RTL / LCL library function calls.
 
It is configurable, see "Function Replacements" in settings dialog.
 
It is configurable, see "Function Replacements" in settings dialog.
  
There is a category defined for each function. The replacement can be enabled or disabled for each category.
+
There is a category defined for each function. The replacement can be enabled or disabled by category.
 
For example there is "UTF8Names" category for file operation related functions.
 
For example there is "UTF8Names" category for file operation related functions.
  
Line 122: Line 129:
 
== Coordinate offsets ==
 
== Coordinate offsets ==
  
Components inside a visual container have different meaning for Top and Left coordinates between Delphi and Lazarus.
+
In Delphi and Lazarus, components have different meaning for Top and Left coordinates when they are inside a visual container.
 
In Delphi the coordinates are relative to container's Top and Left.
 
In Delphi the coordinates are relative to container's Top and Left.
 
In Lazarus they are relative to container's client area which leaves out the border.
 
In Lazarus they are relative to container's client area which leaves out the border.
TGroupBox has the biggest problem because it has a title text on the border.
+
It causes the most visible problem for TGroupBox because it has a title text on the border.
  
 
Subtracting an offset from the coordinates makes the form layout look the same as it looked in Delphi.
 
Subtracting an offset from the coordinates makes the form layout look the same as it looked in Delphi.
Line 132: Line 139:
 
= Issues =
 
= Issues =
  
...
+
When a Delphi program contains Windows API calls which are not ported in RTL/LCL, there is no automatic way to convert it.
 +
Other Windows specific technologies like OLE cause the same problem.
 +
 
 +
Database connections often require changes. Either the DB or the connection component is not compatible.
 +
 
 +
Another problem are some libraries which are not compatible with Delphi libraries. For example XML is used in a slightly different way. Maybe the converter can be improved in this area in the future.
 +
 
 +
As mentioned earlier, Delphi components that don't exist in Lazarus/LCL cause problem, even if they are replaced with a fall-back component type, because they have different properties.
 +
 
 +
Yet, if the program uses only VCL classes and functions, there is a big chance for the conversion to succeed.
 +
 
 +
[[Category:Lazarus]]

Latest revision as of 08:20, 22 May 2013

A Delphi project, Delphi package and a single unit file can be converted for Lazarus. The entries can be found in Lazarus Tools menu:

  • Convert Delphi unit to Lazarus unit ...
  • Convert Delphi project to Lazarus project ...
  • Convert Delphi package to Lazarus package ...

There is also:

  • Convert binary DFM file to text LFM and check syntax ...

which is seldom needed because the DFM form file is always converted while converting a unit.

Conversions

Here the different conversions are listed briefly. See the sections below for details.

Unit file

  • All unit source files get a {$mode delphi} directive. It makes the compiler support language syntax exactly like Delphi has it. This makes sense because we are converting a Delphi program after all. The user can take advantage of {$mode objfpc} features later if he wants, by making the necessary changes manually.
  • {$R *.DFM} is replaced with {$R *.lfm} if the form file is renamed and converted. Conditional compilation is used if the target is Lazarus and Delphi.
  • Unit names in Uses section and include file names are fixed to match the real case sensitive names found in the file system. This is needed for case sensitive file systems.
  • Some unit names in Uses section are either replaced or removed.
  • Some Delphi types are replaced with "fall-back" LCL types (same as in form files).
  • Some function names called in the code are replaced.

Form file

  • Older Delphi versions used a binary format for .dfm form files. They are always converted to ascii text format.
  • .dfm form file is renamed or copied to .lfm and converted as needed. There is also an option to use the same Delphi form file directly. See section Target below.
  • Unknown properties are removed.
  • Some Delphi types are replaced with "fall-back" LCL types (same as in unit files).
  • Top and Left coordinate offset adjustment for controls inside visual containers.

Settings dialog

After selecting an entry from the Tools menu, and then selecting the unit / project / package to convert, the user is presented with a settings dialog. All settings are saved in file delphiconverter.xml in local Lazarus configuration directory. The dialog allows to configure many details of conversion:

  • Project Path shows the selected path.
  • Make backup of changed files saves the original files to directory ConverterBackup under the selected directory.
  • Keep converted files open in editor. When checked, the converted unit files remain open after conversion.

Rest of the dialog settings are covered below.


Picture of settings dialog of Delphi converter

Target

The conversion target is defined in settings dialog. It can be:

  • Cross-platform -- Replace Windows specific units with their cross-platform equivalents.
  • Support Delphi -- Tries to make units compatible with both Delphi and Lazarus by using {$IFDEF...} in Uses section. The Delphi form file .dfm is copied to Lazarus form file .lfm and converted.
  • Use the same DFM form file -- The Delphi form file .dfm is used also with Lazarus. It is not modified except for converting binary format to ascii text format when needed.

However maintaining the file later in both Delphi and Lazarus is problematic because components have slightly different properties.

Unit name replacement and removal

When a unit listed in Uses section is not found, it can be replaced or removed. The replacements are configurable, see "Unit Replacements" in settings dialog. An empty "New name" means removal. For example by default "Windows" is replaced with "LCLIntf, LCLType, LMessages".

The replacement supports regular expression syntax. For example:

  • ^Q(.+) --> $1

means something like: match a string starting with 'Q', followed by anything, and save the part after 'Q', then replace with the saved part. In essence this removes 'Q' in the beginning.

Replacement can be interactive or automatic. When interactive, the user can edit the replacements before they are applied.

If there are still missing units after the replacement, the user will be asked about them in any case. He can then choose to comment them out or search for their unit paths.

Picture of Units Not Found dialog of Delphi converter

Unknown property removal

Not all Delphi component properties are implemented in LCL components. These properties can be removed. There is a system in LCL where non-existent properties are registered and the form loader ignores them. The converter also removes them, automatically or interactively. The interactive removal currently happens in the same dialog that is used for component type replacements (see below). The property can be replaced, too, but that is usually not needed.

Type replacement

Some Delphi components do not exist in LCL. Many 3rd party components also exist only for Delphi. Those types can be replaced with fall-back LCL types. For example:

  • TCoolBar --> TToolBar.

It is configurable, too, see "Type Replacements" in settings dialog.

The same regular expression syntax as used in unit name replacement is supported here.

The types are replaced in both the Pascal source file and the form file (.lfm). The replacement works also in a nested component structure where a component of replaced type has child components that must also be replaced.

Different properties between the original component and the replacement component can cause problems after conversion. There is no easy solution for this.

The best solution would be to make more Delphi compatible components and port all 3rd party components to Lazarus. Because of these potential problems the type conversion is always interactive.

Picture of Fix LFM dialog of Delphi converter

Function call replacement

Some Windows-only function calls in the source code can be replaced with a functionally similar RTL / LCL library function calls. It is configurable, see "Function Replacements" in settings dialog.

There is a category defined for each function. The replacement can be enabled or disabled by category. For example there is "UTF8Names" category for file operation related functions.

The syntax for replacements is:

  • FileExists --> FileExistsUTF8($1)

where ($1) means the first parameter from the original function call is used for replacement function. There is also a more advanced syntax available. Like this:

  • ShellExecute --> if $3 match ":/" then OpenURL($3); OpenDocument($3)

ShellExecute can map to 2 different LCL functions. The string after "match" keyword is again a regular expression. If it matches, the replacement right after it is used, otherwise the next replacement.

Coordinate offsets

In Delphi and Lazarus, components have different meaning for Top and Left coordinates when they are inside a visual container. In Delphi the coordinates are relative to container's Top and Left. In Lazarus they are relative to container's client area which leaves out the border. It causes the most visible problem for TGroupBox because it has a title text on the border.

Subtracting an offset from the coordinates makes the form layout look the same as it looked in Delphi. The offsets are defined in "Coordinate offsets" in settings dialog.

Issues

When a Delphi program contains Windows API calls which are not ported in RTL/LCL, there is no automatic way to convert it. Other Windows specific technologies like OLE cause the same problem.

Database connections often require changes. Either the DB or the connection component is not compatible.

Another problem are some libraries which are not compatible with Delphi libraries. For example XML is used in a slightly different way. Maybe the converter can be improved in this area in the future.

As mentioned earlier, Delphi components that don't exist in Lazarus/LCL cause problem, even if they are replaced with a fall-back component type, because they have different properties.

Yet, if the program uses only VCL classes and functions, there is a big chance for the conversion to succeed.