Sign in Join
Wiki copytemporary

Lazarus/FPC Libraries: what changed

Revision 2 to 3. Removed lines have a minus sign; added lines have a plus sign.

OldNewLine
1-This page describes the possibilities for creating libraries with Lazarus/FPC and using them in projects and packages.
1+This page describes the possibilities for creating libraries with Lazarus/FPC and using them in projects and packages.
22
33## Related Topics
44
5-- [[Creating bindings for C libraries]] - How to convert C header files (.h) to pascal units
5+ * [[Creating bindings for C libraries]] \- How to convert C header files (.h) to pascal units
66
77## General
88
99### Static linking
1010
11-FPC compiles and links a static executable by default. That means it tells the linker to put all .o files of the project and all packages into one big executable.
11+FPC compiles and links a static executable by default. That means it tells the linker to put all .o files of the project and all packages into one big executable.
1212
13-- Advantages:
14- - No external dependencies.
15-- Disadvantages:
16- - No code is shared between different programs on the same computer.
17- - You can not load/unload a plugin.
13+ * Advantages:
14+ * No external dependencies.
15+ * Disadvantages:
16+ * No code is shared between different programs on the same computer.
17+ * You can not load/unload a plugin.
1818
1919### Dynamic libraries
2020
21-The alternative to static linking is using dynamic libraries. The idea of dynamic libraries is to share code between programs,
21+The alternative to static linking is using dynamic libraries. The idea of dynamic libraries is to share code between programs,
2222
23-- Advantages:
24- - Saving the memory of the code
25- - Reducing startup time for often used libraries
26- - Allowing plugins.
27-- Disadvantages:
28- - They are slower for seldomly used libs.
29- - Their structure and internals are more complicated (this is mainly a problem for the compiler).
30- - Their initialization is different (see below)
31- - Sharing code requires a version system to only mix compatible code.
23+ * Advantages:
24+ * Saving the memory of the code
25+ * Reducing startup time for often used libraries
26+ * Allowing plugins.
27+ * Disadvantages:
28+ * They are slower for seldomly used libs.
29+ * Their structure and internals are more complicated (this is mainly a problem for the compiler).
30+ * Their initialization is different (see below)
31+ * Sharing code requires a version system to only mix compatible code.
3232
3333## Operating Systems
3434
3535| Operating System | Dynamic library extension | Static library extension | Library prefix |
36-|----|----|----|----|
36+|---|---|---|---|
3737| FreeBSD | .so | .a | lib |
3838| macOS | .dylib | .a | lib |
3939| Linux | .so | .a | lib |
4040| Windows | .dll | .lib | n/a |
4141| Haiku | .so | .a | lib |
4242
43-The library prefix and extension columns indicate how the names of libraries are resolved and created for the listed operating systems.
43+The library prefix and extension columns indicate how the names of libraries are resolved and created for the listed operating systems.
4444
4545### FreeBSD
4646
47-To Do.
47+To Do.
4848
4949### macOS
5050
51-Under macOS, the library name will always have the lib prefix when it is created. So if you create a dynamic library called test, this will result in the file `libtest.dylib`. When importing routines from shared libraries, it is not necessary to give the library prefix or the library filename extension.
51+Under macOS, the library name will always have the lib prefix when it is created. So if you create a dynamic library called test, this will result in the file `libtest.dylib`. When importing routines from shared libraries, it is not necessary to give the library prefix or the library filename extension.
5252
53-Before [[User Changes 2.2.2|FPC 2.2.2]] released in August 2008, 32 bit .dylibs required exported symbols to be prefixed with an underscore. This is no longer the case.
53+Before [[User Changes 2.2.2|FPC 2.2.2]] released in August 2008, 32 bit .dylibs required exported symbols to be prefixed with an underscore. This is no longer the case.
5454
55-The standard locations for dynamic libraries are `~/lib`, `/usr/local/lib`, and `/usr/lib`. Starting with macOS 10.15 (Catalina) `/usr/lib` is on the system read-only volume so cannot be used for third-party libraries. While you may also place the .dylib file in a non-standard location in your file system, you then must add that location to one of these environment variables:
55+The standard locations for dynamic libraries are `~/lib`, `/usr/local/lib`, and `/usr/lib`. Starting with macOS 10.15 (Catalina) `/usr/lib` is on the system read-only volume so cannot be used for third-party libraries. While you may also place the .dylib file in a non-standard location in your file system, you then must add that location to one of these environment variables:
5656
57-- LD_LIBRARY_PATH
58-- DYLD_LIBRARY_PATH
59-- DYLD_FALLBACK_LIBRARY_PATH
57+ * LD_LIBRARY_PATH
58+ * DYLD_LIBRARY_PATH
59+ * DYLD_FALLBACK_LIBRARY_PATH
6060
61-Private shared libraries should be included in your application's [[Application Bundle]]. This is especially important for libraries which do not have a stable ABI (eg OpenSSL) so that they are revision-locked to the application and cannot be superseded by any other, even newer, versions that may be available to the operating system.
61+Private shared libraries should be included in your application's [[Application Bundle]]. This is especially important for libraries which do not have a stable ABI (eg OpenSSL) so that they are revision-locked to the application and cannot be superseded by any other, even newer, versions that may be available to the operating system.
6262
63-Refer to the See also section below for additional macOS information.
63+Refer to the See also section below for additional macOS information.
6464
6565### Linux
6666
67-A dynamic library filename always has the form 'lib'+packagename+'.so'+version. For example: `libz.so.1` and `libz.so.1.2.2`.
67+A dynamic library filename always has the form 'lib'+packagename+'.so'+version. For example: `libz.so.1` and `libz.so.1.2.2`.
6868
69-Linux searches a library in this order:
69+Linux searches a library in this order:
7070
71-- first in the paths of the environment variable `LD_LIBRARY_PATH`
72-- then in /lib
73-- then /usr/lib
74-- finally the paths of `/etc/ld.so.conf`
71+ * first in the paths of the environment variable `LD_LIBRARY_PATH`
72+ * then in /lib
73+ * then /usr/lib
74+ * finally the paths of `/etc/ld.so.conf`
7575
76-Using `ldconfig` after copying your library file into a lib directory may help with caching issues.
76+Using `ldconfig` after copying your library file into a lib directory may help with caching issues.
7777
78-To share memory (`GetMem`/`FreeMem`, strings) with other libraries (not written in FPC) under Linux, you should use the **unit cmem**. This unit must be added as **the very first unit** in the uses section of the project main source file (typically .lpr), so that its initialization section is called before any other unit can allocate memory.
78+To share memory (`GetMem`/`FreeMem`, strings) with other libraries (not written in FPC) under Linux, you should use the **unit cmem**. This unit must be added as **the very first unit** in the uses section of the project main source file (typically .lpr), so that its initialization section is called before any other unit can allocate memory.
7979
8080### Windows
8181
82-Windows searches a library in:
82+Windows searches a library in:
8383
84-- first in the current directory
85-- then the system directory
86-- finally the directories specified in the environment variable PATH (system and user path).
84+ * first in the current directory
85+ * then the system directory
86+ * finally the directories specified in the environment variable PATH (system and user path).
8787
88-*to do: wasn't there a change in Vista+ behaviour for this?*
88+_to do: wasn't there a change in Vista+ behaviour for this?_
8989
90-When using an FPC made DLL with a non-FPC host application, exception handling can lead to some problems. Workarounds are mentioned in the #Initialization section.
90+When using an FPC made DLL with a non-FPC host application, exception handling can lead to some problems. Workarounds are mentioned in the #Initialization section.
9191
9292## ppumove, .ppu, .ppl
9393
94-FPC normally creates for every unit a .ppu and .o file. The **.ppu file** contains every important information of the .pas/.pp file (types, required filenames like the .o file), while the **.o file** contains the assembler code and the mangled names understood by the current system.
95-
96-The **ppumove** tool included with every FPC installation, converts one or several .ppu and .o files into a dynamic library. It does this by calling the linker to gather all .o files into a .so (windows: .dll) file and removes the .o filename references from the .ppu file. These new .ppu files are normally called **.ppl files**.
94+FPC normally creates for every unit a .ppu and .o file. The **.ppu file** contains every important information of the .pas/.pp file (types, required filenames like the .o file), while the **.o file** contains the assembler code and the mangled names understood by the current system.
9795
98-For example:
96+The **ppumove** tool included with every FPC installation, converts one or several .ppu and .o files into a dynamic library. It does this by calling the linker to gather all .o files into a .so (windows: .dll) file and removes the .o filename references from the .ppu file. These new .ppu files are normally called **.ppl files**.
9997
100-You have the output directory of a package (where the .ppu files are):
98+For example:
10199
102-``` bash
100+You have the output directory of a package (where the .ppu files are):
101+```
103102ppumove -o packagename -e ppl *.ppu
104103```
105104
106-This will convert all .ppu files into .ppl files and creates a libpackagename.so (windows: packagename.dll). Note that under Linux the prefix 'lib' is always prepended.
105+This will convert all .ppu files into .ppl files and creates a libpackagename.so (windows: packagename.dll). Note that under Linux the prefix 'lib' is always prepended.
107106
108-This new library can already be used by other programming languages like C. Or by FPC programs by using the **external** modifiers. But the initialization/finalization sections must be called automatically. This includes the initialization/finalization of the heap manager. This means no strings or GetMem. Of course FPC programmers are spoiled and they can get more.
107+This new library can already be used by other programming languages like C. Or by FPC programs by using the **external** modifiers. But the initialization/finalization sections must be called automatically. This includes the initialization/finalization of the heap manager. This means no strings or GetMem. Of course FPC programmers are spoiled and they can get more.
109108
110109## External - statically loading a dynamic library
111110
112-The static loading of a dynamic library can be done in code, by using the external keyword, like in the example below which shows how a gtk function is loaded:
113-
114-``` pascal
111+The static loading of a dynamic library can be done in code, by using the external keyword, like in the example below which shows how a gtk function is loaded:
112+```
115113const
116-{$ifdef win32}
117- gtklib = 'libgtk-win32-2.0-0.dll';
118-{$else}
119- {$ifdef darwin}
120- gtklib = 'gtk-x11-2.0';
121- {$linklib gtk-x11-2.0}
122- {$else}
123- gtklib = 'libgtk-x11-2.0.so';
124- {$endif}
125-{$endif}
126-
127-procedure gtk_widget_set_events(widget:PGtkWidget; events:gint); cdecl; external gtklib;
114+ {$ifdef win32}
115+ gtklib = 'libgtk-win32-2.0-0.dll';
116+ {$else}
117+ {$ifdef darwin}
118+ gtklib = 'gtk-x11-2.0';
119+ {$linklib gtk-x11-2.0}
120+ {$else}
121+ gtklib = 'libgtk-x11-2.0.so';
122+ {$endif}
123+ {$endif}
124+
125+ procedure gtk_widget_set_events(widget:PGtkWidget; events:gint); cdecl; external gtklib;
128126```
129127
130128## Loadlibrary - dynamically loading a dynamic library
131129
132-Loading a dynamic library is simple with the Loadlibrary function of the unit dynlibs.
133-
134-The main problem is to get the filename, which depends on the version and the operating system. Since 2.2.2, a constant "sharedsuffix" is declared in unit dynlibs to ease this. It maps to the relevant extension (dll/so/dylib) without a point as prefix.
130+Loading a dynamic library is simple with the Loadlibrary function of the unit dynlibs.
135131
136-Here are the functions declared in the unit dynlibs:
132+The main problem is to get the filename, which depends on the version and the operating system. Since 2.2.2, a constant "sharedsuffix" is declared in unit dynlibs to ease this. It maps to the relevant extension (dll/so/dylib) without a point as prefix.
137133
138-``` pascal
134+Here are the functions declared in the unit dynlibs:
135+```
139136Function SafeLoadLibrary(Name : AnsiString) : TLibHandle;
140-Function LoadLibrary(Name : AnsiString) : TLibHandle;
141-Function GetProcedureAddress(Lib : TlibHandle; ProcName : AnsiString) : Pointer;
142-Function UnloadLibrary(Lib : TLibHandle) : Boolean;
137+ Function LoadLibrary(Name : AnsiString) : TLibHandle;
138+ Function GetProcedureAddress(Lib : TlibHandle; ProcName : AnsiString) : Pointer;
139+ Function UnloadLibrary(Lib : TLibHandle) : Boolean;
143140```
144141
145-SafeLoadLibrary is the same as LoadLibrary but it also disables arithmetic exceptions which some libraries expect to be off on loading.
146-
147-Pseudocode of the usage:
142+SafeLoadLibrary is the same as LoadLibrary but it also disables arithmetic exceptions which some libraries expect to be off on loading.
148143
149-``` pascal
144+Pseudocode of the usage:
145+```
150146uses dynlibs;
151-
152-var
153- MyLibC: TLibHandle;
154- MyProc: TMyProc;
155-begin
156- MyLibC := LoadLibrary('libc.' + SharedSuffix);
157- if MyLibC = 0 then Exit;
158- MyProc := TMyProc(GetProcedureAddress(MyLibC, 'getpt');
159- if MyProc = nil then Exit;
160-end;
147+
148+ var
149+ MyLibC: TLibHandle;
150+ MyProc: TMyProc;
151+ begin
152+ MyLibC := LoadLibrary('libc.' + SharedSuffix);
153+ if MyLibC = 0 then Exit;
154+ MyProc := TMyProc(GetProcedureAddress(MyLibC, 'getpt');
155+ if MyProc = nil then Exit;
156+ end;
161157```
162158
163-Pseoudocode for using a function, taking parameters:
164-
165-``` pascal
159+Pseoudocode for using a function, taking parameters:
160+```
166161uses ...dynlibs...
167-
168-procedure UseDLL;
169-type
170- TMyFunc=function (aInt:Integer; aStr: string):String; StdCall;
171-var
172- MyLibC: TLibHandle= dynlibs.NilHandle;
173- MyFunc: TMyFunc;
174- FuncResult: string;
175-begin
176- MyLibC := LoadLibrary('libc.' + SharedSuffix);
177- if MyLibC = dynlibs.NilHandle then Exit; //DLL was not loaded successfully
178- MyFunc:= TMyFunc(GetProcedureAddress(MyLibC, 'MyFunc');
179- FuncResult:= MyFunc (5,'Test'); //Executes the function
180- if MyLibC <> DynLibs.NilHandle then if FreeLibrary(MyLibC) then MyLibC:= DynLibs.NilHandle; //Unload the lib, if already loaded
181-end;
162+
163+ procedure UseDLL;
164+ type
165+ TMyFunc=function (aInt:Integer; aStr: string):String; StdCall;
166+ var
167+ MyLibC: TLibHandle= dynlibs.NilHandle;
168+ MyFunc: TMyFunc;
169+ FuncResult: string;
170+ begin
171+ MyLibC := LoadLibrary('libc.' + SharedSuffix);
172+ if MyLibC = dynlibs.NilHandle then Exit; //DLL was not loaded successfully
173+ MyFunc:= TMyFunc(GetProcedureAddress(MyLibC, 'MyFunc');
174+ FuncResult:= MyFunc (5,'Test'); //Executes the function
175+ if MyLibC <> DynLibs.NilHandle then if FreeLibrary(MyLibC) then MyLibC:= DynLibs.NilHandle; //Unload the lib, if already loaded
176+ end;
182177```
183178
184-> **Note:** Before 1.9.4, the unit dl was used for this. Since 1.9.4, dynlibs provides a portable alternative. Note that pretty much any use of unit dl that can't be substituted by using dynlibs is typically already unportable amongst Unices. This alone makes it advisable to use unit dynlibs as much as possible.
179+
185180
181+![Light bulb](https://upload.wikimedia.org/wikipedia/commons/d/d8/Nuvola_apps_ktip.png) **Note:** Before 1.9.4, the unit dl was used for this. Since 1.9.4, dynlibs provides a portable alternative. Note that pretty much any use of unit dl that can't be substituted by using dynlibs is typically already unportable amongst Unices. This alone makes it advisable to use unit dynlibs as much as possible.
182+
186183### Simplified overview of the system, when loading a shared library under Linux
187184
188-![Loading a shared library...](/wiki-images/a/ad/Lazarus_free_pascal_libraries_loading_under_linux.png)\
189-This chart summarizes how to configure a shared library (referenced by its soname, and its real-name, at least) in /etc/ld.so.conf and to update the library cache using *ldconfig* utility, to inform the Linux system library loader named *ldd* (other methods to load a shared library, with an environment variable like LD_LIBRARY_PATH, with code, by inclusion in the binary elf, etc, are also illustrated in the chart). For information, it's often necessary to check if a soft-symlink exists between the soname and the real-name, at least. The installation of development packages (*-dev*.deb files, for a Debian installation) always delivers such soft-symlink (ex.: abc.so) pointing to the soname (ex.: abc.so.{9}) on which the development package depends. Release packages sometimes forget this, whereas they are best placed to retrieve and to make point an old installation towards a new installed real-name library: indeed, shared libraries should respect the takeover of precedence in their existing APIs, features, at least inside the same soname (backward compatibility).
185+[![Loading a shared library...](/wiki-images/f/fa/lazarus_free_pascal_libraries_loading_under_linux.png)](</File:lazarus_free_pascal_libraries_loading_under_linux.png> "Loading a shared library...")
186+This chart summarizes how to configure a shared library (referenced by its soname, and its real-name, at least) in /etc/ld.so.conf and to update the library cache using _ldconfig_ utility, to inform the Linux system library loader named _ldd_ (other methods to load a shared library, with an environment variable like LD_LIBRARY_PATH, with code, by inclusion in the binary elf, etc, are also illustrated in the chart). For information, it's often necessary to check if a soft-symlink exists between the soname and the real-name, at least. The installation of development packages (*-dev*.deb files, for a Debian installation) always delivers such soft-symlink (ex.: abc.so) pointing to the soname (ex.: abc.so.{9}) on which the development package depends. Release packages sometimes forget this, whereas they are best placed to retrieve and to make point an old installation towards a new installed real-name library: indeed, shared libraries should respect the takeover of precedence in their existing APIs, features, at least inside the same soname (backward compatibility).
190187
191188## Creating a library
192189
193190See the Free Pascal Documentation: <http://www.freepascal.org/docs-html/prog/progse55.html>
194191
195192## Initialization
196193
197-Every unit can contain an initialization section. The order of the initialization sections depend on the uses sections of each unit.
194+Every unit can contain an initialization section. The order of the initialization sections depend on the uses sections of each unit.
198195
199-The initialization of the RTL itself (in system.pp) that is done before your initialization sections are entered slightly differs between a program and a shared library. Most notably there is a difference in how the exception handling is initialized:
196+The initialization of the RTL itself (in system.pp) that is done before your initialization sections are entered slightly differs between a program and a shared library. Most notably there is a difference in how the exception handling is initialized:
200197
201198### Exception handling
202199
203200#### Windows
204201
205-On Windows systems it has been [reported](http://bugs.freepascal.org/view.php?id=12974) that there is no exception handler installed to catch hardware exceptions like access violations or floating point errors; all other native Pascal exceptions that are raised with Raise will work however.
202+On Windows systems it has been [reported](<http://bugs.freepascal.org/view.php?id=12974>) that there is no exception handler installed to catch hardware exceptions like access violations or floating point errors; all other native Pascal exceptions that are raised with Raise will work however.
206203
207-If you really need to catch these hardware exceptions you have to install your own handler, on Windows (beginning with versions XP and later) this is conveniently possible with AddVectoredExceptionHandler() and RemoveVectoredExceptionHandler(), there are some code examples in the above mentioned bug report. Note: work has been started in FPC 2.7.1/trunk to address this problem using 32 bit SEH.
204+If you really need to catch these hardware exceptions you have to install your own handler, on Windows (beginning with versions XP and later) this is conveniently possible with AddVectoredExceptionHandler() and RemoveVectoredExceptionHandler(), there are some code examples in the above mentioned bug report. Note: work has been started in FPC 2.7.1/trunk to address this problem using 32 bit SEH.
208205
209206#### UNIX and UNIX-like systems
210207
211-On UNIX and UNIX-like systems (BSD, Darwin, Linux etc) no exception handler is installed to catch hardware exceptions (signals) like access violations in shared libraries. If you wish to catch these exceptions (signals) in a library code, you need to explicitly call `HookSignal(RTL_SIGDEFAULT)` during library initialization and call `UnhookSignal(RTL_SIGDEFAULT)` during finalization.
208+On UNIX and UNIX-like systems (BSD, Darwin, Linux etc) no exception handler is installed to catch hardware exceptions (signals) like access violations in shared libraries. If you wish to catch these exceptions (signals) in a library code, you need to explicitly call `HookSignal(RTL_SIGDEFAULT)` during library initialization and call `UnhookSignal(RTL_SIGDEFAULT)` during finalization.
212209
213-Keep in mind that when you enable signal handling in your shared library, it will replace signal handlers installed by a host application or other shared libraries of the current process. It may cause unexpected behavior. It is known that Java on Linux uses the SIGSEGV signal for its internal functionality and will crash if a third-party JNI library overrides the SIGSEGV signal handler.
210+Keep in mind that when you enable signal handling in your shared library, it will replace signal handlers installed by a host application or other shared libraries of the current process. It may cause unexpected behavior. It is known that Java on Linux uses the SIGSEGV signal for its internal functionality and will crash if a third-party JNI library overrides the SIGSEGV signal handler.
214211
215212### FPU mask
216213
217-For Delphi compatibility reasons, Free Pascal on i386 will [unmask](http://bugs.freepascal.org/view.php?id=16801) all FPU exceptions in the floating point unit (but without installing a handler for the dll, see above). This unmasking is done before your initialization section begins. If your DLL will be used with a host application that is made with a different compiler (almost all other compilers except FPC and Delphi/ C++ Builder *please verify C++ builder*) this will badly interfere with the host application's exception handling.
218-
219-After the LoadLibrary() call, the host application won't be able to catch any floating point exceptions anymore. The FPU will suddenly have gained the ability to throw hardware exceptions (in the thread that called LoadLibrary()), and the host application will most likely not expect this to happen and not be able to handle it properly. The workaround is to put
214+For Delphi compatibility reasons, Free Pascal on i386 will [unmask](<http://bugs.freepascal.org/view.php?id=16801>) all FPU exceptions in the floating point unit (but without installing a handler for the dll, see above). This unmasking is done before your initialization section begins. If your DLL will be used with a host application that is made with a different compiler (almost all other compilers except FPC and Delphi/ C++ Builder _please verify C++ builder_) this will badly interfere with the host application's exception handling.
220215
221-``` pascal
216+After the LoadLibrary() call, the host application won't be able to catch any floating point exceptions anymore. The FPU will suddenly have gained the ability to throw hardware exceptions (in the thread that called LoadLibrary()), and the host application will most likely not expect this to happen and not be able to handle it properly. The workaround is to put
217+```
222218Set8087CW(Get8087CW or $3f);
223219```
224220
225-in the initialization section to mask them again for the thread that loaded the library. This won't have any unwanted side effects other than restoring what the host application had all the time. In your DLL you would not have been able to catch them anyway (at least not on Windows, see above). If you really need to catch zero-divide and related errors in a DLL that is written for a non-FPC application, you have to
221+in the initialization section to mask them again for the thread that loaded the library. This won't have any unwanted side effects other than restoring what the host application had all the time. In your DLL you would not have been able to catch them anyway (at least not on Windows, see above). If you really need to catch zero-divide and related errors in a DLL that is written for a non-FPC application, you have to
226222
227-- have a handler installed like mentioned above
228-- temporarily unmask the FPU before the try
229-- mask it again before you return to the host application
223+ * have a handler installed like mentioned above
224+ * temporarily unmask the FPU before the try
225+ * mask it again before you return to the host application
230226
231227## Finalization
232228
233-Every unit can contain a finalization section. The order is the reverse order of the initialization sections.
229+Every unit can contain a finalization section. The order is the reverse order of the initialization sections.
234230
235-After all finalization sections are executed it will call the procedure that you have previously assigned to Dll_Process_Detach_Hook.
231+After all finalization sections are executed it will call the procedure that you have previously assigned to Dll_Process_Detach_Hook.
236232
237-Be very careful what you do in this procedure:
233+Be very careful what you do in this procedure:
238234
239-- all other units will already be finalized
240-- parts of the RTL might not work as expected anymore
241-- creating and freeing objects on the heap or even using Pascal strings inside this procedure is a sure way to call for trouble.
235+ * all other units will already be finalized
236+ * parts of the RTL might not work as expected anymore
237+ * creating and freeing objects on the heap or even using Pascal strings inside this procedure is a sure way to call for trouble.
242238
243-If you have to stop threads and free objects you must find a way to do this before the library unloading - it is too late to do it here.
239+If you have to stop threads and free objects you must find a way to do this before the library unloading - it is too late to do it here.
244240
245241## Versions, Distribution
246242
247-Libraries tend to grow and change over time. Adding new features is no problem, but removing a public method or changing its parameters makes the library incompatible. That means either an installed library (.so, .dll, .dylib) is replaced by a compatible one **or** a new library must be added to the system. That's why every library contains a version.
243+Libraries tend to grow and change over time. Adding new features is no problem, but removing a public method or changing its parameters makes the library incompatible. That means either an installed library (.so, .dll, .dylib) is replaced by a compatible one **or** a new library must be added to the system. That's why every library contains a version.
248244
249-To do: explain how to set/use this version both on Windows and *nix
245+To do: explain how to set/use this version both on Windows and *nix
250246
251-To load a dynamic library (**dlopen** of **unit dynlibs**) the correct filename must be known. Under Linux this means that you have to know the version number.
247+To load a dynamic library (**dlopen** of **unit dynlibs**) the correct filename must be known. Under Linux this means that you have to know the version number.
252248
253-To do: proposal how the IDE should create version numbers
249+To do: proposal how the IDE should create version numbers
254250
255251## See also
256252
257-- [[macOS Programming Tips|macOS Programming Tips - Libraries]]
258-- [[macOS Dynamic Libraries]]
259-- [[macOS Static Libraries]]
260-- FPC [[shared library]]
261-- FPC [[packages]]
262-- [[Translations / i18n / localizations for programs]]
253+ * [[macOS Programming Tips|macOS Programming Tips - Libraries]]
254+ * [[macOS Dynamic Libraries]]
255+ * [[macOS Static Libraries]]
256+ * FPC [[shared library]]
257+ * FPC [[packages]]
258+ * [[Translations / i18n / localizations for programs]]
263259
264260---
265-*From the Free Pascal wiki, page "Lazarus/FPC Libraries", as it stood on 2021-09-24 after a change by Eric69, 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).*
261+*From the Free Pascal wiki, page "Lazarus/FPC Libraries", as the Internet Archive kept it on 2025-04-24, last changed on 2024-12-30. 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).*

Back to history