使用Clang编译Gtest测试时出现内部函数未定义引用问题
Clang编译GTest测试用例时出现链接错误,GCC编译正常
问题场景
使用GTest为项目编写测试用例,通过CMake构建,在GCC编译器下可正常编译运行,但切换到Clang编译器时出现链接错误,提示找不到testing::internal相关函数。
CMake配置代码
cmake_minimum_required(VERSION 3.26) project(cpp_stream_socket_tests) include(FetchContent) FetchContent_Declare( googletest URL https://github.com/google/googletest/archive/refs/tags/v1.14.0.zip ) set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) FetchContent_MakeAvailable(googletest) enable_testing() file(GLOB SRCS "src/*.cpp") file(GLOB HEADERS "include/*.hpp") add_executable(${PROJECT_NAME}) target_sources(${PROJECT_NAME} PRIVATE ${SRCS} PRIVATE FILE_SET HEADERS BASE_DIRS include FILES ${HEADERS} ) set_target_properties(${PROJECT_NAME} PROPERTIES LINKER_LANGUAGE CXX CXX_STANDARD 23 CXX_STANDARD_REQUIRED TRUE ) target_link_libraries(${PROJECT_NAME} gtest_main cpp_stream_socket) if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") target_compile_options(${PROJECT_NAME} PUBLIC -stdlib=libc++) endif() add_test(NAME ${PROJECT_NAME} COMMAND ${PROJECT_NAME})
链接错误信息
/usr/bin/ld: CMakeFiles/cpp_stream_socket_tests.dir/src/basic_operations.cpp.o: in function `void posix::net::tests::detail::check_res<std::__1::reference_wrapper<posix::net::socket<(posix::net::side)1, (posix::net::domain)2, (posix::net::type)1, posix::net::ipv4_address, posix::net::policy::multithread> > >(std::__1::expected<std::__1::reference_wrapper<posix::net::socket<(posix::net::side)1, (posix::net::domain)2, (posix::net::type)1, posix::net::ipv4_address, posix::net::policy::multithread> >, posix::net::error> const&)': basic_operations.cpp:(.text._ZN5posix3net5tests6detail9check_resINSt3__117reference_wrapperINS0_6socketILNS0_4sideE1ELNS0_6domainE2ELNS0_4typeE1ENS0_12ipv4_addressENS0_6policy11multithreadEEEEEEEvRKNS4_8expectedIT_NS0_5errorEEE[_ZN5posix3net5tests6detail9check_resINSt3__117reference_wrapperINS0_6socketILNS0_4sideE1ELNS0_6domainE2ELNS0_4typeE1ENS0_12ipv4_addressENS0_6policy11multithreadEEEEEEEvRKNS4_8expectedIT_NS0_5errorEEE]+0x11f): undefined reference to `testing::internal::GetBoolAssertionFailureMessage(testing::AssertionResult const&, char const*, char const*, char const*)' /usr/bin/ld: CMakeFiles/cpp_stream_socket_tests.dir/src/basic_operations.cpp.o: in function `testing::AssertionResult testing::internal::CmpHelperEQFailure<posix::net::state, posix::net::state>(char const*, char const*, posix::net::state const&, posix::net::state const&)': basic_operations.cpp:(.text._ZN7testing8internal18CmpHelperEQFailureIN5posix3net5stateES4_EENS_15AssertionResultEPKcS7_RKT_RKT0_[_ZN7testing8internal18CmpHelperEQFailureIN5posix3net5stateES4_EENS_15AssertionResultEPKcS7_RKT_RKT0_]+0x7f): undefined reference to `testing::internal::EqFailure(char const*, char const*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, bool)' /usr/bin/ld: CMakeFiles/cpp_stream_socket_tests.dir/src/basic_operations.cpp.o: in function `void testing::internal::RawBytesPrinter::PrintValue<posix::net::state, 4ul>(posix::net::state const&, std::__1::basic_ostream<char, std::__1::char_traits<char> >*)': basic_operations.cpp:(.text._ZN7testing8internal15RawBytesPrinter10PrintValueIN5posix3net5stateELm4EEEvRKT_PNSt3__113basic_ostreamIcNS9_11char_traitsIcEEEE[_ZN7testing8internal15RawBytesPrinter10PrintValueIN5posix3net5stateELm4EEEvRKT_PNSt3__113basic_ostreamIcNS9_11char_traitsIcEEEE]+0x1e): undefined reference to `testing::internal::PrintBytesInObjectTo(unsigned char const*, unsigned long, std::__1::basic_ostream<char, std::__1::char_traits<char> >*)' /usr/bin/ld: CMakeFiles/cpp_stream_socket_tests.dir/src/basic_operations.cpp.o: in function `testing::AssertionResult::AppendMessage(testing::Message const&)': basic_operations.cpp:(.text._ZN7testing15AssertionResult13AppendMessageERKNS_7MessageE[_ZN7testing15AssertionResult13AppendMessageERKNS_7MessageE]+0x73): undefined reference to `testing::Message::GetString() const'
环境信息
- gcc: 13.2.1
- clang: 17.0.6
- cmake: 3.28.1
- ld: 2.41.0
问题原因
你的CMake配置仅给测试程序添加了-stdlib=libc++编译选项,但通过FetchContent拉取的GTest默认使用系统默认的标准库(即GCC的libstdc++)编译。这导致测试程序依赖libc++,而GTest依赖libstdc++,两者的标准库符号(比如std::__1相关)不兼容,链接时就会找不到GTest的内部函数符号。
解决方案
修改CMake配置,确保GTest和测试程序使用相同的标准库实现。在FetchContent_MakeAvailable(googletest)之后,给GTest目标也添加libc++的编译和链接选项:
cmake_minimum_required(VERSION 3.26) project(cpp_stream_socket_tests) include(FetchContent) FetchContent_Declare( googletest URL https://github.com/google/googletest/archive/refs/tags/v1.14.0.zip ) set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) FetchContent_MakeAvailable(googletest) enable_testing() file(GLOB SRCS "src/*.cpp") file(GLOB HEADERS "include/*.hpp") add_executable(${PROJECT_NAME}) target_sources(${PROJECT_NAME} PRIVATE ${SRCS} PRIVATE FILE_SET HEADERS BASE_DIRS include FILES ${HEADERS} ) set_target_properties(${PROJECT_NAME} PROPERTIES LINKER_LANGUAGE CXX CXX_STANDARD 23 CXX_STANDARD_REQUIRED TRUE ) target_link_libraries(${PROJECT_NAME} gtest_main cpp_stream_socket) if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") # 给GTest目标添加libc++编译和链接选项 target_compile_options(gtest PUBLIC -stdlib=libc++) target_compile_options(gtest_main PUBLIC -stdlib=libc++) target_link_options(gtest PUBLIC -stdlib=libc++) target_link_options(gtest_main PUBLIC -stdlib=libc++) # 给测试程序添加libc++编译和链接选项 target_compile_options(${PROJECT_NAME} PUBLIC -stdlib=libc++) target_link_options(${PROJECT_NAME} PUBLIC -stdlib=libc++) endif() add_test(NAME ${PROJECT_NAME} COMMAND ${PROJECT_NAME})
这样修改后,GTest和测试程序都会使用libc++编译链接,标准库符号一致,就能解决链接错误问题。
内容的提问来源于stack exchange,提问作者Shadasviar
相关产品推荐
相关产品推荐

