This may be more of a bazel question but since it's in the context of rust, I figured the audience here is as good as any 😄 .
Suppose we have the following targets:
cc_library
building some static lib
rust_library
FFI wrapper over the above
rust_binary
that uses the rust_library
Pretty standard and simple setup for rust using c/c++ code.
In a dbg
or fastbuild
setup, it seems the above just works. However, when I recently tried this with an opt
build using a custom cc toolchain, the code failed to link. Quick note on the custom toolchain - it's very close to the configuration/setup of bazel's builtin crosstool but uses vendored gcc (and related tools).
The link failure was around invalid relocations. This is because rustc
, by default, wants to build position-independent (PIE) executables. To do that, the c/c++ static libs need to be built with -fPIC
- building the cc_library
as PIC fixes the issue. However, this requires modifying a target whose other downstream users may not want to be PIC'd (and PIC can have non-zero perf cost, albeit low from what I gather).
The other fix that I came across is changing the rust_binary
target to specify a codegen option to rustc
: --relocation-model=static
. This builds a non-PIE binary, and doesn't require -fPIC
on the dependent cc libs.
This feels ... wrong, however. Either I'd need to modify all rust binary targets to select static relocation, or I'd need to modify the c/c++ static libs to be PIC. I also don't know why there's a difference between dbg
/fastbuild
and opt
builds.
Does anyone know if there's a better way to control linkage and relocation model? Ideally (I think), a rust_binary
would select the linkage it wants (static or dynamic) and the relocation model (static or dynamic), and this choice would flow down to dependent libs, where bazel would build them as either static or dynamic libs and also select -fPIC
or not.
Curious to hear thoughts/suggestions.
cc @mfarrugi as he's interested in this as well, I believe.