使用CMAKE生成makefile后未定义的引用
Posted
技术标签:
【中文标题】使用CMAKE生成makefile后未定义的引用【英文标题】:Undefined reference after using CMAKE to generate a makefile 【发布时间】:2017-10-24 21:25:54 【问题描述】:我可以生成我的 CMake 项目,但我无法构建它。
我有一个相当简单的项目结构:
├── bin
├── build
├── CMakeLists.txt
├── include
│ └── project
│ ├── base_socket.h
│ ├── tcp_client.h
│ ├── tcp_server.h
│ ├── udp_client.h
│ └── udp_server.h
├── LICENSE.txt
├── README.md
└── src
└── project
├── base_socket.cpp
├── CMakeLists.txt
├── main.cpp
├── tcp_client.cpp
├── tcp_server.cpp
├── udp_client.cpp
└── udp_server.cpp
顶部目录中有一个相当简单的 CMakeLists.txt 文件:
# Project initialization
cmake_minimum_required(VERSION 2.7.2 FATAL_ERROR)
project("cpp_sockets")
# Add include directory
include_directories(include)
# Add subdirectories
add_subdirectory(src/project)
还有一个相当简单的src/project/CmakeLists.txt
:
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY $CMAKE_SOURCE_DIR/bin)
set(HEADER_DIR $CMAKE_SOURCE_DIR/include/project)
set(HEADER_FILES
$HEADER_DIR/base_socket.h
$HEADER_DIR/tcp_client.h
$HEADER_DIR/tcp_server.h
$HEADER_DIR/udp_client.h
$HEADER_DIR/udp_server.h
)
add_executable(cpp_sockets main.cpp $HEADER_FILES)
当我将cd
输入/build
并输入cmake ..
时,它工作正常。
但是,当我使用 make
进行跟踪时,我收到了很多关于 undefined reference
的可怕错误。
main.cpp:(.text+0x2c6): undefined reference to `UDPClient::UDPClient(int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)'
main.cpp:(.text+0x2eb): undefined reference to `UDPClient::send_message(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)'
main.cpp:(.text+0x359): undefined reference to `UDPServer::UDPServer(int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)'
main.cpp:(.text+0x380): undefined reference to `UDPServer::socket_bind()'
main.cpp:(.text+0x38c): undefined reference to `UDPServer::listen()'
main.cpp:(.text+0x400): undefined reference to `TCPClient::TCPClient(int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)'
main.cpp:(.text+0x40c): undefined reference to `TCPClient::make_connection()'
main.cpp:(.text+0x42b): undefined reference to `TCPClient::send_message(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)'
main.cpp:(.text+0x492): undefined reference to `TCPServer::TCPServer(int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)'
main.cpp:(.text+0x4b9): undefined reference to `TCPServer::socket_bind()'
CMakeFiles/cpp_sockets.dir/main.cpp.o: In function `UDPClient::~UDPClient()':
main.cpp:(.text._ZN9UDPClientD2Ev[_ZN9UDPClientD5Ev]+0x14): undefined reference to `Socket::~Socket()'
CMakeFiles/cpp_sockets.dir/main.cpp.o: In function `UDPServer::~UDPServer()':
main.cpp:(.text._ZN9UDPServerD2Ev[_ZN9UDPServerD5Ev]+0x14): undefined reference to `Socket::~Socket()'
CMakeFiles/cpp_sockets.dir/main.cpp.o: In function `TCPClient::~TCPClient()':
main.cpp:(.text._ZN9TCPClientD2Ev[_ZN9TCPClientD5Ev]+0x14): undefined reference to `Socket::~Socket()'
CMakeFiles/cpp_sockets.dir/main.cpp.o: In function `TCPServer::~TCPServer()':
main.cpp:(.text._ZN9TCPServerD2Ev[_ZN9TCPServerD5Ev]+0x14): undefined reference to `Socket::~Socket()'
collect2: error: ld returned 1 exit status
src/project/CMakeFiles/cpp_sockets.dir/build.make:94: recipe for target '../bin/cpp_sockets' failed
make[2]: *** [../bin/cpp_sockets] Error 1
CMakeFiles/Makefile2:85: recipe for target 'src/project/CMakeFiles/cpp_sockets.dir/all' failed
make[1]: *** [src/project/CMakeFiles/cpp_sockets.dir/all] Error 2
Makefile:83: recipe for target 'all' failed
make: *** [all] Error 2
main.cpp
文件看起来像:
#include "project/udp_server.h"
#include "project/udp_client.h"
#include "project/tcp_client.h"
为什么链接器找不到这样的引用?
【问题讨论】:
看起来你已经在udp_client.cpp
源文件和其他文件中给出了函数定义,但是你在创建可执行文件时忘记添加这些文件。 (您包含的头文件仅提供函数的声明)。
in add_executable
列出所有实现文件 (*.cpp),而不是标题。对于标题,只需指定 include_directories
非常感谢@PiotrSkotnicki。这可能是一个答案!
【参考方案1】:
您的 src/project/CMakeLists.txt
似乎忽略了将其他 cpp 文件(如 udp_server.cpp
和 udp_client.cpp
)指定为可执行文件 cpp_sockets
的依赖项。您需要这样做才能让 CMake 编译这些源文件;它不会仅仅因为你已经包含了它们相应的头文件而自动编译它们。事实上,add_executable
声明不需要说明任何关于标头的内容,因为 include_directories
命令会处理这些。
鉴于您的main.cpp
所依赖的头文件,其add_executable
行应如下所示:
add_executable(cpp_sockets main.cpp udp_server.cpp udp_client.cpp tcp_client.cpp)
【讨论】:
以上是关于使用CMAKE生成makefile后未定义的引用的主要内容,如果未能解决你的问题,请参考以下文章
错误 CS0012:“ConnectionStringSettings”类型是在升级到 Visual Studio 2015 后未引用的程序集中定义的