websocketpp庫編譯的心路歷程
阿新 • • 發佈:2018-12-16
前因後果
最近需要用到websocket,google找到star最高的websockpp庫,打算引入進來,但整個編譯過程異常艱辛,出現各種異常錯誤,本文做個統一記錄和梳理,以作備忘。
編譯過程
github下載原始碼
編譯demo
websocketpp/examples/echo_client
先來看下CMakeList.txt檔案
file (GLOB SOURCE_FILES *.cpp)# 設定全域性變數 file (GLOB HEADER_FILES *.hpp)# 設定全域性變數 init_target (echo_client)# 呼叫init_target,初始化專案名稱為echo_client build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES}) #編譯二進位制 link_boost () # 連結boost庫 final_target () # 完成目標輸出 set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "examples") #設定目標輸出屬性
執行在websocketpp/examples/echo_client
目錄執行cmake .
,報如下錯誤
## 遇到問題1 編譯找不到init_target命令
CMake Error at CMakeLists.txt:5 (init_target):
Unknown CMake command "init_target".
提示找不到init_target命令,找了下init_target命令定義在
解決方法有兩個:
- 先將CMakeHelpers.cmake 引入進來(遺留問題:暫未找到cmake如何引入其他cmakelist檔案?)
- 簡單的方法直接將CMakeHelpers.cmake內容copy到examples/echo_client/CMakeList.txt 前面;
這裡為了簡單採用第2中方法,修改後的CMakeList.txt檔案內容如下:
cmake_minimum_required(VERSION 3.11) # Print build configuration macro (print_used_build_config) message ("\n=========== Used Build Configuration =============\n") message (STATUS "ENABLE_CPP11 = " ${ENABLE_CPP11}) message (STATUS "BUILD_EXAMPLES = " ${BUILD_EXAMPLES}) message (STATUS "BUILD_TESTS = " ${BUILD_TESTS}) message ("") message (STATUS "WEBSOCKETPP_ROOT = " ${WEBSOCKETPP_ROOT}) message (STATUS "WEBSOCKETPP_BIN = " ${WEBSOCKETPP_BIN}) message (STATUS "WEBSOCKETPP_LIB = " ${WEBSOCKETPP_LIB}) message (STATUS "Install prefix = " ${CMAKE_INSTALL_PREFIX}) message ("") message (STATUS "WEBSOCKETPP_BOOST_LIBS = ${WEBSOCKETPP_BOOST_LIBS}") message (STATUS "WEBSOCKETPP_PLATFORM_LIBS = ${WEBSOCKETPP_PLATFORM_LIBS}") message (STATUS "WEBSOCKETPP_PLATFORM_TLS_LIBS = ${WEBSOCKETPP_PLATFORM_TLS_LIBS}") message ("") message (STATUS "OPENSSL_FOUND = ${OPENSSL_FOUND}") message (STATUS "OPENSSL_INCLUDE_DIR = ${OPENSSL_INCLUDE_DIR}") message (STATUS "OPENSSL_LIBRARIES = ${OPENSSL_LIBRARIES}") message (STATUS "OPENSSL_VERSION = ${OPENSSL_VERSION}") message ("") endmacro () # Adds the given folder_name into the source files of the current project. # Use this macro when your module contains .cpp and .h files in several subdirectories. # Your sources variable needs to be WSPP_SOURCE_FILES and headers variable WSPP_HEADER_FILES. macro(add_source_folder folder_name) file(GLOB H_FILES_IN_FOLDER_${folder_name} ${folder_name}/*.hpp ${folder_name}/*.h) file(GLOB CPP_FILES_IN_FOLDER_${folder_name} ${folder_name}/*.cpp ${folder_name}/*.c) source_group("Header Files\\${folder_name}" FILES ${H_FILES_IN_FOLDER_${folder_name}}) source_group("Source Files\\${folder_name}" FILES ${CPP_FILES_IN_FOLDER_${folder_name}}) set(WSPP_HEADER_FILES ${WSPP_HEADER_FILES} ${H_FILES_IN_FOLDER_${folder_name}}) set(WSPP_SOURCE_FILES ${WSPP_SOURCE_FILES} ${CPP_FILES_IN_FOLDER_${folder_name}}) endmacro() # Initialize target. macro (init_target NAME) set (TARGET_NAME ${NAME}) message ("** " ${TARGET_NAME}) # Include our own module path. This makes #include "x.h" # work in project subfolders to include the main directory headers. include_directories (${CMAKE_CURRENT_SOURCE_DIR} ) include_directories ( ${WEBSOCKETPP_LIB} ) endmacro () # Build executable for executables macro (build_executable TARGET_NAME) set (TARGET_LIB_TYPE "EXECUTABLE") message (STATUS "-- Build Type:") message (STATUS " " ${TARGET_LIB_TYPE}) add_executable (${TARGET_NAME} ${ARGN}) include_directories (${WEBSOCKETPP_ROOT} ${WEBSOCKETPP_INCLUDE}) target_link_libraries(${TARGET_NAME} ${WEBSOCKETPP_PLATFORM_LIBS} ${WEBSOCKETPP_BOOST_LIBS}/libboost_chrono.a ${WEBSOCKETPP_BOOST_LIBS}/libboost_system.a ${WEBSOCKETPP_BOOST_LIBS}/libboost_random.a) # set_target_properties (${TARGET_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY /Users/yin/code/go_proj/src/aggregated-exchange/) set_target_properties (${TARGET_NAME} PROPERTIES DEBUG_POSTFIX d) endmacro () # Build executable and register as test macro (build_test TARGET_NAME) build_executable (${TARGET_NAME} ${ARGN}) if (${CMAKE_VERSION} VERSION_LESS 3) message(WARNING "CMake too old to register ${TARGET_NAME} as a test") else () add_test(NAME ${TARGET_NAME} COMMAND $<TARGET_FILE:${TARGET_NAME}>) endif () endmacro () # Finalize target for all types macro (final_target) if ("${TARGET_LIB_TYPE}" STREQUAL "EXECUTABLE") install (TARGETS ${TARGET_NAME} RUNTIME DESTINATION "bin" CONFIGURATIONS ${CMAKE_CONFIGURATION_TYPES}) endif () install (DIRECTORY ${CMAKE_SOURCE_DIR}/${TARGET_NAME} DESTINATION include/ FILES_MATCHING PATTERN "*.hpp*") endmacro () macro (link_boost) target_link_libraries (${TARGET_NAME} ${Boost_LIBRARIES}) set_property(TARGET ${TARGET_NAME} APPEND PROPERTY INCLUDE_DIRECTORIES ${Boost_INCLUDE_DIR}) endmacro () macro (link_openssl) target_link_libraries (${TARGET_NAME} ${OPENSSL_SSL_LIBRARY} ${OPENSSL_CRYPTO_LIBRARY}) set_property(TARGET ${TARGET_NAME} APPEND PROPERTY INCLUDE_DIRECTORIES ${OPENSSL_INCLUDE_DIR}) endmacro () macro (link_zlib) target_link_libraries (${TARGET_NAME} ${ZLIB_LIBRARIES}) set_property(TARGET ${TARGET_NAME} APPEND PROPERTY INCLUDE_DIRECTORIES ${ZLIB_INCLUDE_DIR}) endmacro () macro (include_subdirs PARENT) file (GLOB SDIRS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "${PARENT}/*") foreach (SUBDIR ${SDIRS}) if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${SUBDIR}/CMakeLists.txt") add_subdirectory ("${CMAKE_CURRENT_SOURCE_DIR}/${SUBDIR}") endif () endforeach () endmacro() file (GLOB SOURCE_FILES *.cpp)# 設定全域性變數 file (GLOB HEADER_FILES *.hpp)# 設定全域性變數 init_target (echo_client)# 呼叫init_target,初始化專案名稱為echo_client build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES}) #編譯二進位制 link_boost () # 連結boost庫 final_target () # 完成目標輸出 set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "examples") #設定目標輸出屬性
再次執行編譯,又提示找不到標頭檔案:
/Users/code/src/websocketpp/examples/echo_client/echo_client.cpp:28:10: fatal error: 'websocketpp/config/asio_no_tls_client.hpp' file not found
#include <websocketpp/config/asio_no_tls_client.hpp>
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1 error generated.
原因是沒有設定WEBSOCKETPP_LIB
路徑,解決:
加上一行:
set(WEBSOCKETPP_LIB /Users/code/src/websocketpp )
如果有提示找不到boost庫標頭檔案,需要先安裝boost庫。
又出現boost庫連結錯誤:
/Applications/CLion.app/Contents/bin/cmake/mac/bin/cmake -E cmake_link_script CMakeFiles/echo_client.dir/link.txt --verbose=1
/Library/Developer/CommandLineTools/usr/bin/c++ -g -Wl,-search_paths_first -Wl,-headerpad_max_install_names CMakeFiles/echo_client.dir/echo_client.cpp.o -o echo_clientd
Undefined symbols for architecture x86_64:
"boost::chrono::steady_clock::now()", referenced from:
boost::asio::detail::chrono_time_traits<boost::chrono::steady_clock, boost::asio::wait_traits<boost::chrono::steady_clock> >::now() in echo_client.cpp.o
"boost::random::random_device::random_device()", referenced from:
websocketpp::random::random_device::int_generator<unsigned int, websocketpp::concurrency::basic>::int_generator() in echo_client.cpp.o
"boost::random::random_device::~random_device()", referenced from:
websocketpp::random::random_device::int_generator<unsigned int, websocketpp::concurrency::basic>::~int_generator() in echo_client.cpp.o
websocketpp::random::random_device::int_generator<unsigned int, websocketpp::concurrency::basic>::int_generator() in echo_client.cpp.o
"boost::random::random_device::operator()()", referenced from:
unsigned int boost::random::detail::generate_uniform_int<boost::random::random_device, unsigned int>(boost::random::random_device&, unsigned int, unsigned int, mpl_::bool_<true>) in echo_client.cpp.o
"boost::system::system_category()", referenced from:
boost::asio::error::get_system_category() in echo_client.cpp.o
boost::system::error_code::error_code() in echo_client.cpp.o
"boost::system::generic_category()", referenced from:
boost::thread_exception::thread_exception(int, char const*) in echo_client.cpp.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[3]: *** [echo_clientd] Error 1
make[2]: *** [CMakeFiles/echo_client.dir/all] Error 2
make[1]: *** [CMakeFiles/echo_client.dir/rule] Error 2
make: *** [echo_client] Error 2
需要連結boost庫:
set(WEBSOCKETPP_BOOST_LIBS /usr/local/Cellar/boost/1.67.0_1/lib)
target_link_libraries(${TARGET_NAME} ${WEBSOCKETPP_BOOST_LIBS}/libboost_chrono.a ${WEBSOCKETPP_BOOST_LIBS}/libboost_system.a ${WEBSOCKETPP_BOOST_LIBS}/libboost_random.a)
再次編譯:
** echo_client
-- -- Build Type:
-- EXECUTABLE
-- Configuring done
-- Generating done
-- Build files have been written to: /Users/code//websocketpp/examples/echo_client
[Finished]
大功告成!看到[Finish]那一剎那整個人都釋懷了,總算搞定了。看來自己對編譯連結的知識瞭解得不夠,尤其是CMake更應該多學習,不然引入一個開源庫都要折騰半天,時間實在划不來