Search code examples
c++boostcmakeboost-asioboost-beast

CMake multiple errors when include boost/beast/http.hpp


I'm trying to build my project that uses boost beast library with cmake. When I use only boost asio library everything builds okay. But when I add boost/beast/http.hpp header when cmake gives a huge amount of errors.

CMake file:


cmake_minimum_required(VERSION 3.10)

project(ConsoleChat.Server)

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

find_package(Boost 1.75.0 REQUIRED COMPONENTS system filesystem)

add_definitions(-DBOOST_ERROR_CODE_HEADER_ONLY)

include_directories(${Boost_INCLUDE_DIRS})

link_directories(${Boost_LIBRARY_DIRS})

add_executable(ConsoleChat.Server main.cpp)
target_link_libraries(ConsoleChat.Server ${Boost_LIBRARIES})

Code file:

#include <cstdlib>
#include <memory>
#include <thread>
#include <iostream>
#include <string>

#include <boost/asio.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/beast/version.hpp>
#include <boost/beast/http.hpp>

namespace net = boost::asio;
namespace beast = boost::beast;
namespace http = beast::http;
using tcp = boost::asio::ip::tcp;

int main(int argc, char* argv[])
{
    try
    {
        if (argc != 3)
        {
            std::cout <<
                "Usage: websocket-chat-multi <address> <port>\n" <<
                "Example:\n" <<
                "    websocket-chat-server 0.0.0.0 8080\n";
            return EXIT_FAILURE;
        }

        auto const address = net::ip::address::from_string(argv[1]);//net::ip::make_address(argv[1]); 
        auto const port = static_cast<unsigned short>(std::atoi(argv[2]));

        net::io_service ios{1};

        tcp::acceptor acceptor{ios, {address, port}};
    
        for (;;)
        {
            tcp::socket socket{ios};

            acceptor.accept(socket);
        }
    }
    catch(const std::exception& e)
    {
        std::cout << e.what() << '\n';
    }
}

Example of error:

In file included from /usr/local/include/boost/beast/core/buffer_traits.hpp:14,
                 from /usr/local/include/boost/beast/http/basic_dynamic_body.hpp:14,
                 from /usr/local/include/boost/beast/http.hpp:15,
                 from /home/kudryavii/projects/ConsoleChat/ConsoleChat.Server/main.cpp:10:
/usr/local/include/boost/beast/core/detail/buffer_traits.hpp:66:18: error: ‘is_const_buffer_sequence’ is not a member of ‘boost::beast::net’
   66 |             net::is_const_buffer_sequence<B>::value>::type>
      |                  ^~~~~~~~~~~~~~~~~~~~~~~~
/usr/local/include/boost/beast/core/detail/buffer_traits.hpp:66:18: error: ‘is_const_buffer_sequence’ is not a member of ‘boost::beast::net’

I tried to add all boost libraries to find package section but this didn't help.


Solution

  • Yup. The preprocessed source confirms that the first mention of is_const_buffer_sequence is from line 116485 (eek), which is attributed to

    # 49 "/usr/local/include/boost/beast/core/detail/buffer_traits.hpp" 3
    

    from line 116467. On my system, that's not the first mention, because (obviously?) the declaration in boost_1_75_0/boost/asio/buffer.hpp comes before:

    # 2422 "/home/sehe/custom/boost_1_75_0/boost/asio/buffer.hpp" 2 3 4
    

    The include tree for it checks out as¹

    /usr/include/boost/asio.hpp -->
      /usr/include/boost/asio/basic_datagram_socket.hpp -->
        /usr/include/boost/asio/datagram_socket_service.hpp -->
          /usr/include/boost/asio/detail/null_socket_service.hpp -->
            /usr/include/boost/asio/buffer.hpp
    

    So, let's see if we can trace the similar path for your preprocessed source.

    Reducing all the line directives (by stripping actual line numbers, and eliminating subsequent duplicates) I see the expected trail. However, then I spot differences:

    # 124 "/usr/local/include/boost/asio/buffer.hpp" 3
    private:
      friend void* boost::asio::detail::buffer_cast_helper(
          const mutable_buffer& b);
      friend std::size_t boost::asio::detail::buffer_size_helper(
          const mutable_buffer& b);
    
      void* data_;
      std::size_t size_;
    

    Huh? In 1.75.0 these friends don't exist: https://github.com/boostorg/asio/blob/boost-1.75.0/include/boost/asio/buffer.hpp

    You clearly have something else than Boost 1.75.0 installed there - which is funny because CMake's FindPackage should have complained? Anyways, spelunking some more:

    git grep -l is_const_buffer_sequence boost-1.{60..75}.0 | grep buffer.hpp
    boost-1.66.0:include/boost/asio/buffer.hpp
    boost-1.67.0:include/boost/asio/buffer.hpp
    boost-1.68.0:include/boost/asio/buffer.hpp
    boost-1.69.0:include/boost/asio/buffer.hpp
    boost-1.70.0:include/boost/asio/buffer.hpp
    boost-1.71.0:include/boost/asio/buffer.hpp
    boost-1.72.0:include/boost/asio/buffer.hpp
    boost-1.73.0:include/boost/asio/buffer.hpp
    boost-1.74.0:include/boost/asio/buffer.hpp
    boost-1.75.0:include/boost/asio/buffer.hpp
    

    And maybe also find out when the friend got deleted:

    git grep -l friend boost-1.{60..75}.0 | grep buffer.hpp
    boost-1.60.0:include/boost/asio/buffer.hpp
    boost-1.61.0:include/boost/asio/buffer.hpp
    boost-1.62.0:include/boost/asio/buffer.hpp
    boost-1.63.0:include/boost/asio/buffer.hpp
    boost-1.64.0:include/boost/asio/buffer.hpp
    boost-1.65.0:include/boost/asio/buffer.hpp
    

    Right at the same moment. Looks like we can pinpoint an upper-bound to your boost asio header:

    git log -Sfriend include/boost/asio/buffer.hpp
    commit b60e92b13ef68dfbb9af180d76eae41d22e19356
    Author: Christopher Kohlhoff <[email protected]>
    Date:   Mon Oct 23 14:27:36 2017 +1100
    
        Initial merge of Networking TS compatibility.
        
        Merged from chriskohlhoff/asio master branch as of commit
        4a4d28b0d24c53236e229bd1b5f378c9964b1ebb.
    

    That's the same commit that introduced the is_const_buffer_sequence. Git confirms that your Asio version is definitely boost 1.65.0 or older²:

    git tag --contains b60e92b13ef68dfbb9af180d76eae41d22e19356
    boost-1.66.0
    boost-1.67.0
    boost-1.68.0
    boost-1.69.0
    boost-1.69.0-beta1
    boost-1.70.0
    boost-1.70.0.beta1
    boost-1.71.0
    boost-1.71.0.beta1
    boost-1.72.0
    boost-1.72.0.beta1
    boost-1.73.0
    boost-1.73.0.beta1
    boost-1.74.0
    boost-1.74.0.beta1
    boost-1.75.0
    boost-1.75.0.beta1
    

    Now the wild thing is: Boost Beast didn't exist until Boost 1.66.0

    In short, your install is broken. Firstly, you have an old Asio with newer Beast headers. Secondly, it's installed in such a way that CMake apparently detects it as a valid Boost installation satisfying 1.75.0 required.


    ¹ (this is not 100% full fidelity as I checked using vim's :check! command, which doesn't use libclang or anything options/preprocessor aware)

    ² Of course it will be much easier for you to just look in /usr/include/boost/version.hpp or print the value of BOOST_LIB_VERSION:

    std::cout << BOOST_LIB_VERSION << "\n";