[Solved] Cabal `c-sources` and symbols in GHC's object files

The Cabal file of the Win32 package has a c-sources which includes cbits/errors.c which provides a C function getErrorMessage; Win32 uses it to create a Haskell function with the same name.

I created a package which copied that C function (verbatim). However, when I compiled a second package that depended on both Win32 and my new package, the GHC runtime linker complained about a fatal error: it found a duplicate definition for symbol getErrorMessage while processing an object file for my new package and said it was previously defined in an object file for the Win32 package. (This resulted in a ā€œpanic! (the ā€˜impossibleā€™ happened)ā€ and a suggestion it be reported as a GHC bug.)

My question is this: why does the C function result in a symbol in the GHC object file for the package? I had assumed - probably wrongly - that the C function would be somehow ā€˜internalā€™ to the package. Is it possible to specify that the C function is only ā€˜internalā€™? If not, does that mean that C functions used in c-sources need to be named in a way that makes name clashes unlikely?

Perhaps what I experienced was genuinely a GHC 9.2.7 bug; I canā€™t reproduce something similar with a minimal reproducible example.

There is no name spacing for C functions. If you copy the file youā€™ll have to rename the functions to prevent duplicate symbols.

The alternative is: if you depend on Win32 anyway, to just not define the c functions at all and rely on the Win32 library to bring in the definitions.

1 Like

When compiling C files with GHC, all GHC does is add some defines and c compiler flags and then invoked the c compiler. This will produce an object file (.o), which is then together with the object files for the haskell modules, linked into a shared library/executable (and/or archived into an .a archive on object files aka static library).

From the linkers perspective there is just a bunch of symbols (function names and data references), where and how they came about, it doesnā€™t know. It does however require them to be unique.

This if you link two libraries that contain the same name, the linker will complain.

Option one: prefix the function names in C, Iā€™d you want the duplicates to survive.
Option two: just assume the symbols to exist without implementing them, because you know they come in from a dependency at link time anyway and this will be found. M

1 Like

I now have a minimal reproducible example, following this 2012 GHC issue: #6107: GHCi runtime linker cannot link with duplicate common symbols Ā· Issues Ā· Glasgow Haskell Compiler / GHC Ā· GitLab. A Template Haskell splice triggers the problem; without the splice, GHC does not seem to be bothered by the object files containing the same symbol.

Iā€™ll have a look. GHCs in-memory linker is fairly basic. Iā€™m a bit confused as to why this would not happen with the final link product, but maybe the linker ca see that something is not used or itā€™s not passed as a dependency to the linker.

1 Like

For anyone reading this, @RyanGlScott and others left some comments on the gitlab ticket. Iā€™ve also left an analysis as promised.

1 Like

Many thanks for your and @RyanGlScottā€™s thorough analysis at the GitLab tickets - I found that very helpful.

What I take from this is the following: if you are using C functions etc in c-sources it is a good idea to choose names for them that other packages are unlikely to duplicate.

Yes. Use some library/package specific prefix to prevent name clashes.

ret_type <pkg>_<function>(argsā€¦) { ā€¦ }