我有一个项目,我想在那里使用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})当我在make之后运行cmake .时,我会得到以下错误
/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我可以用
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)有什么更优雅的方法吗?
发布于 2021-09-04 18:15:05
要回答您在编辑初始消息后添加的问题,可以通过使用CMake的find_library来避免手动指定libnghttp2_asio.so的完整路径,如下所示:
find_library(nghttp2_asio_LIBRARY NAMES nghttp2_asio)
target_link_libraries(${PROJECT_NAME} PUBLIC nghttp2_asio)但是,您正在混合两种向项目添加外部库的不同方法。由于您已经在项目中包含nghttp2 2的源代码,因此不应该将您的程序与安装在系统范围内的另一个版本的nghttp2链接起来,至少有两个原因:
相反,我建议您按照最初的计划,从源代码构建libnghttp2_asio。
要解决您的初始问题,您应该链接到正确的库(nghttp2_asio而不是nghttp2),并在构建nghttp2时设置标志-enable。下面是您的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 2的文档所解释的那样:
默认情况下,libnghttp2_asio不是生成的。使用--启用-asio-lib配置标志来构建libnghttp2_asio。所需的Boost库是: Boost::Asio、Boost::System和Boost::线程。
https://stackoverflow.com/questions/68988952
复制相似问题