bazelbuild / bazelbuild/bazel

Bad link order with CcSharedLibraryInfo.linker_input

Open
#25,282 0 comments 0 reactions 2 assignees Claimed by @pzembrod View on GitHub
P2 team-Rules-CPP type: bug
Dominant language
Java
Stars
25.8k
Forks
4.6k
Avg merge
2d 20h
Merged PRs (30d)
72

Description

### Description of the bug:

When using `cc_import` in combination with `cc_shared_library`, the `CcSharedLibraryInfo.linker_input` will contain the `.so` files from both the `cc_shared_library` and `cc_import`s. A dependency graph with diamond dependency may then end up in having the same `.so` file specified in `CcSharedLibraryInfo.linker_input` from multiple targets.

Consider the following example:
* `cc_import` X
* `cc_shared_library` A depends on X
* `cc_shared_library` B depends on X
* `cc_binary` top depends on A and B

When linking top, the link order `top.a, A.so, X.so, B.so` is produced and wrong. When B depends on X, `X.so` should be placed behind `B.so`. The wanted link order is `top.a, A.so, B.so, X.so`.

[`cc_shared_library.bzl`](https://cs.opensource.google/bazel/bazel/+/master:src/main/starlark/builtins_bzl/common/cc/cc_shared_library.bzl;l=797-800;drc=a1af43cd4ec8731b39a98401b33f1f27aa0904dd) contains the following code:
```
CcSharedLibraryInfo(
dynamic_deps = merged_cc_shared_library_infos,
exports = exports.keys(),
link_once_static_libs = curr_link_once_static_libs_set,
linker_input = cc_common.create_linker_input(
owner = ctx.label,
libraries = depset([linking_outputs.library_to_link] + precompiled_only_dynamic_libraries),
),
),
```
This will create a single `LinkerInput` with all the `.so` files. When multiple `LinkerInput`s are put in a depset, the ordering of the individual `.so` files in the `LinkerInput.libraries` field will not change. On the contrary, `cc_library` produces multiple `LinkerInput`s with one `.so` file in each. In that case, the depset is able to reorder them on a higher level in the dependency graph.

This problem can (hopefully) be solved if `CcSharedLibraryInfo.linker_input` is changed into `CcSharedLibraryInfo.linker_inputs` where each `LinkerInput` contains a single `LibraryToLink`.

### Which category does this issue belong to?

C++ Rules

### What's the simplest, easiest way to reproduce this bug? Please provide a minimal example if possible.

```
cc_library(
name = "X_impl",
srcs = ["x.c"],
linkstatic = False,
)
filegroup(
name = "X_so",
srcs = [":X_impl"],
output_group = "dynamic_library",
)
cc_import(
name = "X_import",
shared_library = ":X_so",
hdrs = ["X.h"],
)
cc_library(
name = "X",
deps = [":X_import"],
)

# X2 is used to avoid the following error:
# Two shared libraries in dependencies export the same symbols. Both _solib_x86_64/_U/libA.so and _solib_x86_64/_U/libB.so export @@//:X
cc_library(
name = "X2",
deps = [":X"],
)

cc_shared_library(
name = "A",
deps = [":X"],
)
cc_shared_library(
name = "B",
deps = [":X2"],
)

cc_binary(
name = "top",
dynamic_deps = [":A", ":B"],
)
```
```
// x.c
int main() { return 0; }
```
```
$ bazel build :top && objdump -p bazel-bin/top | grep NEEDED
NEEDED libA.so
NEEDED libX_impl.so
NEEDED libB.so
NEEDED libc.so.6

$ bazel aquery 'mnemonic("CppLink", :top)' | grep -A 6 'Command Line'
action 'Linking top'
Mnemonic: CppLink
Target: //:top
...
Command Line: (exec /usr/bin/gcc \
-o \
bazel-out/k8-fastbuild/bin/top \
-Xlinker \
-rpath \
...
-lA \
-lX_impl \
-lB \
-Wl,--push-state,-as-needed \
-lstdc++ \
-Wl,--pop-state \
-Wl,--push-state,-as-needed \
-lm \
-Wl,--pop-state)
# Configuration: 3723722276aac1314320ca9a9fb2a278d80e4eb3b422da8939e984231a537159
# Execution platform: @@platforms//host:host
```

### Which operating system are you running Bazel on?

Linux

### What is the output of `bazel info release`?

release 8.1.0

### If `bazel info release` returns `development version` or `(@non-git)`, tell us how you built Bazel.

_No response_

### What's the output of `git remote get-url origin; git rev-parse HEAD` ?

```text

```

### If this is a regression, please try to identify the Bazel commit where the bug was introduced with bazelisk --bisect.

_No response_

### Have you found anything relevant by searching the web?

### Any other information, logs, or outputs that you want to share?

_No response_

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.