Sunday, April 7, 2013

Shared Object with GHC 7

I was hitting my face on my desk for a few hours today trying to work this out. So here's my post to hopefully save anyone else who ended up stuck on this. I made a bash script to do it all, so here's the script. Note that this makes dynamic shared objects (.so files), still trying to figure out how to do it statically.

#!/bin/bash

TMPHELP="module_init.c"
FILENAME=${1%.*}
declare -i EXITCODE

cat <<TMPHELPER > $TMPHELP
#define CAT(a,b) XCAT(a,b)
#define XCAT(a,b) a ## b
#define STR(a) XSTR(a)
#define XSTR(a) #a

#include <HsFFI.h>

extern void CAT(__stginit_, MODULE)(void);

static void library_init(void) __attribute__((constructor));
static void library_init(void) {
    /* This seems to be a no-op, but it makes the GHCRTS envvar work. */
    static char *argv[] = { STR(MODULE) ".so", 0 }, **argv_ = argv;
    static int argc = 1;

    hs_init(&argc, &argv_);
    hs_add_root(CAT(__stginit_, MODULE));
}

static void library_exit(void) __attribute__((destructor));
static void library_exit(void) {
    hs_exit();
}
TMPHELPER

ghc -O2 --make -dynamic -shared -fPIC $2 -o "${FILENAME}.so" -optl-Wl,-rpath,/usr/lib/ghc/ -lHSrts_debug-ghc7.4.1 $1 $TMPHELP  >&1

EXITCODE=$?

set -x

if [[ $EXITCODE -eq 0 ]] ; then
    rm "${FILENAME}.hi"
    rm "${FILENAME}.o"
fi

if [[ -f ${FILENAME}_stub.h ]] ; then
    rm "${FILENAME}_stub.h"
fi

rm $TMPHELP
exit $EXITCODE

I'm honestly not 100% sure how everything works, but my main goal was to create shared objects so I could use them in Python. One thing to note if you are loading a shared object into Python made with Haskell, the IO functions don't seem to display on IDLE (works fine on the terminal).

No comments:

Post a Comment