C++ 对boost::serialization的未定义引用

C++ 对boost::serialization的未定义引用,c++,boost,cmake,C++,Boost,Cmake,我正在尝试使用boost::asio创建一些简单的服务器,并对结构进行序列化。但是,在我的项目中尝试使用boost::archives时,我遇到了一些链接器错误。我有很多未定义的引用。你能帮我找出错误吗 src/libserver.a(session.cpp.o): In function `boost::archive::text_iarchive::text_iarchive(std::istream&, unsigned int)': session.cpp:(.text._ZN5

我正在尝试使用boost::asio创建一些简单的服务器,并对结构进行序列化。但是,在我的项目中尝试使用boost::archives时,我遇到了一些链接器错误。我有很多未定义的引用。你能帮我找出错误吗

src/libserver.a(session.cpp.o): In function `boost::archive::text_iarchive::text_iarchive(std::istream&, unsigned int)':
session.cpp:(.text._ZN5boost7archive13text_iarchiveC2ERSij[_ZN5boost7archive13text_iarchiveC5ERSij]+0x25): undefined reference to `boost::archive::text_iarchive_impl<boost::archive::text_iarchive>::text_iarchive_impl(std::istream&, unsigned int)'
我的根CMakeLists.txt

cmake_minimum_required(VERSION 3.5)
project(mainServer)

set(Boost_USE_STATIC_LIBS OFF)
set(Boost_USE_MULTITHREADED ON)
set(Boost_USE_STATIC_RUNTIME OFF)

add_subdirectory(src)

find_package(Boost 1.65.1.0 REQUIRED system)

if(Boost_FOUND)
    include_directories(${Boost_INCLUDE_DIRS})
    add_executable(mainServer main.cpp)
    target_link_libraries(mainServer ${Boost_LIBRARIES})
    target_link_libraries(mainServer server)
endif()
add_library(
    server
    server.cpp
    session.cpp
)

set_target_properties(server PROPERTIES LINKER_LANGUAGE CXX)
target_include_directories(server PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}")
和我的src CMakeLists.txt

cmake_minimum_required(VERSION 3.5)
project(mainServer)

set(Boost_USE_STATIC_LIBS OFF)
set(Boost_USE_MULTITHREADED ON)
set(Boost_USE_STATIC_RUNTIME OFF)

add_subdirectory(src)

find_package(Boost 1.65.1.0 REQUIRED system)

if(Boost_FOUND)
    include_directories(${Boost_INCLUDE_DIRS})
    add_executable(mainServer main.cpp)
    target_link_libraries(mainServer ${Boost_LIBRARIES})
    target_link_libraries(mainServer server)
endif()
add_library(
    server
    server.cpp
    session.cpp
)

set_target_properties(server PROPERTIES LINKER_LANGUAGE CXX)
target_include_directories(server PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}")
以及在session.hpp中生成链接错误的代码

#pragma once

#include <boost/asio.hpp>
#include <string>
#include <deque>
#include <memory>
#include <message/message.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/bind/bind.hpp>

class Session : public std::enable_shared_from_this<Session>
{
public:
    Session(boost::asio::ip::tcp::socket socket) : socket(std::move(socket))
    {
    }

    void run();
    void printMessage(const boost::system::error_code &e);
    boost::asio::streambuf stream_buf;

private:
    boost::asio::ip::tcp::socket socket;
    common::message::Message msg;

    template <typename Handler>
    void readMsg(Handler handler)
    {
        void (Session::*f)(
            const boost::system::error_code &,
            common::message::Message &, boost::tuple<Handler>) = &Session::handle_read_header<common::message::Message, Handler>;
        boost::asio::async_read(socket, boost::asio::buffer(inboundHeader),
                                boost::bind(f,
                                            this, boost::asio::placeholders::error, boost::ref(msg),
                                            boost::make_tuple(handler)));
    }

    template <typename T, typename Handler>
    void handle_read_header(const boost::system::error_code &e,
                            T &t, boost::tuple<Handler> handler)
    {
        if (e)
        {
            boost::get<0>(handler)(e);
        }
        else
        {
            std::istringstream is(std::string(inboundHeader, headerLength));
            std::size_t inbound_data_size = 0;
            if (!(is >> std::hex >> inbound_data_size))
            {
                boost::system::error_code error(boost::asio::error::invalid_argument);
                boost::get<0>(handler)(error);
                return;
            }

            inboundData.resize(inbound_data_size);
            void (Session::*f)(
                const boost::system::error_code &,
                T &, boost::tuple<Handler>) = &Session::handle_read_data<T, Handler>;
            boost::asio::async_read(socket, boost::asio::buffer(inboundData),
                                    boost::bind(f, this,
                                                boost::asio::placeholders::error, boost::ref(t), handler));
        }
    }

    template <typename T, typename Handler>
    void handle_read_data(const boost::system::error_code &e,
                          T &t, boost::tuple<Handler> handler)
    {
        if (e)
        {
            boost::get<0>(handler)(e);
        }
        else
        {
            try
            {
                std::string archive_data(&inboundData[0], inboundData.size());
                std::istringstream archive_stream(archive_data);
                boost::archive::text_iarchive archive(archive_stream);
                archive >> t;
            }
            catch (std::exception &e)
            {
                boost::system::error_code error(boost::asio::error::invalid_argument);
                boost::get<0>(handler)(error);
                return;
            }
            boost::get<0>(handler)(e);
        }
    }

    static const size_t headerLength{8};
    std::string outboundHeader;
    std::string outboundData;
    char inboundHeader[headerLength];
    std::vector<char> inboundData;
};
#pragma一次
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
类会话:public std::从\u中启用\u共享\u
{
公众:
会话(boost::asio::ip::tcp::socket套接字):套接字(std::move(socket))
{
}
无效运行();
无效打印消息(const boost::system::error\u code&e);
boost::asio::streambuf stream\u buf;
私人:
boost::asio::ip::tcp::socket;
公共::消息::消息消息消息;
模板
void readMsg(处理程序)
{
无效(会话::*f)(
常量boost::系统::错误\u代码&,
common::message::message&,boost::tuple)=&Session::handle\u read\u头;
boost::asio::async_读取(套接字,boost::asio::buffer(inboundHeader),
boost::bind(f,
这个,boost::asio::占位符::错误,boost::ref(msg),
boost::make_tuple(handler));
}
模板
无效句柄读取头(const boost::system::error\u code&e,
T&T,boost::元组处理程序)
{
如果(e)
{
boost::get(handler)(e);
}
其他的
{
std::istringstream是(std::string(inboundHeader,headerLength));
std::size\u t入站数据\u size=0;
如果(!(是>>标准::十六进制>>入站数据大小))
{
boost::system::error\u代码错误(boost::asio::error::无效的\u参数);
boost::get(处理程序)(错误);
返回;
}
inboundData.resize(入站数据大小);
无效(会话::*f)(
常量boost::系统::错误\u代码&,
T&,boost::tuple)=&Session::handle\u read\u data;
boost::asio::async_读取(套接字,boost::asio::buffer(inboundData),
boost::bind(f,this,
boost::asio::占位符::错误,boost::ref(t),处理程序);
}
}
模板
无效句柄读取数据(const boost::system::error\u code&e,
T&T,boost::元组处理程序)
{
如果(e)
{
boost::get(handler)(e);
}
其他的
{
尝试
{
std::string archive_data(&inboundData[0],inboundData.size());
std::istringstream存档\u流(存档\u数据);
boost::archive::text\u iarchive归档(归档流);
档案>>t;
}
捕获(标准::异常&e)
{
boost::system::error\u代码错误(boost::asio::error::无效的\u参数);
boost::get(处理程序)(错误);
返回;
}
boost::get(handler)(e);
}
}
静态常量大小\u t头长{8};
std::字符串outboundHeader;
std::字符串外部数据;
char inboundHeader[标题长度];
std::矢量边界内数据;
};

序列化是预构建库,因此必须将其包含在find命令中:
find_包(Boost 1.65.1.0要求系统序列化)

仅搜索Boost和Boost::system将只包括Boost和系统库的头文件,而不包括序列化库的二进制文件。
它编译的原因是,Boost::Boost包含序列化头,但它无法链接,因为您没有链接到实现。

如果您使用
-lboost\u serialization
手动构建,它能工作吗?您需要在Boost之后移动add\u子目录(src)。否则它是未知的。我尝试了以下g++main.cpp src/server.cpp src/session.cpp-lboost\u序列化和相同的问题。如果您在使用
-lboost\u序列化进行手动构建时遇到相同的问题,我会说您的安装已中断。我根据boost文档重新安装了boost,得到了最新的cmake,现在手动构建工作正常,所以我认为cmake现在有问题。我将其添加到我的根CmakeList中,并按照@vre的建议在find_包后移动了add_子目录(src),但仍然存在相同的问题:/您使用的是boost的共享库,您是否可以测试将
Boost\u USE\u STATIC\u LIBS
更改为
ON
或确保您的Boost二进制文件(.dll/.so)位于全局路径中。