forked from svaarala/duktape
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcompiling.html
More file actions
354 lines (313 loc) · 18 KB
/
compiling.html
File metadata and controls
354 lines (313 loc) · 18 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
<a name="installing-system-wide"></a> <!-- for old links -->
<h1 id="compiling">Compiling</h1>
<h2>Overview</h2>
<p>There are two basic steps to compiling Duktape:</p>
<ul>
<li><b>Configuration</b>. Use <code>tools/configure.py</code> to prepare
Duktape source and header files for compilation. The requested Duktape
configuration is described using configure.py command line options,
see <a href="http://wiki.duktape.org/Configuring.html">Configuring Duktape for build</a>.
For example:
<pre>
$ python2 tools/configure.py --output-directory /tmp/output -DDUK_USE_FASTINT -UDUK_USE_ES6_PROXY
$ ls /tmp/output/
duk_config.h duk_source_meta.json duktape.c duktape.h
</pre></li>
<li><b>Compilation</b>. Ensure that the generated header files are in the compiler
include search path, and include the generate source file(s) in your application
build; there's no official Duktape build script or Makefile.
For example:
<pre>
$ gcc -O2 -Wall -otest -I/tmp/output /tmp/output/duktape.c my_application.c -lm
</pre></li>
</ul>
<p>While Duktape is usually compiled together with your application, you can
also build it into a static or shared library. Duktape can also be installed
as a system-wide library, see
<a href="https://github.com/svaarala/duktape/blob/master/doc/system-install.rst">system-install.rst</a>.</p>
<div class="note">
The <code>DUK_OPT_xxx</code> feature options are no longer supported in
Duktape 2.x. All configuration information is embedded in <code>duk_config.h</code>
and/or autogenerated sources and headers.
</div>
<a name="timing-sensitive-options"></a> <!-- for old links -->
<a name="memory-constrained-options"></a> <!-- for old links -->
<a name="performance-sensitive-options"></a> <!-- for old links -->
<h2>Configuring</h2>
<h3>Preconfigured sources and default configuration</h3>
<p>The Duktape distributable contains preconfigured sources and headers with
a few variants:</p>
<ul>
<li><code>src/</code>: a single source file version which consists of
<code>duk_config.h</code>, <code>duktape.h</code>, and <code>duktape.c</code>.</li>
<li><code>src-noline/</code>: same as <code>src/</code> but with no <code>#line</code>
directives in the combined source file; this matters in some environments,
see <a href="https://github.com/svaarala/duktape/pull/363">https://github.com/svaarala/duktape/pull/363</a>.</li>
<li><code>src-separate/</code>: a separate source files version which consists
of <code>duk_config.h</code>, <code>duktape.h</code>, and a set of separate
source files. The single source file version is preferred, but separate
files work better with some toolchains.</li>
</ul>
<p>These preconfigured sources provide automatic platform, compiler, and
architecture detection and use the Duktape default configuration:</p>
<ul>
<li>Full ECMAScript E5/E5.1 compliance
(including the optional
<a href="http://www.ecma-international.org/ecma-262/5.1/#sec-B">Annex B</a>
features), except for intentional real world compatibility deviations
(see <a href="#custombehavior">Custom behavior</a>)</li>
<li>ES2015 typed array and Node.js Buffer support</li>
<li>Some features from <a href="#es6features">ECMAScript 2015 (E6)</a> and
<a href="#es7features">ECMAScript 2016 (E7)</a></li>
<li>Packed value representation (8 bytes per value) when available,
unpacked value representation (usually 16 bytes per value) when not</li>
<li>Reference counting and mark-and-sweep garbage collection</li>
<li>Full error messages and tracebacks</li>
<li>No debug printing, no asserts, etc</li>
<li>All portable fast paths enabled</li>
</ul>
<div class="note">
The preconfigured sources cannot be used to build Duktape into a Windows DLL.
Run <code>configure.py</code> with the <code>--dll</code> option to do that.
</div>
<h3>Running configure.py to customize Duktape configuration</h3>
<p>The <code>configure.py</code> utility prepares Duktape source and header
files for a specific configuration described using command line options.
For example, to prepare Duktape sources for a DLL build with fastint
support enabled and ECMAScript 6 <code>Proxy</code> object support disabled:</p>
<pre>
# Default output format is single source file (--separate-sources for separate
# sources) and no #line directives (--line-directives to enable them).
$ python2 tools/configure.py \
--output-directory /tmp/output \
--dll \
-DDUK_USE_FASTINT \
-UDUK_USE_ES6_PROXY
# The output directory /tmp/output contains the header and source files to
# be included in your build.
$ ls /tmp/output
duk_config.h duk_source_meta.json duktape.c duktape.h
</pre>
<p>Configuration options given to <code>configure.py</code> affect several
different aspects of the prepared header and source files, for example:</p>
<ul>
<li>Optional features in Duktape source code are enabled/disabled using config
options (<code>DUK_USE_xxx</code>) which are provided by the
<code>duk_config.h</code> configuration header. The configuration
header also handles platform, architecture, and compiler detection, and
all other aspects of platform portability.</li>
<li>Built-in objects and strings are read in from metadata files and bit-packed
built-in initialization data is generated. It's also possible to supply
custom metadata files to add custom built-in bindings or modify standard
built-ins such as <code>Math</code> and <code>JSON</code>.</li>
<li>When using "ROM built-ins", built-in objects and strings are placed into the
read-only code section to reduce RAM footprint. The necessary source code
for built-in object/string initializers is autogenerated by configure.py.
Also custom built-ins can be placed in the read-only code section.</li>
<li>Unicode data files (UnicodeData.txt and SpecialCasing.txt) are converted into
bit-packed run-time Unicode tables. The Unicode data files can also be
overridden e.g. to reduce Unicode table footprint.</li>
</ul>
<p>The <code>configure.py</code> utility requires Python 2.x support. If your
build environment doesn't support Python 2.x, you can run <code>configure.py</code>
on a different platform and compile the resulting files in your build environment.</p>
<p>Even if the default options are OK, it's recommended that you run
<code>configure.py</code> as part of your build instead of using the
preconfigured sources. Custom options may be necessary on e.g. low memory
platforms. See
<a href="http://wiki.duktape.org/Configuring.html">Configuring Duktape for build</a>
for more practical details.</p>
<a name="duktape-date-provider"></a> <!-- for old links -->
<h3>Commonly needed configuration options</h3>
<p>Some commonly needed configuration options are:</p>
<ul>
<li><b>DUK_USE_FATAL_HANDLER, strongly recommended</b>. The built-in default fatal
error handler will write a debug log message (but <b>won't</b> write anything to
<code>stdout</code> to <code>stderr</code>), and will then call <code>abort()</code>.
If that fails, it enters an infinite loop to ensure execution doesn't resume
after a fatal error. This is usually not the best behavior for production
applications which may already have better fatal error recovery mechanisms.
To replace the default fatal handler, see
<a href="http://wiki.duktape.org/HowtoFatalErrors.html">How to handle fatal errors</a>.</li>
<li><b>Long control transfer: setjmp/longjmp and C++ exceptions</b>.
By default Duktape uses <code>setjmp()</code> and <code>longjmp()</code>
(or their variants) for internal long control transfers. If you're
compiling with a C++ compiler you may want to use
<code>DUK_USE_CPP_EXCEPTIONS</code> which causes Duktape to use C++
exceptions for long control transfers and allows scope-based resource
management (automatic destructors, etc; sometimes referred to as
<a href="https://en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization">RAII</a>)
in Duktape/C functions to work as expected. With MSVC be careful to
avoid the <code>/EHsc</code> exception model (use e.g. <code>/EHs</code>
instead) because the "c" option causes MSVC to assume extern
C functions cannot throw C++ exceptions.</li>
<li><b>Windows DLL build</b>. Windows DLL build requires some
<code>declspec()</code> declarations for DLL library symbols. Use the
<code>--dll</code> option when running <code>configure.py</code> to
enable them for Duktape symbols.</li>
<li><b>Forced byte order or alignment</b>. If you're using Duktape on a
platform where Duktape's automatic feature detection doesn't (yet) work,
you may need to force a specific byte order or alignment requirements
during the configuration step.</li>
<li><b>Date built-in on exotic platforms</b>. When porting to new or exotic
platforms the Duktape built-in Date support may not work on the platform.
In such a case you can implement an external "Date provider" which allows
you to provide the necessary date/time primitives without Duktape changes. See
<a href="https://github.com/svaarala/duktape/blob/master/doc/datetime.rst">datetime.rst</a>.</li>
<li><b>Native stack check macro</b>. When the target has a small stack, it
may be useful to define
<code><a href="https://github.com/svaarala/duktape/blob/master/config/config-options/DUK_USE_NATIVE_STACK_CHECK.yaml">DUK_USE_NATIVE_STACK_CHECK()</a></code>
macro which provides a better safeguard against stack exhaustion than stack
depth limits which can't account for the size of stack frames.</li>
</ul>
<!-- XXX: this might be more suited to the Wiki -->
<h3>Memory management alternatives</h3>
<p>There are two supported memory management alternatives:</p>
<ul>
<li><b>Reference counting and mark-and-sweep (default)</b>: heap objects are
freed immediately when they become unreachable except for objects
participating in unreachable reference cycles. Such objects are freed by
a periodic voluntary, stop the world mark-and-sweep collection.
Mark-and-sweep is also used as the emergency garbage collector if
memory allocation fails.</li>
<li><b>Mark-and-sweep only</b>: reduces code footprint and memory footprint
(heap headers don't need to store a reference count), but there is more
memory usage variance than in the default case. The frequency of voluntary,
stop the world mark-and-sweep collections is also higher than in the default
case where reference counting is expected to handle almost all memory
management. Voluntary (non-emergency) mark-and-sweep can be disabled via
config options.</li>
</ul>
<p>Reference counting relies on mark-and-sweep to handle reference cycles.
For example, every ECMAScript function instance is required to be in a
reference loop with an automatic prototype object created for the function.
You can break this loop manually if you wish. For internal technical reasons,
named function expressions are also in a reference loop; this loop cannot be
broken from user code and only mark-and-sweep can collect such functions.</p>
<h2>Compiling</h2>
<h3>General guidelines</h3>
<p>Duktape doesn't have an official Makefile or a build script: given the
number of different portability targets, maintaining an official build
script would be difficult. Instead, you should add Duktape to your existing
build process in whatever way is most natural.</p>
<p>Duktape is compiled with a C or C++ compiler (C99 is recommended)
and then linked to your program in some way; the exact details vary between
platforms and toolchains. For example, you can:</p>
<ul>
<li>Compile Duktape together with your program without an explicit linking
step.</li>
<li>Compile Duktape as a static library, and link the static library with
your program.</li>
<li>Compile Duktape as a dynamic library, and link the dynamic library with
your program.</li>
<li>Compile Duktape as a dynamic library, install it system-wide, and use it
from several applications; see
<a href="https://github.com/svaarala/duktape/blob/master/doc/system-install.rst">system-install.rst</a>.</li>
</ul>
<p>All Duktape API functions are potentially macros, and the implementation
of a certain API primitive may change between a macro and an actual function
even between compatible releases. Some Duktape configuration options also
affect binary compatibility. To ensure binary compatibility:</p>
<ul>
<li><b>Include <code>duktape.h</code> in application code</b>. This is
good practice in general, but without the header your compiler will
incorrectly assume that all Duktape API functions are actual functions
which will cause linking to fail.</li>
<li><b>Use the same prepared Duktape sources and headers when compiling
Duktape and your application</b>. This ensures Duktape and your application
are compiled with the exactly same Duktape version and configuration.
This is especially important when Duktape is compiled as a library in a
separate compilation step.</li>
<li><b>Use the same compiler when compiling Duktape and your application</b>.
Using a different compiler may affect e.g. type detection in the Duktape
<code>duk_config.h</code> header or function calling convention, and thus
compromise binary compatibility. In practice compilers can be mixed to
some extent, e.g. GCC and Clang are generally compatible.</li>
</ul>
<h3>Recommended compiler options</h3>
<p>Recommended compiler options for GCC/clang, use similar options for
your compiler:</p>
<ul>
<li><code>-std=c99</code>: recommended to ensure C99 semantics
which improve C type detection and allows Duktape to use variadic
macros.</li>
<li><code>-Wall</code>: recommended to catch potential issues early.</li>
<li><code>-Os</code>: optimize for smallest footprint, which is usually
desired when embedding Duktape. <code>-O2</code> is a good compromise
for performance optimized builds.</li>
<li><code>-fomit-frame-pointer</code>: omit frame pointer, further reduces
footprint but may interfere with debugging (leave out from debug builds).</li>
<li><code>-fstrict-aliasing</code>: use strict aliasing rules, Duktape
is compatible with these and they improve the resulting C code.</li>
<li>Configure.py with <code>--dll</code> is needed when Duktape is built as
a DLL, at least when compiling for Windows.</li>
</ul>
<h3>Compilation warnings</h3>
<p>Duktape usually compiles without warnings when using a mainstream compiler
(e.g. GCC, Clang, MSVC, or MinGW) in C99 mode with warnings enabled (e.g.
<code>-Wall</code> in gcc/clang), and using default Duktape configuration
options. There may be some warnings when using a non-mainstream compiler,
very strict warning levels (like <code>-Wextra</code> in gcc/clang or
<code>/W4</code> in MSVC), or non-default Duktape configuration options.
Eliminating compilation warnings for all compilers and all configuration
option combinations is very difficult and is thus explicitly not a project
goal. You're still encouraged to report warnings so that they can be fixed
if possible.</p>
<h3 id="duktape-cplusplus">Using a C++ compiler</h3>
<p>Duktape works with both C and C++ compilers and applications. You can
compile Duktape and the application with a C or a C++ compiler in any
combination. Even so, it is recommended to compile both Duktape and the
application with the same compiler (i.e. both with a C compiler or both
with a C++ compiler) and with the same compiler options.</p>
<p>The <code>duktape.h</code> header contains the necessary glue to make all
of these combinations work. Specifically, all symbols needed by Duktape
public API are inside a <code>extern "C" { ... }</code> wrapper when compiled
with a C++ compiler. This ensures that such symbols are defined and used
without C++ name mangling. Specifically:</p>
<ul>
<li>When compiling Duktape itself with a C++ compiler, symbols needed by
Duktape public API are not mangled. Other Duktape internal symbols will
be mangled, but are not externally visible and should thus cause no
problems even if the application is compiled with a C compiler.</li>
<li>When compiling an application with a C++ compiler, the wrapper ensures
that Duktape public API symbols used by the application are looked up
without mangling.</li>
</ul>
<p>If you mix C and C++ compilation, you should do the final linking with the
C++ toolchain. At least when mixing gcc/g++ you may encounter something like:</p>
<pre>
$ g++ -c -o duktape.o -Isrc/ src/duktape.c
$ gcc -c -o duk_cmdline.o -Isrc/ examples/cmdline/duk_cmdline.c
$ gcc -o duk duktape.o duk_cmdline.o -lm
duktape.o:(.eh_frame+0x1ab): undefined reference to `__gxx_personality_v0'
collect2: error: ld returned 1 exit status
</pre>
<p>One fix is to use <code>g++</code> for linking:</p>
<pre>
$ g++ -c -o duktape.o -Isrc/ src/duktape.c
$ gcc -c -o duk_cmdline.o -Isrc/ examples/cmdline/duk_cmdline.c
$ g++ -o duk duktape.o duk_cmdline.o -lm
</pre>
<p>Because <code>duk_config.h</code> selects C/C++ data types needed by
Duktape and also does other feature detection, mixing C and C++ compilers
could theoretically cause the C and C++ compilers to end up with different
active features or data types. If that were to happen, Duktape and the
application would be binary incompatible which would lead to very difficult
to diagnose issues. This is usually not an issue, but to avoid the potential,
compile Duktape and the application with the same compiler.</p>
<p>By default scope-based resource management (sometimes referred to as
<a href="https://en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization">RAII</a>)
won't work in Duktape/C functions because Duktape uses
<code>longjmp()</code> for internal long control transfers, bypassing
C++ stack unwind mechanisms. You can use <code>DUK_USE_CPP_EXCEPTIONS</code>
to cause Duktape to use C++ exceptions for internal long control transfers,
which allows scope-based resource management to work in Duktape/C functions.
With MSVC be careful to avoid the <code>/EHsc</code> exception model (use e.g.
<code>/EHs</code> instead) because the "c" option causes MSVC to assume extern
C functions cannot throw C++ exceptions. When using MSVC and CMake you can use
e.g.:</p>
<pre>
if (MSVC)
string( REPLACE "/EHsc" "/EHs" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}" )
endif()
</pre>