【问题标题】:How to link nghttp2 asio project using cmake如何使用 cmake 链接 nghttp2 asio 项目
【发布时间】:2021-10-29 11:47:43
【问题描述】:

我有一个项目,我想在其中使用 nghttp2 库。我正在尝试将这个项目链接到CMakeLists.txt,以便我可以使用cmake 编译以下文件。

我的项目结构

.
├── CMakeLists.txt
├── lib
│   ├── Catch2
│   └── nghttp2
├── README.md
└── src
    ├── main
    |  └── Main.cpp
    └── test

导入nghttp2的主程序

#include <iostream>
#include <nghttp2/asio_http2.h>
#include <nghttp2/asio_http2_server.h>
#include <boost/circular_buffer.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/condition_variable.hpp>
#include <boost/thread/thread.hpp>
#include <boost/timer/timer.hpp>
#include <boost/call_traits.hpp>
#include <boost/bind.hpp>
#include <boost/log/trivial.hpp>
#include <string>
#include <limits>

using namespace nghttp2::asio_http2;
using namespace nghttp2::asio_http2::server;

int main(int argc, char *argv[]) {
    boost::system::error_code ec;
    http2 server;

    server.handle("/", [](const request &req, const response &res) {
        res.write_head(200);
        res.end("hello, world\n");
    });

    if (server.listen_and_serve(ec, "localhost", "3000")) {
        std::cerr << "error: " << ec.message() << std::endl;
    }
}

我的CMakeLists.txt 文件如下

cmake_minimum_required(VERSION 3.16.3)
project(my-project)

set(CMAKE_CXX_STANDARD 14)

set(CMAKE_CXX_STANDARD_REQUIRED True)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/build)
set(LIBRARY_NAME ${PROJECT_NAME})
set(TEST_NAME tests)

add_executable(
        ${PROJECT_NAME}

        src/main/Main.cpp
)

find_package(Threads REQUIRED)
find_package(Boost REQUIRED COMPONENTS system)
find_package(Boost REQUIRED COMPONENTS thread)
find_package(Boost REQUIRED COMPONENTS log)
find_package(OpenSSL REQUIRED)

target_link_libraries(
        ${PROJECT_NAME}

        PRIVATE Threads::Threads
        PRIVATE Boost::system
        PRIVATE Boost::thread
        PRIVATE Boost::log
        PRIVATE OpenSSL::Crypto
)

set(NGHTTP2_SRC_DIR lib/nghttp2)
add_subdirectory(${NGHTTP2_SRC_DIR})
target_link_libraries(${PROJECT_NAME} PUBLIC nghttp2)

target_include_directories(
        ${LIBRARY_NAME} PRIVATE
        $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include/${LIBRARY_NAME}>
        $<INSTALL_INTERFACE:include/${LIBRARY_NAME}>
)
target_include_directories(
        ${LIBRARY_NAME} PUBLIC
        $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
        $<INSTALL_INTERFACE:include>
)


# Catch2
set(CATCH2_SRC_DIR lib/Catch2)
add_subdirectory(${CATCH2_SRC_DIR})
add_executable(${TEST_NAME} src/test/Test.cpp)
target_link_libraries(${TEST_NAME} PRIVATE Catch2::Catch2WithMain)
include(${CATCH2_SRC_DIR}/extras/Catch.cmake)
include(${CATCH2_SRC_DIR}/extras/ParseAndAddCatchTests.cmake)
list(APPEND CMAKE_MODULE_PATH ${CATCH2_SRC_DIR}/extras)
include(CTest)
catch_discover_tests(${TEST_NAME})

当我在cmake . 之后运行make 时,出现以下错误

/usr/bin/ld: CMakeFiles/my-project.dir/src/main/Main.cpp.o: in function `std::_Function_handler<void (nghttp2::asio_http2::server::request const&, nghttp2::asio_http2::server::response const&), main::{lambda(nghttp2::asio_http2::server::request const&, nghttp2::asio_http2::server::response const&)#1}>::_M_invoke(std::_Any_data const&, nghttp2::asio_http2::server::request const&, nghttp2::asio_http2::server::response const&)':
/home/username/CLionProjects/myproject/src/main/Main.cpp:23: undefined reference to `nghttp2::asio_http2::server::response::write_head(unsigned int, std::multimap<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, nghttp2::asio_http2::header_value, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, nghttp2::asio_http2::header_value> > >) const'
/usr/bin/ld: CMakeFiles/my-project.dir/src/main/Main.cpp.o: in function `operator()':
/home/username/CLionProjects/myproject/src/main/Main.cpp:24: undefined reference to `nghttp2::asio_http2::server::response::end(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >) const'
/usr/bin/ld: CMakeFiles/my-project.dir/src/main/Main.cpp.o: in function `main.cold':
/home/username/CLionProjects/myproject/src/main/Main.cpp:20: undefined reference to `nghttp2::asio_http2::server::http2::~http2()'
/usr/bin/ld: CMakeFiles/my-project.dir/src/main/Main.cpp.o: in function `main':
/home/username/CLionProjects/myproject/src/main/Main.cpp:20: undefined reference to `nghttp2::asio_http2::server::http2::http2()'
/usr/bin/ld: /home/username/CLionProjects/myproject/src/main/Main.cpp:22: undefined reference to `nghttp2::asio_http2::server::http2::handle(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::function<void (nghttp2::asio_http2::server::request const&, nghttp2::asio_http2::server::response const&)>)'
/usr/bin/ld: /home/username/CLionProjects/myproject/src/main/Main.cpp:27: undefined reference to `nghttp2::asio_http2::server::http2::listen_and_serve(boost::system::error_code&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, bool)'
/usr/bin/ld: /home/username/CLionProjects/myproject/src/main/Main.cpp:20: undefined reference to `nghttp2::asio_http2::server::http2::~http2()'
collect2: error: ld returned 1 exit status
make[2]: *** [CMakeFiles/my-project.dir/build.make:95: build/my-project] Error 1
make[1]: *** [CMakeFiles/Makefile2:942: CMakeFiles/my-project.dir/all] Error 2
make: *** [Makefile:141: all] Error 2

我可以手动编译Main.cpp

g++  Main.cpp -o Main.out -DBOOST_LOG_DYN_LINK -lboost_log -lnghttp2_asio -lboost_system -lcrypto -lpthread -lssl -lboost_thread

编辑:

我首先在我的机器上安装了nghttp2 来编译它。然后在CMakeLists.txt中加入这一行@

target_link_libraries(${PROJECT_NAME} PUBLIC /usr/local/lib/libnghttp2_asio.so)

有没有更优雅的方法来做到这一点?

【问题讨论】:

  • 在命令行中你链接到nghttp2_asio 库,但我在你的CMakeLists.txt 中没有看到这样的链接。
  • @Tsyvarev 是的。我在问如何链接 nghttp2_asio

标签: c++ cmake asio nghttp2


【解决方案1】:

要回答您在编辑初始消息后添加的问题,您可以避免使用 CMake 的 find_library 手动指定 libnghttp2_asio.so 的完整路径,如下所示:

find_library(nghttp2_asio_LIBRARY NAMES nghttp2_asio)
target_link_libraries(${PROJECT_NAME} PUBLIC nghttp2_asio)

但是,您正在混合使用两种不同的方式将外部库添加到您的项目中。由于您已经在项目中包含了 nghttp2 的源代码,因此您不应该将您的程序与您在系统范围内安装的另一个版本的 nghttp2 链接起来,至少有两个原因:

  • 您在项目中包含的 nghttp2 标头可能与您在系统范围内安装的 nghttp2 库的版本不匹配,这可能会导致链接错误
  • 如果有人克隆了您的代码,他们也必须在他们的系统上安装 nghttp2,并且他们可能会遇到与上一点中解释的相同的链接错误

相反,我建议您按照最初的计划从源代码构建 libnghttp2_asio。

要解决您最初的问题,您应该链接到正确的库(nghttp2_asio 而不是 nghttp2)并在构建 nghttp2 时设置标志 --enable-asio-lib。以下是您的 CMake 的外观:

set(NGHTTP2_SRC_DIR lib/nghttp2)
set(ENABLE_ASIO_LIB ON)
add_subdirectory(${NGHTTP2_SRC_DIR})
target_link_libraries(${PROJECT_NAME} PUBLIC nghttp2_asio)

此外,您必须在首次调用 target_link_libraries 时将 Boost::asio 添加到库列表中,如 nghttp2 的文档中所述:

libnghttp2_asio 默认不构建。使用 --enable-asio-lib 配置标志以构建 libnghttp2_asio。所需的 Boost 库 分别是:Boost::Asio、Boost::System 和 Boost::Thread。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-03-17
    • 1970-01-01
    • 2022-11-27
    • 2021-09-22
    • 2021-08-06
    • 1970-01-01
    • 1970-01-01
    • 2017-08-07
    相关资源
    最近更新 更多