-
Notifications
You must be signed in to change notification settings - Fork 81
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Link C libraries statically if possible on linkstatic = True binaries #587
Conversation
So these can be used in other `.bzl` files.
I.e. when building a Haskell binary with `linkstatic = True`, then link statically against Haskell and C library dependencies where possible. GHC's default behaviour (following from the linker's behaviour) is to prefer dynamic libraries over static libraries for C library dependencies, even when linking statically against Haskell libraries. By only passing static library versions (unless on static library is available) of C library dependencies as inputs to the linking action, the linker has no choice but to link statically. Closes #580
Test that a Haskell binary compiled with `linkstatic = True`, will only link to static library dependencies (where available), and that a Haskell binary compiled with `linkstatic = False`, will link all its library dependencies dynamically (where available). The test cases assume that for each library dependency both a dynamic and a static version are available, i.e. the default of `linkstatic = False` for library dependencies. Uses `haskell_test` in place of `haskell_binary` to ensure that the resulting binaries can be executed without any runtime linker errors.
57a18f0
to
b64d064
Compare
What do the CC rules do here? If you |
I think I have my answer in example 5 of this section: https://docs.bazel.build/versions/master/be/c-cpp.html#cc_import. So this PR is ultimately bringing us in line with the CC semantics for |
Yes, |
dbg mode enforces static linking in which case the test case for dynamic linking will fail.
`objdump` is not available on the MacOS build. Furthermore, on MacOS only direct library dependencies are listed under the shared library dependencies. Also, on MacOS the dynamic library dependency listed in the binary's header uses the library ID instead of the mangled library path as on Linux. This changes and simplifies the binary-linkstatic-flag tests to work on both Linux and MacOS seemlessly. First, we turn the indirect C library dependency into a direct dependency. Second, instead of checking for shared library dependencies, we directly check for the `value` and `*HsLib_value_closure` symbols. In a statically linked binary both those symbols will be defined directly in the binary. In a dynamically linked binary both symbols will be listed as undefined. The `nm` tool is available on both the Linux and MacOS builds and can list all undefined symbols in the binary.
1903e55
to
b0a7bd7
Compare
binary="$1" | ||
mode="$2" | ||
if [[ $mode = dbg ]]; then | ||
# Skip test in debug builds. Debug mode forces static linking. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice trick!
Closes #580
Changes rules_haskell to prefer linking C library dependencies statically over dynamically on Haskell binary targets with
linkstatic = True
.GHC's default behaviour (following from the linker's behaviour) is to prefer dynamic libraries over static libraries for C library dependencies, even when linking statically against Haskell libraries.
With this change only static versions of C library dependencies are passed as inputs to the linking action - unless no static library is available. This forces the linker to link against static versions of C library dependencies.
Adds a regression test for #580.