The reason why
cmem et al. need to be placed at the beginning of the main unit's
uses section is a consequence of the way FPC handles unit initialization and involves no magic at all.
The unit tree is traversed left-to-right and depth-first, meaning that in your example...
u0
|
+--------------+
| |
u1 u2
|
+-------+
| |
u11 u12
...the order of initialization is as follows:
u11, u12, u1, u2, u0More specifically, the units'
initialization blocks are executed in that order. Looking at
cmem...
Initialization
GetMemoryManager (OldMemoryManager);
SetMemoryManager (CmemoryManager);
...you'll see that all it does is replace the RTL's global
TMemoryManager record, which
GetMem, FreeMem (and class constructors/destructors) all rely on. To make sure that
all other units (including their
initialize blocks) use the new memory manager, this code needs to run as early as possible - hence the placement at the very beginning in the
uses clause of the root unit.
In the case of multiple units defining a function with the same name, it's important to know two things:
FPC allows extensive name shadowing, meaning that the same identifier may refer to different things in different scopesFor example, the
objpas unit defines
TIntegerArray as a fixed-size array with a total size of 960 MiB (for legacy reasons I assume). If you don't find this useful (I don't), you're free to redefine it as e.g.
type TIntegerArray = array of Integer; and the compiler won't complain - it'll simply use the most recently given definition. This also applies to units in the
uses clause:
uses
u2, u12;
foo(); // Refers to u12.foo
uses
u12, u2;
foo(); // Refers to u2.foo
It's of course also possible to explicitly refer to an implementation by prepending the unit name, e.g.
u12.foo();FPC mangles function names in a way that includes the unit name (among other things)This makes FPC-generated code more powerful in the sense that source-level identifiers don't have to be unique even across objects files / translation units. For example, the
Format function in
SysUtils is referred to by the symbol
SYSUTILS_$$_FORMAT$ANSISTRING$array_of_const$$ANSISTRING by the linker instead of its literal name.