Import Upstream version 20180207
[hcoop/debian/mlton.git] / doc / guide / src / LibrarySupport.adoc
CommitLineData
7f918cf1
CE
1LibrarySupport
2==============
3
4MLton supports both linking to and creating system-level libraries.
5While Standard ML libraries should be designed with the <:MLBasis:> system to work with other Standard ML programs,
6system-level library support allows MLton to create libraries for use by other programming languages.
7Even more importantly, system-level library support allows MLton to access libraries from other languages.
8This article will explain how to use libraries portably with MLton.
9
10== The Basics ==
11
12A Dynamic Shared Object (DSO) is a piece of executable code written in a format understood by the operating system.
13Executable programs and dynamic libraries are the two most common examples of a DSO.
14They are called shared because if they are used more than once, they are only loaded once into main memory.
15For example, if you start two instances of your web browser (an executable), there may be two processes running, but the program code of the executable is only loaded once.
16A dynamic library, for example a graphical toolkit, might be used by several different executable programs, each possibly running multiple times.
17Nevertheless, the dynamic library is only loaded once and it's program code is shared between all of the processes.
18
19In addition to program code, DSOs contain a table of textual strings called symbols.
20These are used in order to make the DSO do something useful, like execute.
21For example, on linux the symbol `_start` refers to the point in the program code where the operating system should start executing the program.
22Dynamic libraries generally provide many symbols, corresponding to functions which can be called and variables which can be read or written.
23Symbols can be used by the DSO itself, or by other DSOs which require services.
24
25When a DSO creates a symbol, this is called 'exporting'.
26If a DSO needs to use a symbol, this is called 'importing'.
27A DSO might need to use symbols defined within itself or perhaps from another DSO.
28In both cases, it is importing that symbol, but the scope of the import differs.
29Similarly, a DSO might export a symbol for use only within itself, or it might export a symbol for use by other DSOs.
30Some symbols are resolved at compile time by the linker (those used within the DSO) and some are resolved at runtime by the dynamic link loader (symbols accessed between DSOs).
31
32== Symbols in MLton ==
33
34Symbols in MLton are both imported and exported via the <:ForeignFunctionInterface:>.
35The notation `_import "symbolname"` imports functions, `_symbol "symbolname"` imports variables, and `_address "symbolname"` imports an address.
36To create and export a symbol, `_export "symbolname"` creates a function symbol and `_symbol "symbolname" 'alloc'` creates and exports a variable.
37For details of the syntax and restrictions on the supported FFI types, read the <:ForeignFunctionInterface:> page.
38In this discussion it only matters that every FFI use is either an import or an export.
39
40When exporting a symbol, MLton supports controlling the export scope.
41If the symbol should only be used within the same DSO, that symbol has '`private`' scope.
42Conversely, if the symbol should also be available to other DSOs the symbol has '`public`' scope.
43Generally, one should have as few public exports as possible.
44Since they are public, other DSOs will come to depend on them, limiting your ability to change them.
45You specify the export scope in MLton by putting `private` or `public` after the symbol's name in an FFI directive.
46eg: `_export "foo" private: int->int;` or `_export "bar" public: int->int;` .
47
48For technical reasons, the linker and loader on various platforms need to know the scope of a symbol being imported.
49If the symbol is exported by the same DSO, use `public` or `private` as appropriate.
50If the symbol is exported by a different DSO, then the scope '`external`' should be used to import it.
51Within a DSO, all references to a symbol must use the same scope.
52MLton will check this at compile time, reporting: `symbol "foo" redeclared as public (previously external)`. This may cause linker errors.
53However, MLton can only check usage within Standard ML.
54All objects being linked into a resulting DSO must agree, and it is the programmer's responsibility to ensure this.
55
56Summary of symbol scopes:
57
58* `private`: used for symbols exported within a DSO only for use within that DSO
59* `public`: used for symbols exported within a DSO that may also be used outside that DSO
60* `external`: used for importing symbols from another DSO
61* All uses of a symbol within a DSO (both imports and exports) must agree on the symbol scope
62
63== Output Formats ==
64
65MLton can create executables (`-format executable`) and dynamic shared libraries (`-format library`).
66To link a shared library, use `-link-opt -l<dso_name>`.
67The default output format is executable.
68
69MLton can also create archives.
70An archive is not a DSO, but it does have a collection of symbols.
71When an archive is linked into a DSO, it is completely absorbed.
72Other objects being compiled into the DSO should refer to the public symbols in the archive as public, since they are still in the same DSO.
73However, in the interest of modular programming, private symbols in an archive cannot be used outside of that archive, even within the same DSO.
74
75Although both executables and libraries are DSOs, some implementation details differ on some platforms.
76For this reason, MLton can create two types or archives.
77A normal archive (`-format archive`) is appropriate for linking into an executable.
78Conversely, a libarchive (`-format libarchive`) should be used if it will be linked into a dynamic library.
79
80When MLton does not create an executable, it creates two special symbols.
81The symbol `libname_open` is a function which must be called before any other symbols are accessed.
82The `libname` is controlled by the `-libname` compile option and defaults to the name of the output, with any prefixing lib stripped (eg: `foo` -> `foo`, `libfoo` -> `foo`).
83The symbol `libname_close` is a function which should be called to clean up memory once done.
84
85Summary of `-format` options:
86
87* `executable`: create an executable (a DSO)
88* `library`: create a dynamic shared library (a DSO)
89* `archive`: create an archive of symbols (not a DSO) that can be linked into an executable
90* `libarchive`: create an archive of symbols (not a DSO) that can be linked into a library
91
92Related options:
93
94* `-libname x`: controls the name of the special `_open` and `_close` functions.
95
96
97== Interfacing with C ==
98
99MLton can generate a C header file.
100When the output format is not an executable, it creates one by default named `libname.h`.
101This can be overridden with `-export-header foo.h`.
102This header file should be included by any C files using the exported Standard ML symbols.
103
104If C is being linked with Standard ML into the same output archive or DSO,
105then the C code should `#define PART_OF_LIBNAME` before it includes the header file.
106This ensures that the C code is using the symbols with correct scope.
107Any symbols exported from C should also be marked using the `PRIVATE`/`PUBLIC`/`EXTERNAL` macros defined in the Standard ML export header.
108The declared C scope on exported C symbols should match the import scope used in Standard ML.
109
110An example:
111[source,c]
112----
113#define PART_OF_FOO
114#include "foo.h"
115
116PUBLIC int cFoo() {
117 return smlFoo();
118}
119----
120
121[source,sml]
122----
123val () = _export "smlFoo" private: unit -> int; (fn () => 5)
124val cFoo = _import "cFoo" public: unit -> int;
125----
126
127
128== Operating-system specific details ==
129
130On Windows, `libarchive` and `archive` are the same.
131However, depending on this will lead to portability problems.
132Windows is also especially sensitive to mixups of '`public`' and '`external`'.
133If an archive is linked, make sure it's symbols are imported as `public`.
134If a DLL is linked, make sure it's symbols are imported as `external`.
135Using `external` instead of `public` will result in link errors that `__imp__foo is undefined`.
136Using `public` instead of `external` will result in inconsistent function pointer addresses and failure to update the imported variables.
137
138On Linux, `libarchive` and `archive` are different.
139Libarchives are quite rare, but necessary if creating a library from an archive.
140It is common for a library to provide both an archive and a dynamic library on this platform.
141The linker will pick one or the other, usually preferring the dynamic library.
142While a quirk of the operating system allows external import to work for both archives and libraries,
143portable projects should not depend on this behaviour.
144On other systems it can matter how the library is linked (static or dynamic).