Using Delphi Packages

Elements allows you to reference and directly work with Delphi-compiled code and have access to the full Delphi type system and APIs from your projects on native Windows, Linux and macOS, on the Island platform.

This is achieved by importing Delphi package files (.dcp) into .fx files that make their content available to the Elements compiler. The resulting binary will then reference and depend on the used packages (.bpls).

This includes support for Delphi's base class libraries (including RTL, VCL, dbGo, FireMonkey and everything else), as well as third-party packages and even your own Delphi-compiled packages.

In Elements code, all types, globals and functions/procedures are directly accessible and usable as-is, underneath the Delphi namespace.


In order to use Delphi packages, you will need a copy and license of a version of Delphi of your choice installed on your system. If you are working on Mac or Linux, you can use a copy of Delphi installation's bin and lib folders for the SDK import, as outlined in the next step.

Support for Delphi packages is based on an imported "Delphi SDK", and tied to a single version of Delphi per project (i.e. you cannot mix binaries from different Delphi versions in the same application).

As of this writing, Elements support using libraries from Delphi 7 thru Delphi 11, but extensive testing on our side has bene limited to versions 10.3 and above.

Do note that platform and architecture support is limited for older Delphi versions. For example, Delphi only added support for arm64 macOS as late as Delphi 11, etc.

Importing a Delphi SDK

For legal and deployment licenses reason, Elements does not ship with binaries for the Delphi SDK, so the first step in using Delphi binaries is to import an SDK using the Water's "Import Delphi SDK" menu item, or the --import-delphi option of the EBuild command line tool.

Importing a Delphi SDK in Water

Simply select the "Import Delphi SDKs" option from the "Tools" menu, and Water will present a list of all supported versions of Delphi it finds installed on your system.

As you see in the screenshot above, Water shows you what platforms are supported (or have support installed) for each version of Delphi, and also which versions you already imported before. You would only need to reimport a version if you upgraded Delphi it to a new .x version, of if there have been fixes/improvements to the importer that yo want to benefit from.

Select the version(s) you would like to import, and click "Import Selected".

Import progress will show in the Build Log pane of Water, which will open automatically.

After the main import of each version/platform of the Delphi SDK, Water will also automatically build the Island.DelphiSupport support library for that version, downloading the source from GitHub if necessary.

Note: you will need to have an active Internet connection and have Git installed for this last step to succeed.

Importing a Delphi SDK with EBuild

From the command line, the Delphi SDK import can be done in three ways:

  • You can import support for all versions of Delphi installed on your local Windows system using the --import-delphi --import-all switches. This will check the Registry for all (known and supported) versions of Delphi, and import each in turn. This may take a very long time. You can add the --skip-existing option, if you installed new versions of Delphi, and don't want to reimport the ones already imported previously; otherwise they will all be (re-)imported.

  • Alternatively, you can specify a specific version of Delphi by name by specifying, e.g. --import-delphi "Delphi 11" (note the quotes to preserve the space). If the specified version is not found in the Registry, EBuild will list all versions if did find; if the specified version is not known/invalid/supported ("e.g. "Delphi 5" or "Delphi 27"), EBuild will list all versions it knows about.

  • Finally, you can manually point the importer to the root folder of a copy of Delphi (the folder that contains bin, lib, etc). This is useful if you have a manual Delphi install that is not registered in the Windows Registry, or if you copied these files over to a non-Windows system (Mac or Linux) to run the import.

The imported .fx files will be stored in a well-defined location1, grouped by Delphi version, platform, and architecture.

You can specify the --build-delphi-support command line switch to have EBuild automatically build the (required) Island.DelphiSupport support library.

Once imported, the Delphi SDK is usable from your Island projects.

Using a Delphi SDK

Using a Delphi SDK in your project is as simple as setting the "Delphi SDK" project setting to the name of Delphi SDK you have imported, for example <DelphiSDK>Delphi 11</DelphiSDK>. This setting will become available in the IDE for compatible Island project types, as soon as one or more Delphi SDK has been imported.

After setting this, a few things will happen automatically, in the IDE and during build:

  • Your project will get an implicit reference to Delphi.rtl.fx, the core package.
  • Your project will get an implicit reference to Island.DelphiSupport.fx, our small support library for interaction with Island RTL and Delphi's object model.
  • Your project will emit additional errors, if you are targeting architectures that your Delphi version does not support (e.g. 64-bit Windows or Linux before Delphi 10.4, macOS before Delphi 10.3 (which added 64bit support, a decade late) or Apple Silicon macOS before Delphi 11.

If necessary, you will need to set the Architecture Project Setting to limit your target architectures.

Delphi.rtl.fx contains the bulk of the basic Delphi APIs. You can add references to any of the other Delphi packages, as you need – for example Delphi.vcl.fx (for Windows), Delphi.dbrtl.fx for database access, and so on – via the standard Add References UI.

Note that all imported packages are prefixed with "Delphi., to avoid name collisions with other standard Elements or OS references (or frameworks, on macOS). This applies to the reference name and the namespace(s) contained within

Using Delphi APIs

Once referenced, all the APIs exposed by a package are available to your code,the same they would be in Delphi, and the same as any other native Elements types and functions are. All Delphi-imported types have their namespace (or unit name, for older Delphi versions) prefixed with "Delphi.", again to avoid name collisions and overlap.

For example, you could add Delphi.System.SysUtils to your uses clause, and start using SysUtils APIs in your code. Add ??? to start using VCL classes such as TForm.

You can also set "Default "uses" Prefixes" in project settings to, just like in Delphi, flatten the namespace hierarchy.

From there, all classes, types and global functions from the Delphi packages you have chosen to reference are available, and should be fully usable.

The Delphi Object Model

As you might know, the Island compiler backed suports different Object Models for platform interaction. By default classes you implement in Elements use the garbage-collected Island object mode, native to Elements, but on Cocoa you have long been able to also use Cocoa and (work in progress) Swift object models for native Objective-C and Swift types, which are reference counted.

Similarly, all classes, interfaces and records imported from Delphi use the Delphi Object Model, which means they live in a separate class hierarchy from your Elements-native types, and all the classes untimately descend from Delphi.System.TObject.

Like in Delphi itself, Delphi object model classes in Elements are not automatically memory-managed – meaning you have to track their life-time, and manually call Free, Destroy, FreeAndNil or dispose of them by other means.

Any classes you define that descend from Delphi-imported types will automatically use the Delphi object mode, as well. You can also explicitly mark a class to use this model by either adding the [Delphi] attribute to it, or explicitly specifying TObject (or one of its descendants) as the ancestor.

You can also set the "Default Object Model" setting for your project to Delphi to have all your types use that model by default, even when no ancestor or attribute is specified. This might be recommended for porting entire existing code bases over, or writing code that uses Delphi APIs more than it uses native Elements or platform APIs.

Note that Delphi types will get wrapped when assigned to an (Island) Object variable or parameter, just as native Island types will get wrapped when passed to a TObject type variable or parameter, as the two hierarchies do not share a common ancestor.

Basic operations such as checking for equality or a type's hash will work for two wrapped instances.

Do note that, by default, strings – such as those created from literals – are still Island-level string types, part of the Island object model tree, and responding to the APIs available on that type.

The DelphiString type is provided for working Delphi-type strings and is compatible with being passed into and received from Delphi APIs that take strings. It provides the same usage semantics as strings do in Delphi, such as one-based access, copy-on-write semantics, and compatibility with PChar.

Island's native String and Delphi's String types provide operators for casting seamlessly between the two, but such casts will have a conversion cost.

Importing Third Party Components and Packages


Importing Your Own Packages


Forms and .DFMs

The Elements tool chain knows about .dfm, .lfm and .fmx form files, and it will compile text-based forms to binary and perform the necessary steps to embed them into your executable for the VCL or FireMonkey classes to find at runtime.

The recommended way for this is to add .dfm, .lfm and .fmx to your project with a Build Action of "EmbeddResource" (which the Delphi project import will do for you), but the build tool chain can also optionally look for {$R resource tags in your Oxygene source files and pull in resource files from that.

Forms embedded in this way are compatible both with Delphi's VCL/FireMonkey library and the limited VCL support in the (unrelated) Delphi RTL native-Elements compatibility library.

Use Cases for Delphi SDKs

The availability of Delphi SDKs to Elements projects brings a whole slew of possibilities for the migration of Delphi projects to Elements.

  • You can simply reference Delphi packages to use your favorite Delphi APIs and classes you are familiar with, in your Elements code.
  • You can move/copy over code from Delphi to Oxygene more seamlessly, as all the APIs it relies on are there.
  • You can even move entire Delphi projects to Oxygene, keep using the VCL and all your third party components, while at the same time still benefitting from the more advanced Oxygene language.

And, of course Delphi SDK support is not limited to just Oxygene – you can use these APIs, and even descend from Delphi classes (such as to implement a new TForm, from all six Elements languages!

See Also

  1. The "Delphi SDKs" folder in EBuild's root cache folder