rules_foreign_cc icon indicating copy to clipboard operation
rules_foreign_cc copied to clipboard

foreign_cc-produced shared library can't be found by dependent binaries at runtime

Open dc6c opened this issue 2 years ago • 2 comments

I can build external libraries using the cmake rule, but when I try to use them as a dependency of a cc_test or cc_binary, on Windows they build but fail at runtime with an error that the shared libraries can't be loaded. Example using ZSTD:

WORKSPACE:

workspace(name = "zstd_build")
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")

# rules for building non-Bazel projects
http_archive(
    name = "rules_foreign_cc",
    url = "https://github.com/bazelbuild/rules_foreign_cc/archive/refs/tags/0.9.0.tar.gz",
    strip_prefix = "rules_foreign_cc-0.9.0",
    sha256 = "2a4d07cd64b0719b39a7c12218a3e507672b82a97b98c6a89d38565894cf7c51",
)

load("@rules_foreign_cc//foreign_cc:repositories.bzl", "rules_foreign_cc_dependencies")
rules_foreign_cc_dependencies()

_ZSTD_ALL_CONTENT = """\
filegroup(
    name = "zstd_all",
    srcs = glob(["**"]),
    visibility = ["//visibility:public"],
)
"""

# libzstd source repository
http_archive(
    name = "zstd",
    build_file_content = _ZSTD_ALL_CONTENT,
    url = "https://github.com/facebook/zstd/releases/download/v1.5.5/zstd-1.5.5.tar.gz",
    strip_prefix = "zstd-1.5.5",
    sha256 = "9c4396cc829cfae319a6e2615202e82aad41372073482fce286fac78646d3ee4",
)

third_party/zstd/BUILD:

load("@rules_foreign_cc//foreign_cc:defs.bzl", "cmake")

cmake(
  name = "zstd",
  working_directory = "build/cmake",
  visibility = ["//visibility:public"],
  lib_source = "@zstd//:zstd_all",
  install = True,
)

BUILD:

cc_test(
  name = "hello_test",
  size = "small",
  srcs = ["hello_test.cc"],
  deps = [
      "//third_party/zstd",
  ],
)

hello_test.cc

#include <zstd.h>

int main() {
    size_t cSize = 3;
    const char cBuf[] = "foo";
    // Read the content size from the frame header should fail with an illegal header format
    unsigned long long const rSize = ZSTD_getFrameContentSize(cBuf, cSize);
    return !(rSize == ZSTD_CONTENTSIZE_ERROR);
}

bazel build ... succeeds with no errors, and I can see the DLL in bazel-bin/third_party/zstd/zstd/bin/zstd.dll and hello_test executable in bazel-bin/hello_test.exe. Running the .exe results in "error while loading shared libraries: zstd.dll: cannot open shared object file: No such file or directory". If I manually copy it into bazel-bin/, everything works fine.

Is there a step I'm missing that would ensure the shared libraries produced by the cmake rule get placed together with binaries that depend on them?

Platform:

  • Windows 10
  • MSVC 2019
  • Bazel 5.1.0 (Chocolatey)

dc6c avatar May 01 '23 18:05 dc6c

Pretty sure bazel uses -rpath to find dynamically linked libraries, which doesn't really have good replacements in Windows. If the license allows, you should try to link statically. If that's not possible, you can try to follow some of the suggestions here: https://stackoverflow.com/questions/107888/is-there-a-windows-msvc-equivalent-to-the-rpath-linker-flag

My experience with bazel suggests that bazel is not great with dynamic linking + rules_foreign_cc. For example, even if your target binary has the correct rpaths, they won't be propogated to the dependent libraries.

DolceTriade avatar Jun 12 '23 22:06 DolceTriade