5

I'm trying to build a Haskell executable with an FFI against some C++ sources.

I have a C header (cstuff/foo.h) like this:

#ifndef _FOO_H_
#define _FOO_H_

#include <somecppheader.c> // Some header outside of my control with C++ constructs

void foo();

#endif

The implementation of foo shouldn't matter. It does something and uses something declared in somecppheader.h along the way.

The executable section in the Cabal file looks like this:

executable botprog
  main-is:             Main.hsc
  other-extensions:    ForeignFunctionInterface
  build-depends:       base >=4.7 && <4.8
  build-tools:         hsc2hs
  default-language:    Haskell2010
  include-dirs:        cstuff
  c-sources:           cstuff/foo.cpp
  pkgconfig-depends:   somelib -- The one that contains somecppheader.h

Main.hsc looks something like this:

{-# LANGUAGE ForeignFunctionInterface #-}

#include <foo.h>
foreign import ccall "foo.h foo" :: IO ()

main = foo >> putStrLn "Called foo."

hsc2hs isn't actually needed in this example, it's just used to, to trigger the error i'm trying to describe.

The problem is that somecppheader.h is a C++ header with C++ specific constructs and the include of foo.h seems to compile it as a C header, which fails, because of C++ constructs, like class definitions.

How can I tell hsc2hs or Cabal that foo.h needs to be compiled with g++, rather than gcc?

Kritzefitz
  • 2,644
  • 1
  • 20
  • 35
  • 1
    I think you can try setting `-c g++ -l g++` in `hsc2hs-options`. – n. m. could be an AI Sep 06 '15 at 12:07
  • So I tried building with `cabal build --hsc2hs-options '-c g++' --hsc2hs-options '-l g++'`, but it didn't work. – Kritzefitz Sep 06 '15 at 12:13
  • 1
    I see that cabal is broken in this respect (it supplies its own cc and ld arguments that override yours). You may want to make your header file C-compatible instead. Don't include any C++ headers in it, or #ifdef out any C++ features. You need to make `foo` C-callable, so use `extern "C"` for it (also suitably #ifdef'ed-out). – n. m. could be an AI Sep 06 '15 at 13:32
  • @n.m. I can't do this, because I need a type definition from the C++ header. I can't define it in my own header, because it may change from platform to platform. – Kritzefitz Sep 06 '15 at 17:59
  • 3
    The shotgun approach `cabal build --with-gcc=g++ --with-ld=g++` works in the simple case, but you have to be extra c areful with it if you have other C sources. You still need to wrap the declaration of `foo` in `extern "C"` but you don't have to #ifdef it out. – n. m. could be an AI Sep 06 '15 at 19:05
  • 1
    OR you can use a wrapper for hsc2hs that calls the real hsc2hs but processes the options the way you want (i.e. discards the default --cc and --ld passed by cabal and uses those you provide). Haven't tried this method but I'm pretty sure it will work (because it works when I call hsc2hs myself with the right options). – n. m. could be an AI Sep 06 '15 at 19:13
  • @n.m. Specifying --with-gcc=g++ (and ld) works and doesn't cause problems, as I only have C++ sources. Thank you! It's not as nice for distributing, because I didn't find a way, to embed these options in the cabal file yet. – Kritzefitz Sep 06 '15 at 20:14
  • @n.m.since your comment resolved the question, maybe you should submit it as an answer? – sclv Feb 25 '16 at 22:36

0 Answers0