tweag / rules_haskell

Haskell rules for Bazel.
https://haskell.build
Apache License 2.0
266 stars 81 forks source link

Bazel-built Shared C Libraries and the GHCi linker #720

Open moritzkiefer-da opened 5 years ago

moritzkiefer-da commented 5 years ago

Let’s say I have two cc_librarys a and b where a depends on b. The shared libraries built by Bazel underlink, i.e., the shared library doesn’t declare that it depends on other shared libraries instead this is tracked internally by Bazel.

If I make a Haskell library that depends on a, I will end up with extra-libraries: a b in my package config. The GHCi linker (triggered by TH) will go through those libraries and call dlopen(libname, RTLD_LAZY|RTLD_LOCAL). It respects the order in extra-libraries so it will first try to load a. If you are lucky, RTLD_LAZY works and despite a referencing b. However, this won’t work in general as RTLD_LAZY only works for function references and even then it can be overridden by things like -Wl,-z,now which, to make matters worse, is passed by default by Bazel. In that case dlopen will error out with an undefined symbol error and builds fail.

Sadly, I don’t know a nice solution to this:

I don’t have a self-contained test case that I can make public right now but we’re seeing this with the official grpc library, i.e., "@com_github_grpc_grpc//:grpc" which we get viahttp_archive`:

http_archive(
    name = "com_github_grpc_grpc"
    strip_prefix = "grpc-1.19.0",
    urls = ["https://github.com/grpc/grpc/archive/v1.19.0.tar.gz"],
    sha256 = "1d54cd95ed276c42c276e0a3df8ab33ee41968b73af14023c03a19db48f82e73",
)
moritzkiefer-da commented 5 years ago

For now, I managed to work around this by creating a rule that creates fat static and dynamic libraries. Since these don’t depend on any other libraries this avoids the problem but obviously it’s not pretty.

Note also that while @Profpatsch tagged this as REPL improvements, this also affects TH so even if you’re willing to give up on a repl, this might mean that you are unable to build your code.

Profpatsch commented 5 years ago

Has this problem been solved by recent improvements to the REPL support in rules_haskell?

aherrmann commented 5 years ago

@Profpatsch As @moritzkiefer-da pointed this does not only concern the REPL but also template Haskell. The issue still persists.

Changing the order in extra-libraries will break static linking afaict since in that case a should come first.

This would indeed break static linking.

Get Bazel to properly declare dependencies of the shared library.

Using the new Starlark C++ API it's possible to create a custom cc_library rule that does not underlink. Using aspects, it's also possible to adapt an existing cc_library target to do the same thing. However, this requires rebuilding the corresponding C library. So, that's probably not something we'd want rules_haskell to do automatically.

aherrmann commented 2 years ago

In https://github.com/tweag/rules_haskell/issues/1696 @jcpetruzza provided a great repro for this issue. https://github.com/tweag/rules_haskell/issues/1696#issuecomment-1040346953 demonstrates that adding the "missing" NEEDED entry fixes the loading error.