websocketpp库编译的⼼路历程
前因后果
最近需要⽤到websocket,google到star最⾼的websockpp库,打算引⼊进来,但整个编译过程异常艰⾟,出现各种异常错误,本⽂做个统⼀记录和梳理,以作备忘。
编译过程
github下载源码
编译demo
websocketpp/examples/echo_client
先来看下⽂件
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 :5 (init_target):
Unknown CMake command "init_target".
提⽰不到init_target命令,了下init_target命令定义在
解决⽅法有两个:
1. 先将ake 引⼊进来(遗留问题:暂未到cmake如何引⼊其他cmakelist⽂件?)
2. 简单的⽅法直接将ake内容copy到examples/echo_ 前⾯;
这⾥为了简单采⽤第2中⽅法,修改后的⽂件内容如下:
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 (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 ()system的头文件
# 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 ${WEBSOCKETP P_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)
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}/")
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库头⽂件,需要先安oost库。
⼜出现boost库链接错误:
/Applications/CLion.app/Contents/bin/cmake/mac/bin/cmake -E cmake_link_script CMakeFiles/echo_client. --verbose=1
/Library/Developer/CommandLineTools/usr/bin/c++  -g -Wl,-search_paths_first -Wl,-headerpad_max_install_names  CMakeFiles/echo_client.dir/echo_clien t.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 ${WE BSOCKETPP_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更应该多学习,不然引⼊⼀个开源库都要折腾半天,时间实在划不来