Link errors when trying to create a c++ binary depending on ITK libraries using bazel (undefined references)

162 views Asked by At

So I'm working on a project where I have the following, simplified structure

./
┗━ utils
  ┗━ BUILD
┗━ tool1
  ┗━ BUILD
┗━ itk.BUILD
┗━ WORKSPACE

in essence i'm trying to build a binary tool1 that depends on a library utils which in turn depends on itk

here are the contents of the utils/BUILD file (simplified):

cc_library(
    name = "utils",
    srcs = glob(
        [
            "utils/*.cpp",
            "include/**",
        ],
    ),
    hdrs = glob([
        "include/*.h",
    ]),
    copts = [
        "-DITK_USE_SYSTEM_ZLIB",
    ],
    includes = ["./include"]
    linkopts = ["-ldl", "-lz", "-lm", "-lgomp", "-lpthread", "-lcrypto", "-lrt"],
    visibility = ["//visibility:public"],
    deps = [
        "@itk//:itk_libs",
    ],
)

and tool1/BUILD:

cc_binary(
    name = "tool1",
    srcs = ["tool1.cpp"],
    deps = [
        "//:utils",
    ],
)

ITK has been pre-compiled in say third_party/itk, it's included as a local repo in the WORKSPACE file:

new_local_repository(
    name = "itk",
    path = "third_party/itk",
    build_file = "itk.BUILD",
)

itk.BUILD just creates a collective library:

cc_library(
    name = "itk_libs",
    srcs = glob(["lib/**/*.a"]),
    hdrs = glob([
        "include/ITK-4.13/**/*.h",
        "include/ITK-4.13/*.h",
        "include/ITK-4.13/**/*.hxx",
        "include/ITK-4.13/*.hxx",
        "include/ITK-4.13/**/*.txx",
        "include/ITK-4.13/*.txx",
    ]),
    strip_include_prefix = "include/ITK-4.13",
    visibility = ["//visibility:public"],
)

when building utils using bazel bazel build //:utils it succeeds, however, when running bazel build //tool1 i get a bunch of link errors like this one:

external/itk/lib/libitkvnl_algo-4.13.a(vnl_cholesky.cxx.o): In function `vnl_cholesky::vnl_cholesky(vnl_matrix<double> const&, vnl_cholesky::Operation)':
vnl_cholesky.cxx:(.text+0x99): undefined reference to `v3p_netlib_dpofa_'

I'm a the end of my wits, been struggling with this for a few weeks now.

What I don't understand is that //:utils compiles successfully, the link errors only occur when building //tool1.

I tried to change the order of the libraries in the command line and run it manually, same results. I tried to add itk directly as a dependency to tool1, that is add @itk//:itk_libs to deps in tool1/BUILD, same results

I must be missing something, I would appreciate it if someone could point me to the right direction. I'm almost certain the problem is something with ITK that I'm unaware of, not necessarily with bazel.

Edit: I was getting a bunch of other errors from other dependecies, which are now resolved, curiously the only errors remaining are all related to libitkvnl_algo-4.13.a.

Edit 2 (for reference after accepting an answer):

I wasn't clear on some bits, the missing references were all from ITK's own libraries, which were all compiled and existing in the command line that's produced by bazel. Also I tried reordering one library in the command line before asking the question, while that didn't work at first, now after Paul's answer I realised, it wasn't just one library that needs reordering.

1

There are 1 answers

1
Paul Janzen On BEST ANSWER

If the archive libitkvnl_algo.a depends on symbols defined in libv3p_netlib.a, then (on Linux) the order of the libraries on the link line for creating the binary matters: libv3p_netlib.a must appear after libitkvnl_algo.a. You won't necessarily get a usable ordering if you just use glob; you may have to explicitly list the libraries in the srcs. Or you can construct one cc_library per .a file and use deps to reflect the correct dependency graph; then bazel will give you the correct link-line ordering automatically.