Как я могу связать дезинфицирующее средство потока с более новой версией clang, чем предоставляет система?

Обычно я загружаю последнюю версию 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, я получу segfault при запуске своей программы.

Итак, я искал доступные библиотеки tsan, поставляемые с clang, и вот что я нашел:

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

Похоже, там есть библиотеки цана. Я думаю, я должен связать с ними. Как мне это сделать?

Это, похоже, не работает:

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.

Как я могу создать ссылку на tsan из готовых бинарных файлов новейшего clang?


person The Quantum Physicist    schedule 21.12.2018    source источник
comment
Что вы имеете в виду под this doesn't work either?   -  person Matthieu Brucher    schedule 21.12.2018
comment
Вы правильно установили флаги ссылок? Те, которые у вас есть, определенно неправильные. SET(CMAKE_EXE_LINKER_FLAGS ${CMAKE_EXE_LINKER_FLAGS} -fsanitize=tsan) SET(CMAKE_SHARED_LINKER_FLAGS ${CMAKE_SHARED_LINKER_FLAGS} -fsanitize=tsan)   -  person Matthieu Brucher    schedule 21.12.2018
comment
@MatthieuBrucher Как я уже упоминал, я либо получаю ошибку компоновщика, либо неопределенную ссылку на какой-то компонент tsan.   -  person The Quantum Physicist    schedule 21.12.2018
comment
@MatthieuBrucher Даже если это сработает, будет использоваться старая библиотека. Мне нужна ссылка на библиотеку tsan clang 7. Не тот, что в системе.   -  person The Quantum Physicist    schedule 21.12.2018
comment
Почему вы говорите, даже если это сработает? Это правильный способ ссылки. Если есть проблема с порядком, используйте VERBOSE=1 make и -v для детализации.   -  person Matthieu Brucher    schedule 21.12.2018
comment
@MatthieuBrucher Вы заметили, что имя библиотеки tsan не libtsan.so, а что-то совершенно другое? Разве это не имеет значения? Я не хочу, чтобы он ссылался на библиотеку в системе.   -  person The Quantum Physicist    schedule 21.12.2018
comment
Да, я заметил, я неплохо разбираюсь в этом флаге.   -  person Matthieu Brucher    schedule 21.12.2018
comment
@MatthieuBrucher Значит, -ltsan должен работать даже с этой библиотекой со странным названием? Как я могу гарантировать, что он не будет использовать тот, что из системы?   -  person The Quantum Physicist    schedule 21.12.2018
comment
Вы не должны использовать -ltsan, вы правы, говоря, что будет выбран неправильный (обычно gcc). Вот почему clang имеет опцию -fsanitizer, чтобы установить внутреннее имя для библиотеки.   -  person Matthieu Brucher    schedule 21.12.2018


Ответы (1)


Установка флага ссылки для компиляции — это большое нет-нет:

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 знает, где находятся его библиотеки поддержки для санитарии (как вы сказали, они помечены тройной информацией и не находятся в обычных папках библиотек, чтобы избежать любого загрязнения от других установок), и полный флаг fsanitize=tsan заставит его выбрать до этих версий. Обратите внимание, что это не -ltsan, а полная опция, которая заставит clang выбрать правильный бэкэнд на пути, где находятся его собственные дезинфицирующие средства.

person Matthieu Brucher    schedule 21.12.2018
comment
Каким-то образом, когда я это делаю, у меня портятся другие пакеты... Я все еще пытаюсь заставить его работать. Boost::thread рушится из-за этого. Cmake говорит: НЕ удалось найти потоки (отсутствует: Threads_FOUND). Вы уверены, что нет других необходимых флагов? Я воспроизводимо удалил эти флаги и восстановил их, чтобы создать проблему. - person The Quantum Physicist; 21.12.2018
comment
О, хорошо, достаточно честно. Я добавлю целевую версию в свой ответ. - person Matthieu Brucher; 21.12.2018
comment
Но разве это не означает, что он не будет ссылаться на tsan для всего? Я не понимаю, почему это не работает с библиотекой потоков и как это исправить. Странное изменение флага ссылки, которое я сделал, заключалось в том, чтобы весь проект использовал tsan. Я как бы хотел, чтобы это было глобальным. - person The Quantum Physicist; 21.12.2018
comment
Первый вариант будет использовать tsan для всего, даже для обнаружения библиотеки, что может быть проблематично (см. журнал вывода CMake и журнал ошибок в папке CMakeFiles). Второй активирует tsan только для тех библиотек, которые вы хотите очистить. - person Matthieu Brucher; 21.12.2018
comment
Вы уверены, что не ошиблись при вводе -fsanitize=tsan вместо -fsanitize=thread? - person The Quantum Physicist; 21.12.2018
comment
Хорошо, он отлично работает с -fsanitize=thread. Ничего общего с целью. Пожалуйста, исправьте свой ответ. Также есть дисбаланс котировок. Спасибо за помощь :-) - person The Quantum Physicist; 21.12.2018
comment
Вместо того, чтобы устанавливать флаги ссылки и компиляции для цели, можно сделать и то, и другое одновременно, используя target_link_libraries(${TARGET} PRIVATE -fsanitize=thread). Источник: stackoverflow.com/a/50163972/8366223 - person PolyGlot; 13.01.2021