Build Duktape for specific platform (ARM 32/ ARM 64)

506 Views Asked by At

I'm going to use Duktape for javascript evaluation for ARM 32/64 platforms. I want to build Duktape only for specific platform & architecture, not for all range.

It seems, that I can build it successfully:

python tools/configure.py \
    --source-directory src-input \
    --platform linux \
    --architecture arm32 \
    --config-metadata config/ \
    --option-file arm32_config.yaml \
    --output-directory /tmp/arm32    

arm32_config.yaml:

DUK_USE_32BIT_PTRS: true
DUK_USE_64BIT_OPS: false 
DUK_USE_FATAL_HANDLER: false

Build pass usually.That's great!

On Raspberry Pi (use it just for tests):

I have a hello.c:

 #include "duktape.h"

 int main(int argc, char *argv[]) {
   duk_context *ctx = duk_create_heap_default();
   duk_eval_string(ctx, "print('Hello world!');");
   duk_destroy_heap(ctx);
   return 0;
 }

and Makefile.hello file:

 DUKTAPE_SOURCES = src/arm32/duktape.c

 # Compiler options are quite flexible.  GCC versions have a significant impact
 # on the size of -Os code, e.g. gcc-4.6 is much worse than gcc-4.5.

 CC = gcc
 CCOPTS = -Os -pedantic -std=c99 -Wall -fstrict-aliasing -fomit-frame-pointer
 CCOPTS += -I./src/arm32  # for combined sources
 CCLIBS = -lm
 CCOPTS += -DUK_USE_32BIT_PTRS
 CCOPTS += -DUK_USE_64BIT_OPS
 CCOPTS += -DUK_USE_FATAL_HANDLER

 # For debugging, use -O0 -g -ggdb, and don't add -fomit-frame-pointer

 hello: $(DUKTAPE_SOURCES) hello.c
    $(CC) -o $@ $(DEFINES) $(CCOPTS) $(DUKTAPE_SOURCES) hello.c $(CCLIBS)

It also works!

But when I'm trying to start program ./hello I've always recived: Segmentation fault

Could please point out on my mistakes?What have I missed? Thank you in advance!

ps: gcc version 4.9.2 (Raspbian 4.9.2-10)

1

There are 1 best solutions below

4
Sami Vaarala On

The main problem you are most likely having is that you're working from Duktape master (which will become the 2.0.0 release) which no longer provides a built-in "print()" binding. That causes an error to be thrown.

That error is uncaught because you don't have a protected call wrapping the eval call, so that a fatal error occurs. Since you don't provide a fatal error handler (in duk_create_heap() or via DUK_USE_FATAL_HANDLER) that causes the default fatal error behavior which is to cause an intentional segfault (this is so that a debugger can attach).

So the easiest fix is to define a print() binding and maybe add a fatal error handler and/or a protected call for the eval. Here's an example to add a print() binding (before doing the eval):

static duk_ret_t native_print(duk_context *ctx) {
    duk_push_string(ctx, " ");
    duk_insert(ctx, 0);
    duk_join(ctx, duk_get_top(ctx) - 1);
    printf("%s\n", duk_safe_to_string(ctx, -1));
    return 0;
}

/* ... before doing eval(): */
duk_push_c_function(ctx, native_print, DUK_VARARGS);
duk_put_global_string(ctx, "print");

Other minor comments:

  • Duktape duk_config.h detects the platform and target you're building for; Duktape never really builds "for all targets" as far as the resulting binary is concerned. So having multiple platforms in duk_config.h doesn't make the result any bigger for example.
  • You shouldn't need the values in your arm32_config.yaml. ARM32 should be detected automatically.
  • The Makefile.hello you're using is (adapted) from Duktape 1.x while the code you're compiling is from Duktape master. The CCOPTS options will be ignored by Duktape master (they go into tools/configure.py) and their format is wrong in the example, e.g. -DUK_USE_FATAL_HANDLER defines the preprocessor value UK_USE_FATAL_HANDLER.