Skip to content

Function definition affects linking behavior

Summary

Based on the definition of a Haskell function, the linking fails or doesn't.

Steps to reproduce

I have a file, src/Codec/Archive/Foreign/ArchiveEntry.chs, with various functions, viz.

ft :: CMode -> FileType
ft 0 = error "Bad FileType"
ft i = (fromIntegral <&> toEnum) i

ft' :: CMode -> FileType
ft' i = (fromIntegral <&> toEnum) i

...

{# fun archive_entry_filetype as ^ { `ArchiveEntryPtr' } -> `FileType' ft #}

...

{# fun archive_entry_acl_next_w as ^ { `ArchiveEntryPtr', coerce `EntryACL', castPtr `Ptr EntryACL', castPtr `Ptr EntryACL', castPtr `Ptr EntryACL', id `Ptr CInt', id `Ptr CWString' } -> `CInt' #} 

When I run cabal test, I get

Linking /home/vanessa/programming/haskell/done/libarchive/dist-newstyle/build/x86_64-linux/ghc-8.8.1/libarchive-2.0.0.0/build/libarchive-test/libarchive-test ...
/home/vanessa/programming/haskell/done/libarchive/dist-newstyle/build/x86_64-linux/ghc-8.8.1/libarchive-2.0.0.0/build/libHSlibarchive-2.0.0.0-inplace.a(ArchiveEntry.o):function libarchivezm2zi0zi0zi0zminplace_CodecziArchiveziForeignziArchiveEntry_zdwarchiveEntryAclNextW_info: error: undefined reference to 'archive_entry_acl_next_w'
collect2: error: ld returned 1 exit status
`gcc' failed in phase `Linker'. (Exit code: 1)

That is not so surprising, since archive_entry_acl_next_w is not actually in libarchive.a, as I later found out. However, if I coerce with ft' rather than ft, that is, if I change

{# fun archive_entry_filetype as ^ { `ArchiveEntryPtr' } -> `FileType' ft #}

to

{# fun archive_entry_filetype as ^ { `ArchiveEntryPtr' } -> `FileType' ft' #} 

then cabal test builds a binary and runs!

Expected behavior

Linking should not depend on the definition of other functions.

Environment

  • GHC version used: 8.8.1, 8.6.5, 8.4.4

Optional:

  • Operating System: Linux
  • System Architecture: x86_64
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information