I'm trying to diagnose strange GHC linking behavior which, as far as I can tell, only occurs on macOS. I feel a bit out of my league debugging this, so I'm hoping someone knows what is causing this.

When building the Haskell libffi library [1], it will link pass -lffi to GHC. Typically, most installations of libffi will include both a static library (libffi.a) and a shared library (libffi.{so,dylib,dll}). My impression is that when the linker finds both, it will default to the shared library. This is definitely the case on Linux and Windows, at least.

An exception to this rule is macOS, however. On macOS, building libffi always appears to default to linking against the static version of libffi, even when a dynamic version is also available. To reproduce this phenomenon, check out libffi [1] and run the following commands:

    $ brew install libffi # If it is not already installed
    $ cabal build ctime
    $ otool -L $(cabal list-bin ctime)

The output reveals that the compiled executable does not dynamically link against libffi.dylib:

    $ otool -L $(cabal list-bin ctime)
    /Users/rscott/Documents/Hacking/Haskell/libffi/dist-newstyle/build/x86_64-osx/ghc-8.10.7/libffi-examples-0.1/x/ctime/build/ctime/ctime:
            /usr/lib/libiconv.2.dylib (compatibility version 7.0.0, current version 7.0.0)
            /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1281.100.1)
            /usr/lib/libcharset.1.dylib (compatibility version 2.0.0, current version 2.0.0)

This is exceedingly strange, since my Hombrew installation does in fact provide libffi.dylib:

    $ ls -alh ~/Software/homebrew/Cellar/libffi/3.4.2/lib/
    total 232
    drwxr-xr-x   6 rscott  1340850540   192B Aug  7 09:38 .
    drwxr-xr-x  11 rscott  1340850540   352B Aug  7 08:51 ..
    -rw-r--r--   1 rscott  1340850540    70K Aug  7 08:51 libffi.8.dylib
    -r--r--r--   1 rscott  1340850540    41K Jun 28  2021 libffi.a
    lrwxr-xr-x   1 rscott  1340850540    14B Jun 28  2021 libffi.dylib -> libffi.8.dylib
    drwxr-xr-x   3 rscott  1340850540    96B Aug  7 08:51 pkgconfig

What's more, this only seems to happen when building the libffi library in particular. If I try building another library that has a C extra-libraries dependency, such as HsOpenSSL, then I can find its dynamic dependencies (libssl.dylib and libcrypto.dylib) using otool:

    $ otool -L dist-newstyle/build/x86_64-osx/ghc-8.10.7/HsOpenSSL-0.11.7.2/build/test-dsa/test-dsa
    dist-newstyle/build/x86_64-osx/ghc-8.10.7/HsOpenSSL-0.11.7.2/build/test-dsa/test-dsa:
            /usr/local/opt/openssl@1.1/lib/libssl.1.1.dylib (compatibility version 1.1.0, current version 1.1.0)
            /usr/local/opt/openssl@1.1/lib/libcrypto.1.1.dylib (compatibility version 1.1.0, current version 1.1.0)
            /usr/lib/libiconv.2.dylib (compatibility version 7.0.0, current version 7.0.0)
            /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1281.100.1)
            /usr/lib/libcharset.1.dylib (compatibility version 2.0.0, current version 2.0.0)

I'm at a bit of a loss trying to figure out why this only happens for libffi, and only on macOS. To make things even stranger, this only seems to happen when using GHC. If I try to compile a simple libffi C program using -lffi, for instance, then otool finds libffi.dylib. Is there something about GHC's linking behavior that would cause this?

Ryan S.
-----
[1] https://github.com/remiturk/libffi