首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用cmake链接nghttp2 asio项目

如何使用cmake链接nghttp2 asio项目
EN

Stack Overflow用户
提问于 2021-08-30 18:43:43
回答 1查看 563关注 0票数 0

我有一个项目,我想在那里使用nghttp2库。我试图在CMakeLists.txt中链接这个项目,这样我就可以用cmake编译下面的文件了。

我的项目结构

代码语言:javascript
复制
.
├── CMakeLists.txt
├── lib
│   ├── Catch2
│   └── nghttp2
├── README.md
└── src
    ├── main
    |  └── Main.cpp
    └── test

导入nghttp2的主程序

代码语言:javascript
复制
#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文件如下

代码语言:javascript
复制
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})

当我在make之后运行cmake .时,我会得到以下错误

代码语言:javascript
复制
/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

我可以用

代码语言:javascript
复制
g++  Main.cpp -o Main.out -DBOOST_LOG_DYN_LINK -lboost_log -lnghttp2_asio -lboost_system -lcrypto -lpthread -lssl -lboost_thread

编辑:

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

代码语言:javascript
复制
target_link_libraries(${PROJECT_NAME} PUBLIC /usr/local/lib/libnghttp2_asio.so)

有什么更优雅的方法吗?

EN

回答 1

Stack Overflow用户

发布于 2021-09-04 18:15:05

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

代码语言:javascript
复制
find_library(nghttp2_asio_LIBRARY NAMES nghttp2_asio)
target_link_libraries(${PROJECT_NAME} PUBLIC nghttp2_asio)

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

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

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

要解决您的初始问题,您应该链接到正确的库(nghttp2_asio而不是nghttp2),并在构建nghttp2时设置标志-enable。下面是您的CMake应该是什么样子:

代码语言:javascript
复制
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 2的文档所解释的那样:

默认情况下,libnghttp2_asio不是生成的。使用--启用-asio-lib配置标志来构建libnghttp2_asio。所需的Boost库是: Boost::Asio、Boost::System和Boost::线程。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68988952

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档