1

I would like to compile the example given in the Google Benchmark documentation with clang using libc++:

#include <benchmark/benchmark.h>

static void BM_StringCreation(benchmark::State& state) {
  for (auto _ : state)
    std::string empty_string;
}
// Register the function as a benchmark
BENCHMARK(BM_StringCreation);

// Define another benchmark
static void BM_StringCopy(benchmark::State& state) {
  std::string x = "hello";
  for (auto _ : state)
    std::string copy(x);
}
BENCHMARK(BM_StringCopy);

BENCHMARK_MAIN();

I use the following command:

clang++ -stdlib=libc++ example.cpp -lbenchmark -lpthread -o example

And I got a lot of linker errors:

[...]
clang: error: linker command failed with exit code 1 (use -v to see invocation)

The full output is available here (more than 1500 lines). If I use the -v option, I can see:

clang version 7.0.1-8 (tags/RELEASE_701/final)
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin
Found candidate GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/8
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/8
Selected GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/8
Candidate multilib: .;@m64
Selected multilib: .;@m64
 "/usr/lib/llvm-7/bin/clang" -cc1 -triple x86_64-pc-linux-gnu -emit-obj -mrelax-all -disable-free -disable-llvm-verifier -discard-value-names -main-file-name example.cpp -mrelocation-model static -mthread-model posix -mdisable-fp-elim -fmath-errno -masm-verbose -mconstructor-aliases -munwind-tables -fuse-init-array -target-cpu x86-64 -dwarf-column-info -debugger-tuning=gdb -v -resource-dir /usr/lib/llvm-7/lib/clang/7.0.1 -internal-isystem /usr/lib/llvm-7/bin/../include/c++/v1 -internal-isystem /usr/include/clang/7.0.1/include/ -internal-isystem /usr/local/include -internal-isystem /usr/lib/llvm-7/lib/clang/7.0.1/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fdeprecated-macro -fdebug-compilation-dir /root -ferror-limit 19 -fmessage-length 0 -fobjc-runtime=gcc -fcxx-exceptions -fexceptions -fdiagnostics-show-option -o /tmp/example-9660e7.o -x c++ example.cpp -faddrsig
clang -cc1 version 7.0.1 based upon LLVM 7.0.1 default target x86_64-pc-linux-gnu
ignoring nonexistent directory "/include"
ignoring duplicate directory "/usr/include/clang/7.0.1/include"
#include "..." search starts here:
#include <...> search starts here:
 /usr/lib/llvm-7/bin/../include/c++/v1
 /usr/include/clang/7.0.1/include
 /usr/local/include
 /usr/include/x86_64-linux-gnu
 /usr/include
End of search list.
 "/usr/bin/ld" --hash-style=both --build-id --eh-frame-hdr -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o example /usr/bin/../lib/gcc/x86_64-linux-gnu/8/../../../x86_64-linux-gnu/crt1.o /usr/bin/../lib/gcc/x86_64-linux-gnu/8/../../../x86_64-linux-gnu/crti.o /usr/bin/../lib/gcc/x86_64-linux-gnu/8/crtbegin.o -L/usr/bin/../lib/gcc/x86_64-linux-gnu/8 -L/usr/bin/../lib/gcc/x86_64-linux-gnu/8/../../../x86_64-linux-gnu -L/lib/x86_64-linux-gnu -L/lib/../lib64 -L/usr/lib/x86_64-linux-gnu -L/usr/bin/../lib/gcc/x86_64-linux-gnu/8/../../.. -L/usr/lib/llvm-7/bin/../lib -L/lib -L/usr/lib /tmp/example-9660e7.o -lbenchmark -lpthread -lc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc /usr/bin/../lib/gcc/x86_64-linux-gnu/8/crtend.o /usr/bin/../lib/gcc/x86_64-linux-gnu/8/../../../x86_64-linux-gnu/crtn.o
[...]
clang: error: linker command failed with exit code 1 (use -v to see invocation)

I don't know if the issue comes from my clang or my Google Benchmark installation. Here is the script I made to install both:

#!/bin/sh
apt-get -y install clang libc++-dev libc++abi-dev git cmake
git clone https://github.com/google/benchmark.git
git clone https://github.com/google/googletest.git benchmark/googletest
pushd benchmark
cmake -E make_directory "build"
cmake -E chdir "build" cmake -DCMAKE_BUILD_TYPE=Release -DLLVMAR_EXECUTABLE=/usr/bin/llvm-ar-7 -DLLVMNM_EXECUTABLE=/usr/bin/llvm-nm-7 -DLLVMRANLIB_EXECUTABLE=/usr/bin/llvm-ranlib-7 ../
cmake --build "build" --config Release --target install
popd

During the second cmake command, I have the following message:

CMake Warning:
  Manually-specified variables were not used by the project:

    LLVMAR_EXECUTABLE
    LLVMNM_EXECUTABLE
    LLVMRANLIB_EXECUTABLE

Does it mean Google Benchmark is not build using libc++ and I can't link it to my benchmark? How can I fix this issue?


Here is my system information:

$ uname -a
Linux 1b3149ded49c 4.9.0-8-amd64 #1 SMP Debian 4.9.144-3.1 (2019-02-19) x86_64 GNU/Linux
Pierre
  • 1,942
  • 3
  • 23
  • 43
  • 1
    Before that error `clang: error: linker command failed with exit code 1` there is no explanation what exactly went wrong? – pptaszni Aug 27 '20 at 10:09
  • @pptaszni I added a pastebin link of the output of my compilation command: https://pastebin.com/FFZjjDGZ – Pierre Aug 27 '20 at 11:08
  • Great, you should include it in your question, because this information is crucial. [This topic](https://stackoverflow.com/questions/16770751/clang-3-2-linker-not-finding-c-stdlib) covers the problem with linking to incompatible C++ std libraries. Most likely GBenchmark was compiled with `libstdc++` and now you try to use `libc++`. Try it and let me know. You can also show the output from your GBenchmark compilation to confirm which libraries were used. – pptaszni Aug 27 '20 at 11:19
  • @pptaszni So the question is: how can I build Google Benchmark with libc++? – Pierre Aug 27 '20 at 11:20
  • 1
    Not sure, but you can try [this solution](https://stackoverflow.com/questions/43662736/cmake-switch-between-clang-g-and-libc-libstdc). Also take a look at [this CMakeLists](https://chromium.googlesource.com/chromium/llvm-project/libcxx/+/refs/heads/master/benchmarks/CMakeLists.txt). And you don't need to pass those `LLVM*` cmake variables to build it, they are not used anyway. – pptaszni Aug 27 '20 at 11:28

1 Answers1

2

In the GitHub repository of the project is a travis file. The line corresponding to the cmake command is:

cmake -DCMAKE_C_COMPILER=${C_COMPILER} -DCMAKE_CXX_COMPILER=${COMPILER} -DCMAKE_BUILD_TYPE=${BUILD_TYPE} -DCMAKE_C_FLAGS="${EXTRA_FLAGS}" -DCMAKE_CXX_FLAGS="${EXTRA_FLAGS} ${EXTRA_CXX_FLAGS}" -DBENCHMARK_DOWNLOAD_DEPENDENCIES=ON -DBENCHMARK_BUILD_32_BITS=${BUILD_32_BITS} ${EXTRA_OPTIONS} ..

All I have to do is replace the travis variables by what I want:

cmake -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS="-stdlib=libc++" -DBENCHMARK_DOWNLOAD_DEPENDENCIES=ON ../

After installation, I can compile my benchmark with clang and libc++:

clang++ -stdlib=libc++ example.cpp -lbenchmark -lpthread -o example
Pierre
  • 1,942
  • 3
  • 23
  • 43