There are two basic steps to compiling Duktape:
tools/configure.py
to prepare
Duktape source and header files for compilation. The requested Duktape
configuration is described using configure.py command line options,
see Configuring Duktape for build.
For example:
$ 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
$ gcc -O2 -Wall -otest -I/tmp/output /tmp/output/duktape.c my_application.c -lm
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 system-install.rst.
DUK_OPT_xxx
feature options are no longer supported in
Duktape 2.x. All configuration information is embedded in duk_config.h
and/or autogenerated sources and headers.
The Duktape distributable contains preconfigured sources and headers with a few variants:
src/
: a single source file version which consists of
duk_config.h
, duktape.h
, and duktape.c
.src-noline/
: same as src/
but with no #line
directives in the combined source file; this matters in some environments,
see https://github.com/svaarala/duktape/pull/363.src-separate/
: a separate source files version which consists
of duk_config.h
, duktape.h
, and a set of separate
source files. The single source file version is preferred, but separate
files work better with some toolchains.These preconfigured sources provide automatic platform, compiler, and architecture detection and use the Duktape default configuration:
configure.py
with the --dll
option to do that.
The configure.py
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 Proxy
object support disabled:
# 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
Configuration options given to configure.py
affect several
different aspects of the prepared header and source files, for example:
DUK_USE_xxx
) which are provided by the
duk_config.h
configuration header. The configuration
header also handles platform, architecture, and compiler detection, and
all other aspects of platform portability.Math
and JSON
.The configure.py
utility requires Python 2.x support. If your
build environment doesn't support Python 2.x, you can run configure.py
on a different platform and compile the resulting files in your build environment.
Even if the default options are OK, it's recommended that you run
configure.py
as part of your build instead of using the
preconfigured sources. Custom options may be necessary on e.g. low memory
platforms. See
Configuring Duktape for build
for more practical details.
Some commonly needed configuration options are:
stdout
to stderr
), and will then call abort()
.
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
How to handle fatal errors.setjmp()
and longjmp()
(or their variants) for internal long control transfers. If you're
compiling with a C++ compiler you may want to use
DUK_USE_CPP_EXCEPTIONS
which causes Duktape to use C++
exceptions for long control transfers and allows scope-based resource
management (automatic destructors, etc; sometimes referred to as
RAII)
in Duktape/C functions to work as expected. With MSVC be careful to
avoid the /EHsc
exception model (use e.g. /EHs
instead) because the "c" option causes MSVC to assume extern
C functions cannot throw C++ exceptions.declspec()
declarations for DLL library symbols. Use the
--dll
option when running configure.py
to
enable them for Duktape symbols.There are two supported memory management alternatives:
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.
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.
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:
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:
duktape.h
in application code. 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.duk_config.h
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.Recommended compiler options for GCC/clang, use similar options for your compiler:
-std=c99
: recommended to ensure C99 semantics
which improve C type detection and allows Duktape to use variadic
macros.-Wall
: recommended to catch potential issues early.-Os
: optimize for smallest footprint, which is usually
desired when embedding Duktape. -O2
is a good compromise
for performance optimized builds.-fomit-frame-pointer
: omit frame pointer, further reduces
footprint but may interfere with debugging (leave out from debug builds).-fstrict-aliasing
: use strict aliasing rules, Duktape
is compatible with these and they improve the resulting C code.--dll
is needed when Duktape is built as
a DLL, at least when compiling for Windows.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.
-Wall
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 -Wextra
in gcc/clang or
/W4
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.
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.
The duktape.h
header contains the necessary glue to make all
of these combinations work. Specifically, all symbols needed by Duktape
public API are inside a extern "C" { ... }
wrapper when compiled
with a C++ compiler. This ensures that such symbols are defined and used
without C++ name mangling. Specifically:
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:
$ 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
One fix is to use g++
for linking:
$ 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
Because duk_config.h
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.
By default scope-based resource management (sometimes referred to as
RAII)
won't work in Duktape/C functions because Duktape uses
longjmp()
for internal long control transfers, bypassing
C++ stack unwind mechanisms. You can use DUK_USE_CPP_EXCEPTIONS
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 /EHsc
exception model (use e.g.
/EHs
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.:
if (MSVC) string( REPLACE "/EHsc" "/EHs" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}" ) endif()