如何使用系统提供的较新版本的clang链接到线程消毒剂?

时间:2018-12-21 10:01:28

标签: c++ thread-safety clang c++14 thread-sanitizer

我通常从their website下载最新的clang版本。这可以帮助我使用最新版本的C ++,因为用gcc这样做实际上是不可能的。我刚刚获得了适用于我的Ubuntu / Debian的二进制文件,我很好。

对我来说,与tsan库(线程清理程序库)的链接从未如此简单。我在cmake中使用了疯狂的措施使其工作。以前,当我从系统中使用gcc时,这就是我在cmake中所做的,以使链接正常工作:

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

基本上修改了链接标志,以将所有小物件与tsan链接。这已经工作了一段时间了,但是要使其正常工作,我应该使用系统的编译器gcc。如果我尝试使用clang 7进行此类链接,则在运行程序时会出现段错误。

因此,我搜索了clang附带的可用tsan库,这是我发现的内容:

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

那里似乎有tsan库。我想我必须链接到他们。我该怎么做?

这似乎不起作用:

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")

这也不起作用:

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")

我尝试了其他几种组合。但是它们似乎都不起作用。我得到的错误是链接错误或对某些tsan组件的未定义引用。

如何从最新的clang的预构建二进制文件链接到tsan?

1 个答案:

答案 0 :(得分:0)

设置编译的链接标志是一个很大的禁忌:

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

然后,您还需要对链接标志执行相同的操作:

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

您还可以仅更改目标属性:

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

请注意,这会覆盖所有标志(我不记得CMAKE_CXX_FLAGS是否也在那里),您可能想检索当前标志并将其附加而不是删除所有标志。

clang知道其卫生支持库在哪里(如您所说,这些库带有类似三重的信息标记,并且不在常规库文件夹中,以避免其他安装造成污染),以及完整的{{1 }}标志将使其选择这些版本。请注意,它不是fsanitize=tsan,而是一个完整的选项,它将使clang在其自身的消毒剂所在的路径中拾取适当的后端。