Free Pascal and Lazarus get first full dynamic package release

A developer who identifies himself as sysrpl has announced, on getlazarus.org, the first release of full dynamic package support for the Free Pascal Compiler (FPC) and the Lazarus IDE. He calls the feature long overdue for the ecosystem. A complete implementation is available for download from his site, and the full set of changes to FPC and Lazarus is committed to GitLab in his forked branch named dynamic packages.

The central claim is that dynamic packages let users create and install components, controls and Lazarus extensions in seconds without rebuilding the entire IDE. They can also be used in your own programs to build and deploy plugins that expose native Pascal classes and types through dynamic package libraries. To make that work, the author says he made numerous improvements to the compiler, its runtime and the Lazarus IDE, and also wrote extra IDE extensions for working with Lazarus packages.

Technically, dynamic packages are standard shared library files on Linux, Windows and macOS. They carry additional compiler-generated metadata that can be inspected and queried through new RTL units. The runtime also has mechanisms for safely preserving thread variables and for managing dynamic types, such as strings and dynamic arrays, between a program and its packages or between several packages. When deploying, a program can still be bundled into a single executable, or it can be split into multiple dynamic packages that can be replaced while the program is running, which gives it a plugin system.

There are three restrictions. First, a unit in a package cannot have the same name as the package. To help, the default package system now appends the word Package to the generated Pascal source file, so a package called ElectroTools.lpk gets ElectroToolsPackage.pas instead of ElectroTools.pas. Second, unit names must be unique across packages: if someone already has a unit named Widgets, you cannot install another package containing a unit with that name, and must choose one package or rename a unit. Third, dynamic packages are larger than ordinary shared libraries because they contain a map of everything inside them, and stripping a package removes the metadata it needs to work as a dynamic package.

On the RTL side, a new unit, DynPkgTypes.pas, helps read information from dynamic packages. It includes a TPackageType record describing a type (declaring unit name, type name, kind, RTTI pointer, and the class if the kind is a class). The author says the same RTTI information can be gathered from a package, and the RTL has enough functions to load, enumerate, search and unload packages at runtime.

The Lazarus changes are the bulk of the post. A new progress window that can appear outside the IDE shows up when source belonging to a registered package changes and the package is automatically rebuilt before Lazarus starts. It also appears when the whole IDE is rebuilt, showing the current operation and the estimated time remaining before the IDE restarts, and when adding or removing packages takes more than five seconds. Installing multiple packages at once is another new feature. A new Packages window, docked on the right by default, lists recently opened packages, persists between sessions, and lets you browse a package's files and double click to open one. When you open an installed package and click Compile in its window, associated controls, components or extensions update within a second or two, where such changes previously needed a full IDE rebuild. The package menu now updates when packages are added or removed, with no rebuild. Under IDE Integrations, a package can be restricted to a specific platform or widgetset; if it does not match, it is hidden from the package list and ignored by the IDE. The author's example is a TWinControl for the Windows IShellView COM interface, which can be made available only when Lazarus runs on Windows.

To show off the capability, the author also built a form or frame conversion feature for Lazarus extensions. It turns any form or frame into an installable control that is automatically added to the component palette, copying all controls, events, methods and properties, so new controls can be designed visually and existing forms or frames reused in other projects. If you try to build a package that an open form is using, the IDE asks you to save or close the form first.

Problems should be reported through the GitLab issue tracker for the linked branches, and questions go to a forum where a moderator must approve a new account before it can post. The author asks for help in two areas: the site needs moderators, and he is struggling to produce macOS builds. He asks anyone willing to donate an M1 Macintosh to message him, because he wants to work on the compiler code needed to support dynamic packages on the M1 architecture.

Key facts

  • Author sysrpl announced the first release of full dynamic package support for the Free Pascal Compiler and the Lazarus IDE, downloadable from getlazarus.org, with changes in his forked GitLab branch named dynamic packages.
  • Dynamic packages are standard shared libraries on Linux, Windows and macOS; the author says they let users install components, controls and extensions in seconds without rebuilding the IDE.
  • A program can be split into dynamic packages that are replaced while it runs, giving a plugin system; bundling into a single executable is still possible.
  • Restrictions: a unit cannot share its package's name, unit names must be unique across packages, and packages are larger than normal shared libraries because of embedded metadata.
  • Lazarus gains a progress window, a Packages window, per-platform and per-widgetset package restrictions, and a form-to-control conversion feature; macOS M1 support still needs donated hardware.

Why it matters

Changing a component or extension in Lazarus has meant rebuilding the whole IDE. The author says dynamic packages cut that to a second or two after clicking Compile in an installed package's window, and let packages be installed in seconds. The same mechanism lets a Pascal program ship as separate packages that can be swapped while it runs, which gives it a plugin system. The post presents this as the first release of a complete implementation.

Who it affects

Developers who build components, controls or IDE extensions for Lazarus, and those who want plugin architectures in Free Pascal programs, are the main audience. Package authors need to take the naming restrictions into account. Anyone on macOS is affected by the build situation: the author says he has difficulty producing macOS builds and wants a donated M1 Mac to work on M1 support.

How to use it

Download the release from getlazarus.org, or use the dynamic packages branch of the author's FPC and Lazarus fork on GitLab. In Lazarus, open an installed package and click Compile to update its controls. Use the new Packages window to browse recent packages, and set platform or widgetset limits under IDE Integrations. Name package units so they differ from the package (the package source file gets the Package suffix automatically) and from units in other packages. In your own code, the new DynPkgTypes.pas unit and the RTL functions handle loading, enumerating, searching and unloading packages at runtime. Bugs go to the GitLab issue tracker; questions go to the forum, which requires moderator approval of a new account.

How solid is it

This is the author's own announcement of his own work, with a demonstration video referenced on the page. The page gives no benchmarks, no version numbers and no release date. The timing claims, seconds to install and a second or two to update, are the author's statements, not measurements. The code is in his forked branch on GitLab and in downloads from his site.

Risks and caveats

The announcement points to the author's forked branch and his own downloads, not to official upstream releases. Two naming restrictions can cause conflicts: a unit cannot share its package's name, and unit names must be unique across packages, so two packages that both contain a unit such as Widgets cannot be installed together. Dynamic packages are larger than ordinary shared libraries, and stripping them removes the metadata they need. macOS builds are a stated difficulty, and dynamic package support on the M1 architecture is something the author still wants to work on, pending donated hardware. Trying to build a package used by an open form makes the IDE ask you to save or close the form first.

“Dynamic packages allow users to create and install components, controls, and Lazarus extensions in seconds without rebuilding the entire IDE.”

— sysrpl, getlazarus.org