Compiler modes / FFI / forcing CPP
Philip Hölzenspies
p.k.f.holzenspies at utwente.nl
Wed Apr 29 18:48:43 EDT 2009
Dear GHC-ers,
From earlier questions, it seems no one wants to get down and dirty
with linker tricks in ghc. I'm now looking over an alternative solution.
I'm currently trying to use SDL. There's a wrapper on hackage, which
works fine under Linux, but it takes some tinkering under Mac OS X,
because OS X needs instantiated Cocoa stuff for the SDL entry point.
Long story short, to use SDL with ghc on the OS X, a little wrapper c-
file needs to be written, because the linker will find a 'main'
function in libSDLmain.a which expects a function 'SDL_main' as an
entry point into the user code.
I have written a small c file that can be used to wrap around any
haskell module (see below), based on the macro (cpp) definition of
MODNAME. I can compile this c file with gcc, for, let's say a module
Foo with entry point Foo.bar (so, if we could still have ghc make the
entry point, we would say ghc -main-is Foo.bar):
gcc -c -DMODNAME=Foo -D"ENTRYPOINT=bar();" -o Foo_entry.o entry.c
However, this only works after I explicitly add ghc's "include" dir to
my search path so that HsFFI.h can be found. Before I had this pre-
processor trick, I could simply feed the c file to ghc, together with
all my haskell files. Ghc then simply adds the correct includes and
feeds the c file to the c compiler. Unfortunately, giving ghc the
above -D options doesn't do much good.
The problem seems to lie with the suffix recognition ghc does. I took
this from [1]. With the -cpp switch, the c pre-processor is used, but
only when the file has a .hs suffix. The c compiler is only run when
the file has a .c suffix. Using -x .hs puts the file correctly through
the c pre-processor, but then fails to compile it, because it's not
haskell code. Using -x .c doesn't do pre-processing (even with -cpp).
I tried to compile this wrapper using this command (assume now that we
have Foo.hsMain as an entry point):
ghc -cpp -pgmP cc -optP-E -DMODNAME=Foo -o Foo_entry.o entry.c
(Notice that you can't just use cpp, because on OS X that's a shell
script that doesn't provide CPPs full strength, so you want "cc -E".)
This doesn't work:
entry.c:27:2: error: #error MODNAME undefined!
Trying to be more explicit as to where the -D should go:
ghc -cpp -pgmP cc -optP-E -optP-DMODNAME=Foo -o Foo_entry.o entry.c
does exactly the same. Now faking .hs:
ghc -cpp -pgmP cc -optP-E -optP-DMODNAME=Foo -o Foo_entry.o -x hs
entry.c
which produces the error (coming from stdio.h inclusion):
/usr/include/i386/_types.h:37:28: parse error on input `;'
So, I guess my question is: Is it possible to let a c input file of
ghc pass through *both* the c pre-processor *and* the c compiler?
Kind regards,
Philip
[1] GHC User's Guide: Section 5.4: Modes of operation
http://www.haskell.org/ghc/docs/latest/html/users_guide/modes.html
entry.c:
#ifdef MODNAME
#ifndef ENTRYPOINT
#define ENTRYPOINT hsMain();
#endif
#include <stdio.h>
#include "HsFFI.h"
#define __HS_mangle(name) __stginit_ ## name
#define __Xpand_HS_mangle(nm) __HS_mangle(nm)
#define __hs_mangled_module __Xpand_HS_mangle( MODNAME )
#define __pack_quotes(x) #x
#define __calc_include(x) __pack_quotes(x##_stub.h)
#define __Xpand_calc_include(x) __calc_include(x)
#include __Xpand_calc_include(MODNAME)
extern void __hs_mangled_module ( void );
int
SDL_main(int argc, char *argv[])
{
hs_init(&argc, &argv);
hs_add_root(__hs_mangled_module);
ENTRYPOINT
hs_exit();
return 0;
}
#else /* MODNAME */
#error MODNAME undefined!
#endif /* MODNAME */
More information about the Glasgow-haskell-users
mailing list