Search code examples
c++thread-safetyclangc++14thread-sanitizer

How can I link to thread sanitizer with a newer version of clang than the system provides?


I download normally the latest clang version from their website. This helps me use the latest version of C++ as doing this with gcc is not really possible. I just get the binaries for my Ubuntu/Debian and I'm good to go.

For me, linking with tsan library (thread-sanitizer library) has never been something simple. I use insane measures in cmake to make it work. Previously, when I used gcc from the system, this is what I did in cmake to make the link work correctly:

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=thread -ltsan")
set(CMAKE_LINK_LIBRARY_FLAG "-ltsan -l")

which basically modifies the linking flags to link every little thing with tsan. This has worked fine for a while, but to make it work, I should use gcc, the system's compiler. If I try to link like this with clang 7, I get a segfault when I run my program.

So I searched for the available tsan libraries that come with clang, and here's what I found:

user@machine:/opt/clang7$ find -iname "*tsan*"
./lib/clang/7.0.0/lib/linux/libclang_rt.tsan_cxx-x86_64.a
./lib/clang/7.0.0/lib/linux/libclang_rt.tsan-x86_64.a
./lib/clang/7.0.0/lib/linux/libclang_rt.tsan_cxx-x86_64.a.syms
./lib/clang/7.0.0/lib/linux/libclang_rt.tsan-x86_64.a.syms
./lib/clang/7.0.0/include/sanitizer/tsan_interface_atomic.h
./lib/clang/7.0.0/include/sanitizer/tsan_interface.h

There seems to be tsan libraries there. I guess I gotta link to them. How do I do that?

This, doesn't seem to work:

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=thread -L/opt/clang7/lib/clang/7.0.0/lib/linux/ -lclang_rt.tsan_cxx-x86_64")
set(CMAKE_LINK_LIBRARY_FLAG "-L/opt/clang7/lib/clang/7.0.0/lib/linux/ -lclang_rt.tsan_cxx-x86_64 -l")

This doesn't work either:

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=thread -l:/opt/clang7/lib/clang/7.0.0/lib/linux/libclang_rt.tsan_cxx-x86_64.a")
set(CMAKE_LINK_LIBRARY_FLAG "-l:/opt/clang7/lib/clang/7.0.0/lib/linux/libclang_rt.tsan_cxx-x86_64.a -l")

I've tried a few other combinations. But None of them seem to work. The errors I get are either linking errors or undefined references to some tsan components.

How can I link to tsan from the newest clang's prebuilt binaries?


Solution

  • Setting the link flag for the compilation is a big no-no:

    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=thread")
    

    Then you need to do the same for the link flags as well:

    SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=thread") 
    SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fsanitize=thread")
    

    You can also change the target properties only:

    set_target_properties(${TARGET} PROPERTIES
        LINK_FLAGS -fsanitizer=thread
        COMPILE_FLAGS -fsanitizer=thread)
    

    Be aware that this overrides all flags (I don't remember if CMAKE_CXX_FLAGS are also there, maybe not), you may want to retrieve the current ones and append these instead of removing everything.

    clang knows where its support libraries for sanitation are (as you said, these are tagged with a triple-like information and are not in the usual library folders, to avoid any contamination from other installs), and the full fsanitize=tsan flag will make it pick up these versions. Note that it's not -ltsan, but a full option that will make clang pick up the proper backend in the path where its own sanitizers are.