Linking a dynamic lib using Bazel on MacOS

Viewed 1583

I'm compiling my program using Bazel, and I have a dependency on Intel TBB. Intel TBB only provide dynamic libraries (no static) for good reasons (if you are curious: ctrl+f static here).

In my bazel WORKSPACE I defined that rule :

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

and in my "inteltbb.BUILD" I have:

cc_library(
  name = "dynamic_lib",
  srcs = ["build/macos_intel64_clang_cc8.1.0_os10.12.5_debug/libtbb_debug.dylib"],
  hdrs = glob(["include/**/*.h"]),
  visibility = ["//visibility:public"],
  strip_include_prefix = "include/"
)

Then in my final program (under the cc_binary rule) I have:

deps = [
    "@inteltbb//:dynamic_lib", [...]

It compile properly, find the headers successfully but at runtime it crashes saying:

____Running command line: bazel-bin/build-game
dyld: Library not loaded: @rpath/libtbb_debug.dylib
  Referenced from: /private/var/tmp/_bazel_dmabin/526b91f44cfc47d856222c6b20765cc8/execroot/__main__/bazel-out/darwin_x86_64-fastbuild/bin/build-game
  Reason: image not found

I check under the "bazel-bin" folder (where the executable is symlink for runtime execution: bazel-bin/build-game.runfiles/main/) and I do have:

  • the symlink for the executable (build-game)
  • a folder called (brace yourself): _solib_darwin_x86_64/_U@inteltbb_S_S_Cdynamic_Ulib___Uexternal_Sinteltbb_Sbuild_Smacos_Uintel64_U clang_Ucc8.1.0_Uos10.12.5_Udebug that contain my libtbb_debug.dylib for intel tbb.

Also when I run: otool -l build-game | grep LC_RPATH -A2 the result is:

      cmd LC_RPATH
  cmdsize 152
     path $ORIGIN/_solib_darwin_x86_64/_U@inteltbb_S_S_Cdynamic_Ulib___Uexternal_Sinteltbb_Sbuild_Smacos_Uintel64_Uclang_Ucc8.1.0_Uos10.12.5_Udebug (offset 12)

I don't understand why my executable doesn't find my dylib. I can't find anything wrong about the otool output but I'm not a mac expert (at all). Any idea is welcome.

[edit] If I edit the executable using otool to replace the path to the dylib like that:

@executable_path/_solib_darwin_x86_64/_U@inteltbb_S_S_Cdynamic_Ulib___Uexternal_Sinteltbb_Slib/libtbb_debug.dylib

Then it works fine. I doesn't feel right that bazel force me to do that at every compilation :/

[edit 2] A few people asked me the line I used to modify the path of the lib in the executable. First run:

otool -L build-game

To spot the path of the lib you want to change. In my case it was: @rpath/libtbb_debug.dylib. After that run:

install_name_tool -change @rpath/libtbb_debug.dylib @executable_path/_solib_darwin_x86_64/_U@inteltbb_S_S_Cdynamic_Ulib___Uexternal_Sinteltbb_Slib/libtbb_debug.dylib build-game

to change the path. Note that you can use @executable_path to make it relative to the binary path or you can put an absolute path, up to you.

1 Answers
Related