Open trittweiler opened 3 years ago
Maybe I am just mistaken, and bazel does not actually look at the CXX
environment variable?
It seems to be compiling the ubsan_test.cc
also with clang
, i.e. the contents of the CC
variable.
So am I simply using it wrong?
Assuming bazel does indeed not look at CXX
at this time, this issue is essentially evidence for someone tripping over what is covered by Issue #5186.
bazel currently compiles through the base clang/gcc driver and doesn't support the c++ drivers of these commands, bazel c++ toolchains generally have to be explicit about any implicit c++ stuff that would otherwise happen when you use the c++ drivers for clang/gcc.
if you run -v on your invocation with clang++ you'll probably see something like --whole-archive /usr/lib/clang/11.0.0/lib/linux/libclang_rt.ubsan_standalone_cxx-x86_64.a --no-whole-archive --dynamic-list=/usr/lib/clang/11.0.0/lib/linux/libclang_rt.ubsan_standalone_cxx-x86_64.a.syms
you effectively need to do this manually in your toolchain (or via --linkopts, or via the linkopts rule attributes), afaik this is a known limitation of the toolchain design, the link invocation is also always assumed to be c++ which isn't great but is typically benign because c code won't emit any references to c++ symbols.
See https://github.com/bazelbuild/bazel/issues/11122#issuecomment-896613570 for two easy ways to fix this problem. There is no need to hardcode library paths. Appending either
--linkopt -fsanitize-link-c++-runtime
or
--linkopt --driver-mode=g++
to the commandline above makes clang link the UBSan C++ runtime libraries without the need to use clang++. In fact, the latter flag makes clang behave as if it were clang++.
This workaround solves the problem of compiling C++ code with a C compiler by trying to act like a C++ compiler. I was successfully able to compile C++ code with this workaround, but doing so broke the compilation of some of our dependencies that use C (see below).
IMO, the fact that we need workarounds for this is evidence that we should allow specifying both the C and C++ compiler.
We get errors like:
bazel build @zstd//:zstd
INFO: Analyzed target @zstd//:zstd (2 packages loaded, 16111 targets configured).
INFO: Found 1 target...
ERROR: /usr/local/google/home/msta/.cache/bazel/_bazel_msta/ed8a9562ed8b7b4d013265ed31cbccd4/external/zstd/BUILD.bazel:48:10: Linking external/zstd/zstd failed: (Exit 1): x86_64-cros-linux-gnu-clang failed: error executing command (from target @zstd//:zstd) /usr/local/google/home/msta/.cache/bazel/_bazel_msta/ed8a9562ed8b7b4d013265ed31cbccd4/external/_main~toolchains~toolchain_sdk/bin/x86_64-cros-linux-gnu-clang ... (remaining 1 argument skipped)
Use --sandbox_debug to see verbose messages from the sandbox and retain the sandbox build root for debugging
ld.lld: error: undefined symbol: __cxa_begin_catch
>>> referenced by benchzstd.c
>>> bazel-out/k8-dbg/bin/external/zstd/_objs/zstd/benchzstd.pic.o:(__clang_call_terminate)
ld.lld: error: undefined symbol: std::terminate()
>>> referenced by benchzstd.c
>>> bazel-out/k8-dbg/bin/external/zstd/_objs/zstd/benchzstd.pic.o:(__clang_call_terminate)
ld.lld: error: undefined symbol: __gxx_personality_v0
>>> referenced by benchzstd.c
>>> bazel-out/k8-dbg/bin/external/zstd/_objs/zstd/benchzstd.pic.o:(DW.ref.__gxx_personality_v0)
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Target @zstd//:zstd failed to build
And hundreds of warnings like the following:
INFO: From Compiling lib/compress/zstd_lazy.c:
clang: warning: treating 'c' input as 'c++' when in C++ mode, this behavior is deprecated [-Wdeprecated]
Thank you for contributing to the Bazel repository! This issue has been marked as stale since it has not had any activity in the last 1+ years. It will be closed in the next 90 days unless any other activity occurs. If you think this issue is still relevant and should stay open, please post any comment here and the issue will no longer be marked as stale.
@comius @pzembrod I am thinking of extending the auto-configured toolchain in a way that ends up using g++
/clang++
for C++ compilation actions, ideally in a backwards compatible way. This would bring Bazel in line with other build tools and remove subtle behavioral differences (https://github.com/bazel-contrib/toolchains_llvm/issues/372 just came up as another example). What do you think of that?
Description of the problem / feature request:
Linking a C++ program with
clang -fsanitize=undefined
results in undefined symbols. It is necessary to useclang++ -fsanitize=undefined
instead.And bazel as of 3.7.2 tries to link C++ object files using
clang
rather thanclang++
.What operating system are you running Bazel on?
Ubuntu Focal 20.04.1 LTS.
The test case was done using clang 10.0.0-4ubuntu1, that's simply from the clang-10 Ubuntu package.
What's the output of
bazel info release
?release 3.7.2
Bugs: what's the simplest, easiest way to reproduce this bug? Please provide a minimal example if possible.
Here's a test case:
And we now try to build, link and run
:ubsan_test
as follows:Now I am going to manually repeat the link step (the
/usr/bin/clang @bazel-out/k8-dbg/bin/ubsan_test-2.params
) but replaceclang
withclang++
:And that succeeded just fine. And when I manually run the produced binary, it works just fine: