Sign in Join
Wiki copytemporary

System unit: what changed

Revision 0 to 1. Removed lines have a minus sign; added lines have a plus sign.

Title: System unit

OldNewLine
1+In Free Pascal the **System** unit is the unit that is included by *every* program. FPC's [[RTL|run-time library]] comes with a System unit where most, if not all of its functionalities work on every available [[Platform list|platform]].
2+
3+Also depending on the platform it's not true that no further unit is added, because for example on Windows the **SysInit** unit is also used, because that contains the entry point for the binary.
4+
5+## Compilation of System unit
6+
7+For quite some time already FPC automatically applies the -Us switch to the unit named System, so you don't need the -Us switch. The -Us switch tells the compiler that only basic type definitions are being made. Types such as [[Integer]] are not yet available.
8+
9+### Mandatory tasks of System unit
10+
11+If you attempt to create your own system unit, you'll incrementally notice what the compiler needs or what the generated code expects. On a Linux target, the minimal system unit has to contain:
12+
13+``` pascal
14+unit system;
15+
16+interface
17+```
18+
19+The type **hresult** must be defined, for example:
20+
21+``` pascal
22+type
23+ hresult = LongInt;
24+```
25+
26+The identifier **operatingsystem_result** has to be declared. The data stored at that position are communicated to the operating system as return value. Whether **hresult** and **operatingsystem_result** are defined in the "interface" section is irrelevant. However, it is very plausible to put those into the "interface" section, so programs using this system unit can manipulate those.
27+
28+``` pascal
29+var
30+ ExitCode: hresult = 0; export name 'operatingsystem_result';
31+
32+implementation
33+```
34+
35+Here comes to light what the system responsibilities are: It has to (or should) initialize units, that means call every unit's [[Initialization]] routines. For that the label **FPC_INITIALIZEUNITS** has to be defined.
36+
37+``` pascal
38+procedure InitializeUnits; alias: 'FPC_INITIALIZEUNITS';
39+begin
40+end;
41+```
42+
43+Also the label **FPC_DO_EXIT** has to be defined. Here, system unit programmers have the chance to finalize units.
44+
45+``` pascal
46+procedure doExit; alias: 'FPC_DO_EXIT';
47+begin
48+end;
49+
50+end.
51+```
52+
53+Furthermore FPC will possibly complain the unit FPIntRes is missing. So create a file fpintres.pas:
54+
55+``` pascal
56+unit FPIntRes;
57+interface
58+implementation
59+end.
60+```
61+
62+After doing so, you can compile your system unit (flag -Us is not needed), or directly create an empty program and compile it to examine the impact on the binary's size. On a x86-64 Linux target the executable had a size of 2.7 Kbytes. The big trade-off is no convenience. All functionality that can't be “implemented” by the compiler is gone. For example [[Addr]] or [[Ord]] still work, while Sin() or Random() are not available. Confer the procedure **create_intern_symbols** in "compiler/psystem.pas".
63+
64+> **Note:** Depending on what your program uses, there might *other* mandatory tasks, too. Especially OOP won't work without a functional ObjPas unit.
65+
66+### Initialization and finalization of units
67+
68+For those who are curious, how to implement FPC_INITIALIZEUNITS: FPC puts into every program's data section a INITFINAL table. Compiling a program with the "-al" flag will retain the Assembler file "*.s". Examining this Assembler file, you will encounter something like:
69+
70+``` asm
71+.section .data.n_INITFINAL
72+ .balign 8
73+.globl INITFINAL
74+ .type INITFINAL,@object
75+INITFINAL:
76+ .quad 1,0
77+ .quad INIT$_$SOMEUNIT
78+ .quad FINALIZE$_$SOMEUNIT
79+```
80+
81+For further investigations have a glimpse at an actual implementation: ["rtl/inc/system.inc"](https://gitlab.com/freepascal.org/fpc/source/-/blob/main/rtl/inc/system.inc).
82+
83+> **Note:** In general, implementing an “own” system unit is a stupid idea. There is “smart-linking” if [[Size Matters|size matters]].
84+
85+### Other issues with compilation
86+
87+- Q: Now FPC wants to compile the ObjPas unit.
88+- A: That is because your project's mode is set to ObjFPC (Lazarus will pass a -MObjFPC parameter to the compiler then) which automatically leads to an insertion of the ObjPas unit. Either change your project's mode in Project Settings -\> Compiler Settings -\> Parsing or add a {\$mode fpc} to your main program file.
89+
90+------------------------------------------------------------------------
91+
92+- Q: Now FPC cannot find this:
93+
94+`Unknown compilerproc "fpc_initializeunits". Check if you use the correct run time library.`
95+
96+- A: You need to add a
97+
98+``` pascal
99+ procedure fpc_initializeunits; compilerproc;
100+```
101+
102+both in the interface and implementation section.
103+
104+------------------------------------------------------------------------
105+
106+- Q: I am stuck, FPC says:
107+
108+`Internal type "TEXCEPTADDR" was not found`
109+
110+- A: The compiler expects some system defined types to be defined when parsing a subroutine such as the implementation section of System. This means you have to add some type definitions to System. It appears that this check was added to 3.2.0.
111+
112+## Example of System unit
113+
114+The example is made by user Okoba [at forum](https://forum.lazarus.freepascal.org/index.php?topic=49434.msg367677#msg367677).
115+
116+File system.pas:
117+
118+``` pas
119+unit system;
120+{$MODE FPC}
121+interface
122+
123+type
124+ hresult = LongInt;
125+ DWord = LongWord;
126+ Cardinal = LongWord;
127+ Integer = SmallInt;
128+ UInt64 = QWord;
129+ TTypeKind = (tkUnknown, tkInteger, tkChar, tkEnumeration, tkFloat, tkSet,
130+ tkMethod, tkSString, tkLString, tkAString, tkWString, tkVariant, tkArray,
131+ tkRecord, tkInterface, tkClass, tkObject, tkWChar, tkBool, tkInt64, tkQWord,
132+ tkDynArray, tkInterfaceRaw, tkProcVar, tkUString, tkUChar, tkHelper, tkFile,
133+ tkClassRef, tkPointer);
134+
135+type
136+ jmp_buf = packed record
137+ rbx, rbp, r12, r13, r14, r15, rsp, rip: QWord;
138+ {$IFDEF win64}
139+ rsi, rdi: QWord;
140+ xmm6, xmm7, xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15: record
141+ m1, m2: QWord;
142+ end;
143+
144+ mxcsr: LongWord;
145+ fpucw: word;
146+ padding: word;
147+ {$ENDIF win64}
148+ end;
149+
150+ Pjmp_buf = ^jmp_buf;
151+ PExceptAddr = ^TExceptAddr;
152+ TExceptAddr = record
153+ buf: Pjmp_buf;
154+ next: PExceptAddr;
155+ {$IFDEF CPU16}
156+ frametype: SmallInt;
157+ {$ELSE CPU16}
158+ frametype: LongInt;
159+ {$ENDIF CPU16}
160+ end;
161+
162+ PGuid = ^TGuid;
163+ TGuid = packed record
164+ case Integer of
165+ 1:
166+ (Data1: DWord;
167+ Data2: word;
168+ Data3: word;
169+ Data4: array [0 .. 7] of byte;
170+ );
171+ 2:
172+ (D1: DWord;
173+ D2: word;
174+ D3: word;
175+ D4: array [0 .. 7] of byte;
176+ );
177+ 3:
178+ ( { uuid fields according to RFC4122 }
179+ time_low: DWord; // The low field of the timestamp
180+ time_mid: word; // The middle field of the timestamp
181+ time_hi_and_version: word;
182+ // The high field of the timestamp multiplexed with the version number
183+ clock_seq_hi_and_reserved: byte;
184+ // The high field of the clock sequence multiplexed with the variant
185+ clock_seq_low: byte; // The low field of the clock sequence
186+ node: array [0 .. 5] of byte; // The spatially unique node identifier
187+ );
188+ end;
189+
190+var
191+ ExitCode: hresult = 0; export name 'operatingsystem_result';
192+
193+procedure fpc_initializeunits; compilerproc;
194+
195+procedure fpc_do_exit; compilerproc;
196+
197+implementation
198+
199+procedure fpc_initializeunits;
200+begin
201+end;
202+
203+procedure fpc_do_exit;
204+begin
205+end;
206+
207+end.
208+```
209+
210+File sysinit.pas:
211+
212+``` Pascal
213+unit sysinit;
214+{$MODE FPC}
215+
216+interface
217+
218+procedure _FPC_mainCRTStartup; stdcall; public name '_mainCRTStartup';
219+
220+implementation
221+
222+procedure _FPC_mainCRTStartup; stdcall;
223+begin
224+end;
225+
226+end.
227+```
228+
229+File fpintres.pas:
230+
231+``` Pascal
232+unit FPIntRes;
233+{$MODE FPC}
234+
235+interface
236+implementation
237+end.
238+```
239+
240+## Comparative remarks
241+
242+Other compilers such as [[GNU Pascal]] or [[Delphi]] use similar constructs, but to varying extent, and the file is not necessarily named "system.pas".
243+
244+## See also
245+
246+- FPC RTL System unit reference
247+- [[System unit structure]], some explanation about the distributed system unit
248+- [[Minimal RTL]]
249+- [[RTL development articles]]
250+
251+---
252+*From the Free Pascal wiki, page "System unit", as it stood on 2022-01-07 after a change by Alextp, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*
253+Category: Code

Back to history