Viktor Csimma
Viktor Csimma

Reputation: 33

GHC libraries with FFI on Windows have "foreign export" symbols missing

I have the following Haskell source, from which I would like to compile a static library that can be linked into a C program:

{-# LANGUAGE ForeignFunctionInterface #-}

module Lib where

printHello :: IO ()
printHello = putStrLn "Hello world"
foreign export ccall printHello :: IO ()

The command I use is:

ghc -staticlib Lib.hs

But this produces a main.exe file instead of a liba.a (as I would expect based on the documentation).

And it does not work; when I try to link it with C sources (either with GHC or plain GCC), I get undefined references. Oddly enough, it finds the functions pre-defined in the FFI (like hs_init and hs_exit); only the one I export (printHello) is missing.

I tried to inspect the file with nm and I get Lib.o: file format not recognized (and no printHello symbol).

Even more interestingly, if I compile directly against the Lib.o file and the main.exe file (using GHC), it seems to work. So Lib.o itself is probably not corrupted. I also tried to swap the object with ar but it didn't help.

The goal would be to produce a static library (so something with a .a or .lib extension) that I can link into C programs, using either GHC or GCC. For this, it would probably be necessary to see the symbols exported using nm.

DLLs get compiled with a correct name; however, the missing symbols are still there (I followed the documentation for Win32 DLLs).

I've read the documentation for flags, the FFI, ar, nm, ld and I still don't know how to deal with this.

If this helps, I'm using GHC 9.2.8 on Windows 10 1903.

Thank you very much in advance:)

Update:

I've also tried using ar this way:

create libb.a
addlib liba.a
addlib Lib.o
save
end

A dummy C program which simply called printHello:

void hs_init(int* argc, char*** argv);
void hs_exit(void);
void printHello(void);

int main(int argc, char** argv) {  
  hs_init(&argc, &argv);
  printHello();
  hs_exit();
  return 0;
}

Still, system libraries had to be specified for GCC for some reason. But after that, it worked:

gcc main.c libb.a -lpthread -lws2_32 -lntdll -lDbghelp -lOle32 -lRpcrt4 -lucrt -lgdi32 -lwinmm

But, for a more complex program, with the same technique I get the following error on running:

a.exe: setEvent: SetEvent: permission denied

And it seems to happen when calling a user-defined foreign exported function.

Upvotes: 0

Views: 79

Answers (0)

Related Questions