haskell / c2hs

c2hs is a pre-processor for Haskell FFI bindings to C libraries
http://hackage.haskell.org/package/c2hs
Other
197 stars 50 forks source link

Linker error with sublibraries and `__c2hs__wrapped__`-functions #292

Open selkie-diligent opened 4 months ago

selkie-diligent commented 4 months ago

Error Description

If you use a sublibrary for .chs-files and c2hs generates .chs.c-files with __c2hs__wrapped__-functions, then this fails with an error that these symbols cannot be found.

❯ cabal build
Resolving dependencies...
Build profile: -w ghc-9.4.8 -O1
In order, the following will be built (use -v for more details):
 - tmp-ifRBXdAUos-0.1.0.0 (lib:tmp-ifRBXdAUos-sub) (first run)
 - tmp-ifRBXdAUos-0.1.0.0 (lib) (first run)
 - tmp-ifRBXdAUos-0.1.0.0 (exe:tmp-ifRBXdAUos) (first run)
Configuring library 'tmp-ifRBXdAUos-sub' for tmp-ifRBXdAUos-0.1.0.0..
Preprocessing library 'tmp-ifRBXdAUos-sub' for tmp-ifRBXdAUos-0.1.0.0..
Building library 'tmp-ifRBXdAUos-sub' for tmp-ifRBXdAUos-0.1.0.0..
[1 of 1] Compiling MySubLib         ( /tmp/tmp.ifRBXdAUos/dist-newstyle/build/x86_64-linux/ghc-9.4.8/tmp-ifRBXdAUos-0.1.0.0/l/tmp-ifRBXdAUos-sub/build/tmp-ifRBXdAUos-sub/MySubLib.hs, /tmp/tmp.ifRBXdAUos/dist-newstyle/build/x86_64-linux/ghc-9.4.8/tmp-ifRBXdAUos-0.1.0.0/l/tmp-ifRBXdAUos-sub/build/tmp-ifRBXdAUos-sub/MySubLib.o, /tmp/tmp.ifRBXdAUos/dist-newstyle/build/x86_64-linux/ghc-9.4.8/tmp-ifRBXdAUos-0.1.0.0/l/tmp-ifRBXdAUos-sub/build/tmp-ifRBXdAUos-sub/MySubLib.dyn_o )
Configuring library for tmp-ifRBXdAUos-0.1.0.0..
Preprocessing library for tmp-ifRBXdAUos-0.1.0.0..
Building library for tmp-ifRBXdAUos-0.1.0.0..
[1 of 1] Compiling MyLib            ( src/MyLib.hs, /tmp/tmp.ifRBXdAUos/dist-newstyle/build/x86_64-linux/ghc-9.4.8/tmp-ifRBXdAUos-0.1.0.0/build/MyLib.o, /tmp/tmp.ifRBXdAUos/dist-newstyle/build/x86_64-linux/ghc-9.4.8/tmp-ifRBXdAUos-0.1.0.0/build/MyLib.dyn_o )
Configuring executable 'tmp-ifRBXdAUos' for tmp-ifRBXdAUos-0.1.0.0..
Preprocessing executable 'tmp-ifRBXdAUos' for tmp-ifRBXdAUos-0.1.0.0..
Building executable 'tmp-ifRBXdAUos' for tmp-ifRBXdAUos-0.1.0.0..
[1 of 1] Compiling Main             ( app/Main.hs, /tmp/tmp.ifRBXdAUos/dist-newstyle/build/x86_64-linux/ghc-9.4.8/tmp-ifRBXdAUos-0.1.0.0/x/tmp-ifRBXdAUos/build/tmp-ifRBXdAUos/tmp-ifRBXdAUos-tmp/Main.o )
[2 of 2] Linking /tmp/tmp.ifRBXdAUos/dist-newstyle/build/x86_64-linux/ghc-9.4.8/tmp-ifRBXdAUos-0.1.0.0/x/tmp-ifRBXdAUos/build/tmp-ifRBXdAUos/tmp-ifRBXdAUos
/tmp/tmp.ifRBXdAUos/dist-newstyle/build/x86_64-linux/ghc-9.4.8/tmp-ifRBXdAUos-0.1.0.0/build/libHStmp-ifRBXdAUos-0.1.0.0-inplace.a(MyLib.o):function tmpzmifRBXdAUoszm0zi1zi0zi0zminplace_MyLib_someFunc1_info:(.text+0xd7): error: undefined reference to '__c2hs_wrapped__pw_check_library_version'
collect2: error: ld returned 1 exit status
ghc-9.4.8: `gcc' failed in phase `Linker'. (Exit code: 1)
Error: cabal: Failed to build exe:tmp-ifRBXdAUos from tmp-ifRBXdAUos-0.1.0.0.

To Reproduce

  1. Create new project
/tmp
❯ cd $(mktemp -d)

/tmp/tmp.ifRBXdAUos
❯ ghc --version; cabal --version
The Glorious Glasgow Haskell Compilation System, version 9.4.8
cabal-install version 3.10.2.1
compiled using version 3.10.2.1 of the Cabal library

/tmp/tmp.ifRBXdAUos
❯ cabal init --libandexe -nm
[Log] Guessing dependencies...
[Log] Guessing dependencies...
[Log] Using cabal specification: 3.0
[Warning] unknown license type, you must put a copy in LICENSE yourself.
[Log] Creating fresh file CHANGELOG.md...
[Log] Creating fresh directory ./src...
[Log] Creating fresh file src/MyLib.hs...
[Log] Creating fresh directory ./app...
[Log] Creating fresh file app/Main.hs...
[Log] Creating fresh file tmp-ifRBXdAUos.cabal...
[Warning] No synopsis given. You should edit the .cabal file and add one.
[Info] You may want to edit the .cabal file and add a Description field.
  1. Edit some files

Edit ./tmp-ifRBXdAUos.cabal

cabal-version:   3.0
name:            tmp-ifRBXdAUos
version:         0.1.0.0
license:         NONE
author:          Unknown
maintainer:      Unknown
build-type:      Simple
extra-doc-files: CHANGELOG.md

common warnings
    ghc-options: -Wall

library
    import:           warnings
    exposed-modules:  MyLib
    build-depends:    base ^>=4.17.2.1, tmp-ifRBXdAUos-sub
    hs-source-dirs:   src
    default-language: Haskell2010

library tmp-ifRBXdAUos-sub
    import:           warnings
    exposed-modules:  MySubLib
    build-depends:    base ^>=4.17.2.1
    hs-source-dirs:   src-sub
    default-language: Haskell2010
    build-tool-depends: c2hs:c2hs >= 0.28.8
    pkgconfig-depends: libpipewire-0.3

executable tmp-ifRBXdAUos
    import:           warnings
    main-is:          Main.hs
    build-depends:
        base ^>=4.17.2.1,
        tmp-ifRBXdAUos

    hs-source-dirs:   app
    default-language: Haskell2010

Add ./src-sub/MySubLib.chs

module MySubLib ( pwCheckLibraryVersion ) where

#include <pipewire/version.h>
{#fun pw_check_library_version as ^ {`Int', `Int', `Int'} -> `Bool'#}

Edit ./src/MyLib.hs

module MyLib (someFunc) where

import MySubLib

someFunc :: IO ()
someFunc = pwCheckLibraryVersion 0 0 0 >>= print
  1. Run cabal build

Remark

If the sublibrary is removed and everything is moved to the main library, then it works as you would expect.