[fpc-pascal] ANN: Dynamic Package Support for Windows, MacOS, and Linux

Sven Barth pascaldragon at googlemail.com
Mon Oct 19 23:46:11 CEST 2026


Am 18.10.2026 um 18:56 schrieb Anthony Walter via fpc-pascal:
> Please let me know if you have any comments or questions.

First some general remarks (especially if you want to work towards 
creating a merge request for this):
- don't commit the updated Makefiles together with other changes, do 
them as separate commits as otherwise such commits are harder to review
- please get rid of the added, but unrelated examples, they add 
*massive* noise to the commit
- also why did you remove the *.o files for the C and C++ tests (and 
some other binary files)? If a binary is commited then it's usually done 
for a reason
- separate commits that affect different functionality, e.g. the 
adjustment in comprsrc.CollectResourceFiles can be a separate commit; 
this also allows to better explain certain functionaliy, for example why 
the IndirectInits and related functionality is needed (this also applies 
to other parts)

Some specific remarks:
- in fpcp it is on purpose that the PCP file and the final module can 
reside in different directories; the user needs to supply the correct 
library and package search paths (for example for a installation on a 
*nix system the *.so files would reside in /lib/... while the *.pcp 
files would reside in /usr/share/...)
- in fpkg don't name the field fingerprint, but checksum to be 
consistent with the names of PPUs
- use symconst.suffix_indirect instead of literal '$indirect'
- in dynpkgtypes: the compiler is not restricted to PE, Mach-O and ELF, 
so the $else case should not be ELF
- most of the low level package loading functionality should be part of 
the System unit (that's why I moved the library manager there after all 
(and also for delayed imports)) and should be shared between all targets 
as much as possible; only the nitty, gritty platform specific parts 
should be part of a separate unit (except for Windows) to avoid pulling 
in the C library when not needed

One further thing that you did not think of: we need to rework the unit 
initialization/finalization mechanism to be reference counted.
Take for example the following code structure:

ProgramFile.pp (does *not* use Classes)
- sysinit.pp

rtl.ppk
- system.pp
- classes.pp

pkgA.ppk
- unitA.pp (uses Classes)

pkgB.ppk
- unitB.pp (uses Classes)

Now ProgramFile obviously links against the RTL package at compile time. 
This means that the System unit of the RTL package will be initialized, 
but not the Classes unit, because ProgramFile does not link against that.
Now the program loads PkgA which will lead to all units of PkgA as well 
as all units from other packages used by units of PkgA to be initialized 
(in this case the Classes unit from the RTL package).
Now the program also loads PkgB which will also initialize all its units 
and those indirectly used; this means that the Classes unit *must not* 
be initialized again.
Now PkgA is unloaded. But that means the Classes unit *must not* be 
finalized yet, because PkgB (which uses the Classes unit as well) is 
still loaded.

This means that the unit initialization/finalization should be reworked 
to have a single entry point (currently a unit has several depending on 
whether it as an indirect initializer/finalizer, an 
initialization/finalization section and class constructors/destructors) 
and that should only be executed if its reference count is still 0 (for 
initialization) or reaches 0 (for finialization). The 
initializer/finalizer will also have the task of initializing/finalizing 
all used interface and implementation units.

With this the InitTable of the program will only contain those units 
directly (and automatically) used by the program. All other units will 
be initialized indirectly. Same with the UnitTable of the packages.

Since changing to this reference counting scheme (and thus essentially a 
depth first search of the unit tree) needs to a change in the 
initialization order the JVM and AVR targets (which don't use the 
typical InitTable scheme) need to be adjusted to have the same order 
generated at compile time.

Also as a further, somewhat related change: we should introduce a meta 
data type per unit which contains reference to the unit's RTTI, 
Threadvars, etc. This would also be the base for the RTTI units' 
GetTypes method and in the end each type's RTTI should have a reference 
to this meta data instead of a unit name like e.g. a class' RTTI 
currently has.

Please note that these comments are not yet fully conclusive, due to the 
extension of your commit. Once you've broken it down to easier 
digestable chunks more in depth discussion can be had.

Regards,
Sven


More information about the fpc-pascal mailing list