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 (.bpl
s).
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.
Prerequisites
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 .DFM
s
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
Delphi
Object Model
-
The "
Delphi SDKs
" folder in EBuild's root cache folder. ↩