使用CMake编译C++代码时遭遇链接错误2,请求协助排查
CMake编译C++代码时出现重复定义错误
最近我尝试用CMake编译一段简单的C++代码,结果踩了个坑,相关的代码、CMake配置以及make时的错误信息我整理出来了:
涉及的代码文件
test.cpp
#ifndef _IOSTREAM_ #include<iostream> #endif #include"test1.cpp" using namespace std; int main() { printing("hello"); return 0; }
test1.cpp
#ifndef _IOSTREAM_ #include<iostream> #endif #include<string> void printing(const string& msg) { cout << msg << endl; }
CMakeLists.txt配置
cmake_minimum_required(VERSION 3.10) project(TestProject) add_executable(test test.cpp test1.cpp)
make时的错误信息
/usr/bin/ld: CMakeFiles/test.dir/test.cpp.o:/home/user/test/test1.cpp:8: multiple definition of `printing(std::__cxx11::basic_string<char, std::char_traits
, std::allocator > const&)'; CMakeFiles/test.dir/test1.cpp.o:/home/user/test/test1.cpp:8: first defined here
collect2: error: ld returned 1 exit status
make[2]: *** [CMakeFiles/test.dir/build.make:104: test] Error 1
make[1]: *** [CMakeFiles/Makefile2:76: CMakeFiles/test.dir/all] Error 1
make: *** [Makefile:84: all] Error 1
问题分析
这个错误的核心原因是直接在源文件中包含另一个.cpp文件:
- 当
test.cpp包含test1.cpp时,编译test.cpp会把test1.cpp的内容全部展开,导致test.cpp.o中包含了printing函数的定义; - 同时CMakeLists.txt里又把
test1.cpp作为单独的源文件加入编译,生成的test1.cpp.o中也有printing函数的定义; - 链接阶段,两个目标文件里的同一个函数定义冲突,就报了重复定义的错误。
解决方法
1. 调整代码结构,使用头文件+源文件的标准写法
- 创建
test1.h头文件,用于声明函数:
#ifndef TEST1_H #define TEST1_H #include<string> // 函数声明 void printing(const std::string& msg); #endif // TEST1_H
- 修改
test1.cpp,只保留函数实现,并包含对应的头文件:
#include "test1.h" #include <iostream> // 函数实现 void printing(const std::string& msg) { std::cout << msg << std::endl; }
- 修改
test.cpp,改为包含头文件test1.h而非源文件test1.cpp:
#include <iostream> #include "test1.h" using namespace std; int main() { printing("hello"); return 0; }
2. 保持CMakeLists.txt的正确配置(无需修改)
原来的CMake配置是正确的,它会编译两个源文件并链接成可执行文件:
cmake_minimum_required(VERSION 3.10) project(TestProject) add_executable(test test.cpp test1.cpp)
3. 重新编译执行
清理之前的构建文件,重新编译:
rm -rf build && mkdir build && cd build cmake .. make ./test
这样就能正常编译运行,输出hello了。
内容的提问来源于stack exchange,提问作者user9574361
相关产品推荐
相关产品推荐

