You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 03:59:52