Skip to content

Commit eac0b82

Browse files
authored
Initial update to dynamic linking docs (#15613)
1 parent f8fef89 commit eac0b82

File tree

2 files changed

+84
-68
lines changed

2 files changed

+84
-68
lines changed

site/source/docs/compiling/Building-Projects.rst

+20-14
Original file line numberDiff line numberDiff line change
@@ -258,20 +258,26 @@ The simplest solution is usually to build the project twice: once natively, and
258258
In some cases it makes sense to modify the build scripts so that they build the generated executable natively. For example, this can be done by specifying two compilers in the build scripts, *emcc* and *gcc*, and using *gcc* just for generated executables. However, this can be more complicated than the previous solution because you need to modify the project build scripts, and you may have to work around cases where code is compiled and used both for the final result and for a generated executable.
259259

260260

261-
Dynamic linking
262-
---------------
263-
264-
Emscripten's goal is to generate the fastest and smallest possible code, and for that reason it focuses on generating a single JavaScript file for an entire project. For that reason, dynamic linking should be avoided when possible.
265-
266-
By default, Emscripten ``.so`` files are the same as regular ``.o`` object files.
267-
Dynamic libraries that you specify in the final build stage (when generating
268-
JavaScript or HTML) are linked in as static libraries. *Emcc* ignores commands
269-
to dynamically link libraries during the compile stage (i.e., not in the
270-
final build stage). This is to ensure that the same dynamic library is not
271-
linked multiple times in intermediate build stages, which would result in
272-
duplicate symbol errors.
273-
274-
There is :ref:`experimental support <Dynamic-Linking>` for true dynamic libraries, loaded as runtime, either via dlopen or as a shared library. See that link for the details and limitations.
261+
Faux Dynamic Linking
262+
--------------------
263+
264+
Emscripten's goal is to generate the fastest and smallest possible code, and for
265+
that reason it focuses on generating a single JavaScript file for an entire
266+
project. For that reason, dynamic linking should be avoided when possible.
267+
268+
For this reason, by default, when the `-shared` flag use used to build a shared
269+
library, Emscripten will produce an ``.so`` library that is actually just a
270+
regular ``.o`` object file (Under the hood it uses `ld -r` to combine objects
271+
into a single larger object). When these faux "shared libraries" are linked
272+
into your application they are effectively linked as static libraries. When
273+
building these shared libraries *Emcc* will ignore other shared libraries on the
274+
command line. This is to ensure that the same dynamic library is not linked
275+
multiple times in intermediate build stages, which would result in duplicate
276+
symbol errors.
277+
278+
See :ref:`experimental support <Dynamic-Linking>` for how to build true dynamic
279+
libraries, which can be linked together either at load time, or at runtime (via
280+
dlopen).
275281

276282

277283
Configure may run checks that appear to fail

site/source/docs/compiling/Dynamic-Linking.rst

+64-54
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,16 @@
44
Dynamic Linking
55
===============
66

7-
.. note:: Dynamic linking in emscripten is still somewhat experimental and subject to change. This documentation is also curently somewhat outdated the in the process of being refreshed.
7+
.. note:: This documentation is somewhat outdated and is in the process of being refreshed.
88

99
Emscripten supports linking object files (and ar archives that contain
1010
object files) statically. This lets most build systems work with Emscripten
1111
with little or no changes (see :ref:`Building-Projects`).
1212

1313
In addition, Emscripten also has support for a form of **dynamic** linking of
1414
WebAssembly modules. This can add overhead, so for best performance static
15-
linking should still be prefered. However, this overhead can can be reduced
16-
with the use of certain command line flags, see below for details.
15+
linking should still be preferred. However, this overhead can can be reduced
16+
with the use of certain command line flags. See below for details.
1717

1818
Background
1919
==========
@@ -63,9 +63,9 @@ Overview of Dynamic Linking
6363
===========================
6464

6565
Emscripten’s dynamic linking is fairly simple: you build several
66-
separate code “modules” containing JavaScript, and can link them at
67-
runtime. The linking basically connects up the unresolved symbols in
68-
each module with the implemented symbols in the others, in the simplest
66+
separate code “modules” from your source code, and can link them at
67+
runtime. The linking basically connects up the undefined symbols in
68+
each module with the defined symbols in the others, in the simplest
6969
of ways. It does not currently support some corner cases.
7070

7171
System libraries do utilize some more advanced linking features that
@@ -77,19 +77,17 @@ the problem as follows: There are two types of shared modules:
7777

7878
A project should contain **exactly one** main module. It can then be
7979
linked at runtime to multiple side modules. This model also makes other
80-
things simpler, like only the singleton main module has the general
81-
JavaScript environment setup code to connect to the web page and so
82-
forth; side modules contain just the pure compiled WebAssembly and
83-
nothing more.
80+
things simpler, like only the singleton main module includes the
81+
JavaScript environment and side modules are pure WebAssembly modules.
8482

85-
The one tricky aspect to this design is that a side module might need a
86-
system library that the main doesn’t know about. See the section on
83+
The one tricky aspect to this design is that a side module might depend on a
84+
system library that the main module did not depend on. See the section on
8785
system libraries, below, for how to handle that.
8886

8987
Note that the “main module” doesn’t need to contain the ``main()``
9088
function. It could just as easily be in a side module. What makes the
91-
main module the “main” module is just that there is only one main
92-
module, and only it has system libs linked in.
89+
main module the “main” module is that there is only one main module, and
90+
only it has system libraries linked in.
9391

9492
(Note that system libraries are linked in to the main module
9593
*statically*. We still have some optimizations from doing it that way,
@@ -99,58 +97,61 @@ Practical Details
9997
=================
10098

10199
If you want to jump to see running code, you can look in the test suite.
102-
There are ``test_dylink_*`` tests that test general dynamic linking, and
100+
There are ``test_dylink_*`` tests that test dynamic linking in general, and
103101
``test_dlfcn_*`` tests that test ``dlopen()`` specifically. Otherwise,
104102
we describe the procedure now.
105103

106-
General Dynamic Linking
107-
-----------------------
104+
Load-time Dynamic Linking
105+
-------------------------
108106

109-
- Build one part of your code as the main module, using
110-
``-s MAIN_MODULE=1``.
111-
- Build other parts of your code as side modules, using
112-
``-s SIDE_MODULE=1``.
107+
Load-time dynamic linking refers to case when the side module are loaded
108+
along with the main module, during startup and they are linked together
109+
before your application starts to run.
113110

114-
Important: since 1.38.16 you need to set ``-s EXPORT_ALL=1`` (for
115-
SIDE_MODULEs, as well as the MAIN_MODULE if it exposes functions to the
116-
modules). Alternatively, use ``-s EXPORTED_FUNCTIONS`` to declare the
117-
exported functions. Without either of them, modules are useless.
111+
- Build one part of your code as the main module, linking it using
112+
``-s MAIN_MODULE``.
113+
- Build other parts of your code as side modules, linking it using
114+
``-s SIDE_MODULE``.
118115

119-
Note that both should have suffix ``.js`` or ``.wasm`` (``emcc`` uses
120-
suffixes to know what to emit). If you want, you can then rename the
121-
side modules to ``.so`` or such (but it is just a superficial change.)
116+
For the main module the output suffix should be ``.js`` (the WebAssembly
117+
file will be generated alongside it just like normal). For the side
118+
module the output will be just a WebAssembly module we recommend the
119+
output suffix ``.wasm`` or ``.so`` (which is the shared libraries suffix used by
120+
UNIX systems).
122121

123-
You then need to tell the main module to load the sides. You can do that
124-
using the ``Module`` object, with something like
122+
In order to have the side modules loaded at startup you need to tell the
123+
main module about their existence. You can do this by specifying them on
124+
the command line when you link the main module. e.g.
125125

126126
::
127127

128-
Module.dynamicLibraries = ['libsomething.js'];
128+
emcc -s MAIN_MODULE main.c libsomething.wasm
129129

130-
At runtime, when you run the main module, if it sees
131-
``dynamicLibraries`` on ``Module``, then it loads them one by one and
132-
links them. The running application then can access code from any of the
130+
At runtime, the JavaScript loading code will load ``libsomthing.wasm`` (along
131+
with any other side modules) along with the main module before the application
132+
starts to run. The running application then can access code from any of the
133133
modules linked together.
134134

135-
``dlopen()`` Dynamic Linking
136-
----------------------------
135+
Runtime Dynamic Linking with ``dlopen()``
136+
-----------------------------------------
137137

138-
``dlopen()`` is slightly simpler than general dynamic linking. The
139-
procedure begins in the same way, with the same flags used to build the
140-
main and side modules. The difference is that you do not use
141-
``Module.dynamicLibraries``; instead, you must load the side module into
142-
the filesystem, so that ``dlopen`` (or ``fopen``, etc.) can access it
143-
(except for ``dlopen(NULL)`` which means to open the current executable,
144-
which just works without filesystem integration). That’s basically it -
145-
you can then use ``dlopen(), dlsym()``, etc. normally.
138+
Runtime dynamic linking can be performed by the calling the ``dlopen()``
139+
function to load side modules after the program is already running. The
140+
procedure begins in the same way, with the same flags used to build the main and
141+
side modules. The difference is that you do not specify the side modules on the
142+
command line when linking the main module; instead, you must load the side
143+
module into the filesystem, so that ``dlopen`` (or ``fopen``, etc.) can access
144+
it (except for ``dlopen(NULL)`` which means to open the current executable,
145+
which just works without filesystem integration). That’s basically it - you can
146+
then use ``dlopen(), dlsym()``, etc. normally.
146147

147148
System Libraries
148149
================
149150

150151
As mentioned earlier, system libraries are handled in a special way by
151152
the Emscripten linker, and in dynamic linking, only the main module is
152153
linked against system libraries. A possible issue is if a side module
153-
needs a system library that the main does not. If so, you’ll get a
154+
depends on a system library that the main does not. If so, you’ll get a
154155
runtime error. This section explains what to do to fix that.
155156

156157
To get around this, you can build the main module with
@@ -173,10 +174,16 @@ also possible to use normal dead code elimination, by building with
173174
``-s MAIN_MODULE=2`` (instead of 1). In that mode, the main module is
174175
built normally, with no special behavior for keeping code alive. It is
175176
then your responsibility to make sure that code that side modules need
176-
is kept alive. You can do this in the usual ways, like adding to
177-
``EXPORTED_FUNCTIONS``. See ``other.test_minimal_dynamic`` for an
178-
example of this in action. There is also the corresponding
179-
``-s SIDE_MODULE=2`` for side modules.
177+
is kept alive. You can do this either by adding to ``EXPORTED_FUNCTIONS`` or
178+
tagging the symbol ``EMSCRIPTEN_KEEPALIVE`` in the source code.
179+
See ``other.test_minimal_dynamic`` for an example of this in action.
180+
181+
If you are doing load time dynamic linking then any symbols needed by
182+
the side modules specified on the command line will be kept alive
183+
automatically. For this reason we strongly recommend using ``MAIN_MODULE=2``
184+
when doing load time dynamic linking.
185+
186+
There is also the corresponding ``-s SIDE_MODULE=2`` for side modules.
180187

181188
Miscellaneous Notes
182189
===================
@@ -191,7 +198,7 @@ symbols remain unresolved, and code can start to run even if there are.
191198
It will run successfully if they are not called in practice. If they
192199
are, you will get a runtime error. What went wrong should be clear from
193200
the stack trace (in an unminified build); building with
194-
``-s ASSERTIONS=1`` can help some more.
201+
``-s ASSERTIONS`` can help some more.
195202

196203
Limitations
197204
-----------
@@ -202,11 +209,14 @@ Limitations
202209
startup
203210
`[doc] <https://emscripten.org/docs/porting/files/packaging_files.html#preloading-files>`__
204211
`[discuss] <https://groups.google.com/forum/#!topic/emscripten-discuss/cE3hUV3fDSw>`__.
205-
- See also `webAssembly standalone <https://github.com/emscripten-core/emscripten/wiki/WebAssembly-Standalone>`_` for more on side modules in this context.
206212

207213
Pthreads support
208214
----------------
209215

210-
Dynamic linking + pthreads is not supported. It would require new wasm
211-
spec features (a way to share the Table), or some serious workarounds in
212-
the toolchain.
216+
Dynamic linking + pthreads is is still experimental. While you can link with
217+
``MAIN_MODULE`` and ``-pthread`` emscripten will produce a warning by default
218+
when you do this.
219+
220+
While load-time dynamic linking should largely work and does not have any major
221+
known issues, runtime dynamic linking (with ``dlopen()``) has limited support
222+
when used with pthreads.

0 commit comments

Comments
 (0)