CMake ASAN 没有链接 pthread
CMake ASAN not linking pthread
我正在尝试 运行 asan
使用几个编译器版本来捕获不同目标的问题。为此,我使用自定义 cmake
工具链文件,并开始使用官方 GCC Docker 容器。使用 gcc:11
一切都按预期工作,但是对于 gcc:10
和 gcc:9
我根本无法 link pthread
使用此自定义工具链文件。我已经确认我可以 link pthread
没有我的自定义工具链文件并且对于 ubsan
工具链文件一切正常。我怀疑我遗漏了一些小细节。我有一个最小的例子可以可靠地重现这个:
# asan.toolchain.cmake
set (CMAKE_C_COMPILER gcc)
set (CMAKE_CXX_COMPILER g++)
set (CMAKE_CXX_STANDARD 14)
set (CMAKE_CXX_FLAGS_INIT "-O0 -g -fsanitize=address -fno-omit-frame-pointer -fno-var-tracking-assignments")
set (CMAKE_LINKER_FLAGS_INIT "-fsanitize=address -fno-omit-frame-pointer")
set (CMAKE_BUILD_TYPE Debug)
# CMakeLists.txt
cmake_minimum_required (VERSION 3.13...3.18)
project (ASAN_TEST LANGUAGES CXX)
set (CMAKE_THREAD_PREFER_PTHREADS ON)
set (THREADS_PREFER_PTHREAD_FLAG TRUE)
find_package (Threads REQUIRED)
add_executable (test main.cpp)
target_link_libraries (test PRIVATE Threads::Threads)
// main.cpp
#include <pthread.h>
int main() {
pthread_key_t key{};
pthread_setspecific(key, nullptr);
}
使用 docker run -itv $(pwd):/usr/src gcc:9
在 docker 内安装项目并调用 cmake
和 make
产生以下结果:
root@94f4b543dd0b: apt update && apt install -y cmake
root@94f4b543dd0b: mkdir build && cd build
root@94f4b543dd0b:/build# cmake -DCMAKE_TOOLCHAIN_FILE=/usr/src/asan.toolchain.cmake /usr/src/
-- The CXX compiler identification is GNU 9.4.0
-- Check for working CXX compiler: /usr/local/bin/g++
-- Check for working CXX compiler: /usr/local/bin/g++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Looking for C++ include pthread.h
-- Looking for C++ include pthread.h - found
-- Looking for pthread_create
-- Looking for pthread_create - found
-- Found Threads: TRUE
-- Configuring done
-- Generating done
-- Build files have been written to: /build
root@87d5ef6a3b5f:/build# make VERBOSE=1
/usr/bin/cmake -S/usr/src -B/build --check-build-system CMakeFiles/Makefile.cmake 0
/usr/bin/cmake -E cmake_progress_start /build/CMakeFiles /build/CMakeFiles/progress.marks
make -f CMakeFiles/Makefile2 all
make[1]: Entering directory '/build'
make -f CMakeFiles/test.dir/build.make CMakeFiles/test.dir/depend
make[2]: Entering directory '/build'
cd /build && /usr/bin/cmake -E cmake_depends "Unix Makefiles" /usr/src /usr/src /build /build /build/CMakeFiles/test.dir/DependInfo.cmake --color=
Dependee "/build/CMakeFiles/test.dir/DependInfo.cmake" is newer than depender "/build/CMakeFiles/test.dir/depend.internal".
Dependee "/build/CMakeFiles/CMakeDirectoryInformation.cmake" is newer than depender "/build/CMakeFiles/test.dir/depend.internal".
Scanning dependencies of target test
make[2]: Leaving directory '/build'
make -f CMakeFiles/test.dir/build.make CMakeFiles/test.dir/build
make[2]: Entering directory '/build'
[ 50%] Building CXX object CMakeFiles/test.dir/main.cpp.o
/usr/local/bin/g++ -O0 -g -fsanitize=address -fno-omit-frame-pointer -fno-var-tracking-assignments -g -std=gnu++14 -o CMakeFiles/test.dir/main.cpp.o -c /usr/src/main.cpp
[100%] Linking CXX executable test
/usr/bin/cmake -E cmake_link_script CMakeFiles/test.dir/link.txt --verbose=1
/usr/local/bin/g++ -O0 -g -fsanitize=address -fno-omit-frame-pointer -fno-var-tracking-assignments -g CMakeFiles/test.dir/main.cpp.o -o test
/usr/bin/ld: CMakeFiles/test.dir/main.cpp.o: undefined reference to symbol 'pthread_setspecific@@GLIBC_2.2.5'
/usr/bin/ld: //lib/x86_64-linux-gnu/libpthread.so.0: error adding symbols: DSO missing from command line
collect2: error: ld returned 1 exit status
make[2]: *** [CMakeFiles/test.dir/build.make:84: test] Error 1
make[2]: Leaving directory '/build'
make[1]: *** [CMakeFiles/Makefile2:73: CMakeFiles/test.dir/all] Error 2
make[1]: Leaving directory '/build'
make: *** [Makefile:84: all] Error 2
如果使用 ubsan
工具链文件或 没有任何 工具链文件调用 cmake
,则此编译和 links。请注意,尽管 cmake
报告已找到 -pthread
,但在 make
调用的输出中缺少 -pthread
。
为了完整起见,这里是 ubsan
工具链文件:
# ubsan.toolchain.cmake
set (CMAKE_C_COMPILER gcc)
set (CMAKE_CXX_COMPILER g++)
set (CMAKE_CXX_STANDARD 14)
set (CMAKE_CXX_FLAGS_INIT "-O0 -g -fsanitize=undefined -fno-omit-frame-pointer -fno-var-tracking-assignments")
set (CMAKE_BUILD_TYPE Debug)
我的问题是这是否是通过 cmake
link asan
和 pthread
的正确方法,因为我对使用消毒剂的世界相当陌生.
感谢您的任何见解!
编辑:修正了拼写错误和陈述的问题。
any insights
libasan
有 pthread_create
符号,所以检查有缺陷。它已通过提交 https://github.com/Kitware/CMake/commit/e9a1ddc594de6e6251bf06d732775dae2cabe4c8#diff-717bcf9af3f2e98be38313ac012d165baefc9cc26180f10246cec3c947b1687b 固定在 CMake/Modules/FindThreads.cmake
:
# Check if pthread functions are in normal C library.
# If the pthread functions already exist in C library, we could just use
# them instead of linking to the additional pthread library. We could
# try to check any pthread symbol name, but here is an exception. If we
# use clang asan build, we will find the pthread_create() symbol in the
# libc(libasan). However, it doesn't have the full pthread implementation.
# So, we can't assume that we have the pthread implementation in libc
# using the pthread_create() checking here. Then, we turn to check the
# pthread_kill() symbol instead.
我正在尝试 运行 asan
使用几个编译器版本来捕获不同目标的问题。为此,我使用自定义 cmake
工具链文件,并开始使用官方 GCC Docker 容器。使用 gcc:11
一切都按预期工作,但是对于 gcc:10
和 gcc:9
我根本无法 link pthread
使用此自定义工具链文件。我已经确认我可以 link pthread
没有我的自定义工具链文件并且对于 ubsan
工具链文件一切正常。我怀疑我遗漏了一些小细节。我有一个最小的例子可以可靠地重现这个:
# asan.toolchain.cmake
set (CMAKE_C_COMPILER gcc)
set (CMAKE_CXX_COMPILER g++)
set (CMAKE_CXX_STANDARD 14)
set (CMAKE_CXX_FLAGS_INIT "-O0 -g -fsanitize=address -fno-omit-frame-pointer -fno-var-tracking-assignments")
set (CMAKE_LINKER_FLAGS_INIT "-fsanitize=address -fno-omit-frame-pointer")
set (CMAKE_BUILD_TYPE Debug)
# CMakeLists.txt
cmake_minimum_required (VERSION 3.13...3.18)
project (ASAN_TEST LANGUAGES CXX)
set (CMAKE_THREAD_PREFER_PTHREADS ON)
set (THREADS_PREFER_PTHREAD_FLAG TRUE)
find_package (Threads REQUIRED)
add_executable (test main.cpp)
target_link_libraries (test PRIVATE Threads::Threads)
// main.cpp
#include <pthread.h>
int main() {
pthread_key_t key{};
pthread_setspecific(key, nullptr);
}
使用 docker run -itv $(pwd):/usr/src gcc:9
在 docker 内安装项目并调用 cmake
和 make
产生以下结果:
root@94f4b543dd0b: apt update && apt install -y cmake
root@94f4b543dd0b: mkdir build && cd build
root@94f4b543dd0b:/build# cmake -DCMAKE_TOOLCHAIN_FILE=/usr/src/asan.toolchain.cmake /usr/src/
-- The CXX compiler identification is GNU 9.4.0
-- Check for working CXX compiler: /usr/local/bin/g++
-- Check for working CXX compiler: /usr/local/bin/g++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Looking for C++ include pthread.h
-- Looking for C++ include pthread.h - found
-- Looking for pthread_create
-- Looking for pthread_create - found
-- Found Threads: TRUE
-- Configuring done
-- Generating done
-- Build files have been written to: /build
root@87d5ef6a3b5f:/build# make VERBOSE=1
/usr/bin/cmake -S/usr/src -B/build --check-build-system CMakeFiles/Makefile.cmake 0
/usr/bin/cmake -E cmake_progress_start /build/CMakeFiles /build/CMakeFiles/progress.marks
make -f CMakeFiles/Makefile2 all
make[1]: Entering directory '/build'
make -f CMakeFiles/test.dir/build.make CMakeFiles/test.dir/depend
make[2]: Entering directory '/build'
cd /build && /usr/bin/cmake -E cmake_depends "Unix Makefiles" /usr/src /usr/src /build /build /build/CMakeFiles/test.dir/DependInfo.cmake --color=
Dependee "/build/CMakeFiles/test.dir/DependInfo.cmake" is newer than depender "/build/CMakeFiles/test.dir/depend.internal".
Dependee "/build/CMakeFiles/CMakeDirectoryInformation.cmake" is newer than depender "/build/CMakeFiles/test.dir/depend.internal".
Scanning dependencies of target test
make[2]: Leaving directory '/build'
make -f CMakeFiles/test.dir/build.make CMakeFiles/test.dir/build
make[2]: Entering directory '/build'
[ 50%] Building CXX object CMakeFiles/test.dir/main.cpp.o
/usr/local/bin/g++ -O0 -g -fsanitize=address -fno-omit-frame-pointer -fno-var-tracking-assignments -g -std=gnu++14 -o CMakeFiles/test.dir/main.cpp.o -c /usr/src/main.cpp
[100%] Linking CXX executable test
/usr/bin/cmake -E cmake_link_script CMakeFiles/test.dir/link.txt --verbose=1
/usr/local/bin/g++ -O0 -g -fsanitize=address -fno-omit-frame-pointer -fno-var-tracking-assignments -g CMakeFiles/test.dir/main.cpp.o -o test
/usr/bin/ld: CMakeFiles/test.dir/main.cpp.o: undefined reference to symbol 'pthread_setspecific@@GLIBC_2.2.5'
/usr/bin/ld: //lib/x86_64-linux-gnu/libpthread.so.0: error adding symbols: DSO missing from command line
collect2: error: ld returned 1 exit status
make[2]: *** [CMakeFiles/test.dir/build.make:84: test] Error 1
make[2]: Leaving directory '/build'
make[1]: *** [CMakeFiles/Makefile2:73: CMakeFiles/test.dir/all] Error 2
make[1]: Leaving directory '/build'
make: *** [Makefile:84: all] Error 2
如果使用 ubsan
工具链文件或 没有任何 工具链文件调用 cmake
,则此编译和 links。请注意,尽管 cmake
报告已找到 -pthread
,但在 make
调用的输出中缺少 -pthread
。
为了完整起见,这里是 ubsan
工具链文件:
# ubsan.toolchain.cmake
set (CMAKE_C_COMPILER gcc)
set (CMAKE_CXX_COMPILER g++)
set (CMAKE_CXX_STANDARD 14)
set (CMAKE_CXX_FLAGS_INIT "-O0 -g -fsanitize=undefined -fno-omit-frame-pointer -fno-var-tracking-assignments")
set (CMAKE_BUILD_TYPE Debug)
我的问题是这是否是通过 cmake
link asan
和 pthread
的正确方法,因为我对使用消毒剂的世界相当陌生.
感谢您的任何见解!
编辑:修正了拼写错误和陈述的问题。
any insights
libasan
有 pthread_create
符号,所以检查有缺陷。它已通过提交 https://github.com/Kitware/CMake/commit/e9a1ddc594de6e6251bf06d732775dae2cabe4c8#diff-717bcf9af3f2e98be38313ac012d165baefc9cc26180f10246cec3c947b1687b 固定在 CMake/Modules/FindThreads.cmake
:
# Check if pthread functions are in normal C library.
# If the pthread functions already exist in C library, we could just use
# them instead of linking to the additional pthread library. We could
# try to check any pthread symbol name, but here is an exception. If we
# use clang asan build, we will find the pthread_create() symbol in the
# libc(libasan). However, it doesn't have the full pthread implementation.
# So, we can't assume that we have the pthread implementation in libc
# using the pthread_create() checking here. Then, we turn to check the
# pthread_kill() symbol instead.