You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

336 lines
17 KiB

<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.</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>
</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.</p>