Skip to content
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

macOS-only runtime dyld error with dynamically-linked binary indirectly depending on linkstatic=True library #11552

Open
bjacob opened this issue Jun 5, 2020 · 5 comments
Labels
P4 This is either out of scope or we don't have bandwidth to review a PR. (No assignee) platform: apple team-Rules-CPP Issues for C++ rules type: bug

Comments

@bjacob
Copy link

bjacob commented Jun 5, 2020

Summary: See attached minimal testcase. On macOS, Bazel produces a binary that fails at runtime to dynamically link to its dependency. This happens in the following scenario: a binary "c" with linkstatic=False depends on a library "b" with linkstatic=False, itself depending on a library "a" with linkstatic=True. Each of these aspects is necessary to reproduce the issue:

  • Seems macOS-specific: the testcase runs fine on Linux.
  • If "c" depends directly on "a" instead of through the intermediate "b", the error disappears.
  • If "c" is linkstatic=True, the error disappears.
  • If "a" is linkstatic=False, the error disappears.

Minimal testcase attached: bazel_link_error.tar.gz

BUILD file from the testcase pasted here for your convenience:

# "a" is a library with linkstatic=True
cc_library(
  name = "a",
  srcs = ["a.cc"],
  hdrs = ["a.h"],
  linkstatic = True,  # Omitting this avoids the link error in "c"
)

# "b" has linkstatic=False (default) and wraps the library "a"
cc_library(
  name = "b",
  srcs = ["b.cc"],
  hdrs = ["b.h"],
  deps = [":a"],
  # Setting linkstatic=True avoids the link error in "c"
)

# cc_test is similar to cc_binary except that linkstatic defaults to
# False in cc_test, vs. True in cc_binary. This testcases reproduces
# also with cc_binary with linkstatic=False.
cc_test(
  name = "c",
  srcs = ["c.cc"],
  deps = [":b"],
)

To reproduce, untar the archive and run //:c

tar xfzv bazel_link_error.tar.gz
cd bazel_link_error
bazel run //:c

Actual result:

Executing tests from //:c
-----------------------------------------------------------------------------
dyld: lazy symbol binding failed: Symbol not found: __Z1av
  Referenced from: /private/var/tmp/_bazel_benoitjacob/b022d434d29bde6eb5304b94cf8f92cb/execroot/__main__/bazel-out/darwin-fastbuild/bin/c.runfiles/__main__/_solib_darwin_x86_64//liblibb.so
  Expected in: flat namespace

dyld: Symbol not found: __Z1av
  Referenced from: /private/var/tmp/_bazel_benoitjacob/b022d434d29bde6eb5304b94cf8f92cb/execroot/__main__/bazel-out/darwin-fastbuild/bin/c.runfiles/__main__/_solib_darwin_x86_64//liblibb.so
  Expected in: flat namespace
copybara-service bot pushed a commit to google/ruy that referenced this issue Jun 5, 2020
copybara-service bot pushed a commit to google/ruy that referenced this issue Jun 5, 2020
copybara-service bot pushed a commit to google/ruy that referenced this issue Jun 5, 2020
copybara-service bot pushed a commit to google/ruy that referenced this issue Jun 5, 2020
@aiuto aiuto added z-team-Apple Deprecated. Send to rules_apple, or label team-Rules-CPP + platform:apple untriaged team-Rules-CPP Issues for C++ rules and removed z-team-Apple Deprecated. Send to rules_apple, or label team-Rules-CPP + platform:apple labels Jun 6, 2020
tensorflow-copybara pushed a commit to tensorflow/tensorflow that referenced this issue Jun 8, 2020
PiperOrigin-RevId: 315313209
Change-Id: I5d86e271b7733cf16d9b8de98d1c2ee69764608f
@c-mita c-mita added P2 We'll consider working on this in future. (Assignee optional) and removed untriaged labels Aug 28, 2020
@oquenchil oquenchil added P3 We're not considering working on this, but happy to review a PR. (No assignee) type: bug and removed P2 We'll consider working on this in future. (Assignee optional) labels Nov 19, 2020
@oquenchil oquenchil added platform: apple P1 I'll work on this now. (Assignee required) and removed P3 We're not considering working on this, but happy to review a PR. (No assignee) labels Sep 29, 2021
@oquenchil
Copy link
Contributor

oquenchil commented Sep 30, 2021

@keith @googlewalt Hello Keith and Walt,

I'm not sure if what's happening here is a Bazel bug or a limitation of linkers on macOS. This is the command line I got on Linux:

-o
bazel-out/k8-fastbuild/bin/c
-Wl,-rpath,$ORIGIN/_solib_k8/
-Lbazel-out/k8-fastbuild/bin/_solib_k8
-Wl,-S
-fuse-ld=/usr/AAAAAA/clang11/bin/ld.lld
-Wl,-no-as-needed
-Wl,-z,relro,-z,now
-B/usr/AAAAAAAA/clang11/bin
bazel-out/k8-fastbuild/bin/_objs/c/c.pic.o
-llibb
-Wl,--start-lib
bazel-out/k8-fastbuild/bin/_objs/a/a.pic.o
-Wl,--end-lib
-lstdc++
-lm

This is the command line my colleague got on macOS:

-o
bazel-out/darwin-fastbuild/bin/c
-Wl,-rpath,@loader_path/_solib_darwin/
-Lbazel-out/darwin-fastbuild/bin/_solib_darwin
bazel-out/darwin-fastbuild/bin/_objs/c/c.pic.o
-llibb
bazel-out/darwin-fastbuild/bin/liba.a
-Wl,-S
-undefined
dynamic_lookup
-headerpad_max_install_names

I see that liba.a is passed rather than the object file but that should not matter (that's enabled with the feature SUPPORTS_START_END_LIB). What is happening here is that a shared object (libb) depends on a which is not linked dynamically against it but is linked into the binary (c). Since when we build b we don't have the binary yet, we don't even know what it would be called, then we can't make a be a dynamic dependency of b. On Linux this works, you don't have to link a dynamically to b, it will find the symbols later in the binary but I know that this doesn't work on Windows. Is it the same case on macOS?

If that limitation exists, then this just won't work. If the reason why you have this setup is because you have a precompiled archive that you don't control and they won't provide you with a shared object instead, then what you can do is wrap the precompiled archive in a cc_binary(linkshared=1). If that's not the case and you are compiling everything from source, why do you need this setup?

# "a" is a library with linkstatic=True
cc_binary(
  name = "a",
  srcs = ["liba.a"], # Assuming you just have liba.a
  linkshared = True,
)
cc_library(
  name = "dynamic_a",
  hdrs = ["a.h"],
  srcs = ["a"],
)

# "b" has linkstatic=False (default) and wraps the library "a"
cc_library(
  name = "b",
  srcs = ["b.cc"],
  hdrs = ["b.h"],
  deps = [":dynamic_a"],
  # Setting linkstatic=True avoids the link error in "c"
)

# cc_test is similar to cc_binary except that linkstatic defaults to
# False in cc_test, vs. True in cc_binary. This testcases reproduces
# also with cc_binary with linkstatic=False.
cc_test(
  name = "c",
  srcs = ["c.cc"],
  deps = [":b"],
)

@keith
Copy link
Member

keith commented Sep 30, 2021

I see that liba.a is passed rather than the object file but that should not matter

this isn't particularly true, I don't fully understand your repro case, but can you try to use alwayslink / force_load with your library? more info on another case: bazelbuild/rules_apple#332 (comment)

@googlewalt
Copy link
Contributor

googlewalt commented Oct 1, 2021

This essentially boils down to:

clang++ c.o libb.so liba.a

For this test case to work, the linker needs to pull in symbols from a into the c binary to satisfy undefined symbols in b. This has to be done by the linker (as opposed to anything bazel can do), and ld64 (Apple's linker) does not appear to support this use case.

If "c" depends directly on "a" instead of through the intermediate "b", the error disappears.

I think the error still remains, for the same reason.

@comius comius added P4 This is either out of scope or we don't have bandwidth to review a PR. (No assignee) and removed P1 I'll work on this now. (Assignee required) labels Jan 23, 2024
@comius
Copy link
Contributor

comius commented Jan 23, 2024

It's 2024. This looks like P1 issue since 2021? Is it still relevant?

@googlewalt
Copy link
Contributor

Yeah I think we can close this. I don't think this was a supported use case, and it's WAI.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
P4 This is either out of scope or we don't have bandwidth to review a PR. (No assignee) platform: apple team-Rules-CPP Issues for C++ rules type: bug
Projects
None yet
Development

No branches or pull requests

7 participants