C项目中Boost单元测试因函数未定义引用致链接失败求助
问题
编译Boost单元测试时出现链接错误,提示未定义对add(int, int)的引用,错误信息如下:
/usr/bin/ld: CMakeFiles/MyTest.dir/test_main.cpp.o: in function `test_add::test_method()': test_main.cpp:(.text+0x1dedb): undefined reference to `add(int, int)' /usr/bin/ld: test_main.cpp:(.text+0x1e004): undefined reference to `add(int, int)' collect2: error: ld returned 1 exit status make[2]: *** [tests/CMakeFiles/MyTest.dir/build.make:105: tests/MyTest] Error 1 make[1]: *** [CMakeFiles/Makefile2:190: tests/CMakeFiles/MyTest.dir/all] Error 2 make: *** [Makefile:103: all] Error 2
注释掉单元测试的CMake配置后,主程序可正常编译运行。项目目录结构:
. ├── CMakeLists.txt ├── include │ └── my_functions.h ├── src │ ├── CMakeLists.txt │ ├── main.c │ └── my_functions.c └── tests ├── CMakeLists.txt └── test_main.cpp
相关文件内容
my_functions.h
#ifndef MY_FUNCTIONS_H #define MY_FUNCTIONS_H int add(int a, int b); #endif // MY_FUNCTIONS_H
my_functions.c
#include "my_functions.h" int add(int a, int b) { return a + b; }
main.c
#include "my_functions.h" #include <stdio.h> int main() { printf("Hello, World!\n"); printf("Sum of 3 and 4 is %d\n", add(3, 4)); return 0; }
test_main.cpp
#define BOOST_TEST_MODULE MyTest #include <boost/test/included/unit_test.hpp> #include "../include/my_functions.h" // dummy unit test BOOST_AUTO_TEST_CASE(test_dummy) { BOOST_CHECK(true); } BOOST_AUTO_TEST_CASE(test_add) { BOOST_CHECK(add(2, 3) == 5); BOOST_CHECK(add(0, 0) == 0); }
根目录CMakeLists.txt
cmake_minimum_required(VERSION 3.10) project(MyProject VERSION 1.0) # Set C standard set(CMAKE_C_STANDARD 11) set(CMAKE_C_STANDARD_REQUIRED True) # Include directories include_directories(include) # Create a library target for your functions add_library(my_functions_lib src/my_functions.c) # Add subdirectories add_subdirectory(src) add_subdirectory(tests)
src目录CMakeLists.txt
# Add executable add_executable(MyProject main.c) # Link the library with your executable target_link_libraries(MyProject my_functions_lib)
tests目录CMakeLists.txt
# Find Boost find_package(Boost REQUIRED COMPONENTS unit_test_framework) # Add test executable add_executable(MyTest test_main.cpp) # Link Boost libraries and your function library to the test executable target_link_libraries(MyTest Boost::unit_test_framework my_functions_lib ) # Include directories target_include_directories(MyTest PRIVATE ../include)
注释掉add函数引用后,虚拟测试可正常运行,需解决如何在test_main.cpp中正确引用add函数的问题。
解决方案
核心原因
问题源于C和C++的名称修饰规则差异:
my_functions.c是C代码,编译后函数名保留原始的add符号;test_main.cpp是C代码,编译时会对add进行C风格的名称修饰(比如生成_Z3addii这类符号);- 链接时,C++代码找不到C语言编译出的
add原始符号,因此抛出未定义引用错误。
修复步骤
修改my_functions.h,添加C/C兼容的编译指令,让C代码以C语言的规则解析头文件中的函数声明:
#ifndef MY_FUNCTIONS_H #define MY_FUNCTIONS_H #ifdef __cplusplus extern "C" { #endif int add(int a, int b); #ifdef __cplusplus } #endif #endif // MY_FUNCTIONS_H
原理说明
__cplusplus是C编译器自动定义的宏,当C代码包含该头文件时,会触发extern "C"块;extern "C"告诉C编译器,块内的函数采用C语言的名称规则,不进行C风格的名称修饰;- 这样C++代码编译后会使用原始的
add符号,就能和C语言编译出的库成功链接。
验证操作
修改完头文件后,重新执行编译:
mkdir build && cd build cmake .. make ./tests/MyTest
测试将正常运行,不再出现链接错误。
内容的提问来源于stack exchange,提问作者BhanuKiran
相关产品推荐
相关产品推荐

