使用CMake构建uWebSockets C++示例遇到编译问题求助
解决uWebSockets EchoServer在Windows下的CMake构建问题
问题背景
我基于uWebSockets开发项目,想运行示例中的EchoServer.cpp,但uWebSockets官方没有提供示例的CMake构建配置。项目目录结构如下:
my-app │ CMakeLists.txt │ ├───examples │ CMakeLists.txt │ uwebsockets.example.cpp │ └───external └───uwebsockets CMakeLists.txt
Windows环境下CMake配置和生成能成功,但构建uwebsocketsExample1目标时出错。需要通过external\uWebSockets\CMakeLists.txt使用FetchContent拉取uWebSockets及其子模块(如uSockets),完成EchoServer的构建。
现有文件内容
my-app\CMakeLists.txt
cmake_minimum_required(VERSION 3.24) project(my-app VERSION 1.0.0) set(CMAKE_CXX_STANDARD 20) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) add_subdirectory(external/uWebSockets) add_subdirectory(examples)
external\uwebsockets\CMakeLists.txt
cmake_minimum_required(VERSION 3.24) project(libuWebsockets VERSION 1.0.0) set(CMAKE_CXX_STANDARD 20) include(FetchContent) include(CMakePrintHelpers) FetchContent_Declare(uwebsockets GIT_REPOSITORY https://github.com/uNetworking/uWebSockets.git) FetchContent_MakeAvailable(uwebsockets) add_library(uwebsockets INTERFACE) target_include_directories(uwebsockets INTERFACE ${uwebsockets_SOURCE_DIR}/src) add_library(uwebsockets::uwebsockets ALIAS uwebsockets)
examples\CMakeLists.txt
cmake_minimum_required(VERSION 3.24) project(projExamples VERSION 1.0.0) set(CMAKE_CXX_STANDARD 20) add_executable(uwebsocketsExample1 uwebsockets.example.cpp) target_link_libraries(uwebsocketsExample1 PRIVATE uwebsockets::uwebsockets)
examples\uwebsockets.example.cpp
/* 直接引入根头文件"App.h",即可使用uWS::App和uWS::SSLApp */ #include "App.h" /* 这是一个简单的WebSocket回声服务器示例。 * 可以用"WITH_OPENSSL=1 make"或直接"make"编译 */ int main() { /* ws->getUserData会返回该结构体实例 */ struct PerSocketData { /* 在这里添加自定义用户数据 */ }; /* 注意:如果编译时未开启SSL支持,uWS::SSLApp({options})等价于uWS::App()。 * 不需要SSL的话可以直接用uWS::App() */ uWS::App({ /* 示例证书可以在uWebSockets.js仓库中找到 */ .key_file_name = "misc/key.pem", .cert_file_name = "misc/cert.pem", .passphrase = "1234" }).ws<PerSocketData>("/*", { /* 配置项 */ .compression = uWS::CompressOptions(uWS::DEDICATED_COMPRESSOR_4KB | uWS::DEDICATED_DECOMPRESSOR), .maxPayloadLength = 100 * 1024 * 1024, .idleTimeout = 16, .maxBackpressure = 100 * 1024 * 1024, .closeOnBackpressureLimit = false, .resetIdleTimeoutOnSend = false, .sendPingsAutomatically = true, /* 事件处理器 */ .upgrade = nullptr, .open = [](auto */*ws*/) { /* 连接建立事件,可通过ws->getUserData()访问PerSocketData结构体 */ }, .message = [](auto *ws, std::string_view message, uWS::OpCode opCode) { /* 这里的逻辑和常规需求相反:当消息小于16KB时才压缩 * 这么做是为了方便测试大消息无压缩发送的性能 */ ws->send(message, opCode, message.length() < 16 * 1024); }, .drain = [](auto */*ws*/) { /* 在这里检查ws->getBufferedAmount() */ }, .ping = [](auto */*ws*/, std::string_view) { /* 暂未实现 */ }, .pong = [](auto */*ws*/, std::string_view) { /* 暂未实现 */ }, .close = [](auto */*ws*/, int /*code*/, std::string_view /*message*/) { /* 在这里可以访问ws->getUserData() */ } }).listen(9001, [](auto *listen_socket) { if (listen_socket) { std::cout << "监听端口 " << 9001 << std::endl; } }).run(); }
修复方案
1. 修改external\uwebsockets\CMakeLists.txt
原配置仅拉取了uWebSockets源码,未处理依赖的uSockets子模块,也未链接必要系统库。更新后的配置如下:
cmake_minimum_required(VERSION 3.24) project(libuWebsockets VERSION 1.0.0) set(CMAKE_CXX_STANDARD 20) include(FetchContent) # 拉取uWebSockets并递归拉取子模块 FetchContent_Declare(uwebsockets GIT_REPOSITORY https://github.com/uNetworking/uWebSockets.git GIT_TAG master # 可指定具体版本,如v20.48.0 GIT_SUBMODULES_RECURSE TRUE ) FetchContent_MakeAvailable(uwebsockets) # 构建uSockets子模块 add_subdirectory(${uwebsockets_SOURCE_DIR}/uSockets ${CMAKE_CURRENT_BINARY_DIR}/uSockets) # 定义uwebsockets接口库,链接uSockets和系统库 add_library(uwebsockets INTERFACE) target_include_directories(uwebsockets INTERFACE ${uwebsockets_SOURCE_DIR}/src) target_link_libraries(uwebsockets INTERFACE uSockets) # Windows下需要额外链接ws2_32和psapi库 if(WIN32) target_link_libraries(uwebsockets INTERFACE ws2_32 psapi) endif() add_library(uwebsockets::uwebsockets ALIAS uwebsockets)
2. 调整examples\CMakeLists.txt
添加Windows下的编译定义,避免符号兼容性问题:
cmake_minimum_required(VERSION 3.24) project(projExamples VERSION 1.0.0) set(CMAKE_CXX_STANDARD 20) add_executable(uwebsocketsExample1 uwebsockets.example.cpp) target_link_libraries(uwebsocketsExample1 PRIVATE uwebsockets::uwebsockets) # Windows下添加编译定义,适配系统API版本 if(WIN32) target_compile_definitions(uwebsocketsExample1 PRIVATE _WIN32_WINNT=0x0601) endif()
3. 可选:关闭示例中的SSL支持(若未配置OpenSSL)
如果本地没有OpenSSL环境,将示例代码中的SSL相关配置移除,改用无SSL版本:
// 替换原SSLApp/App配置为: uWS::App().ws<PerSocketData>("/*", { /* 配置项保持不变,去掉.key_file_name等SSL字段 */ .compression = uWS::CompressOptions(uWS::DEDICATED_COMPRESSOR_4KB | uWS::DEDICATED_DECOMPRESSOR), .maxPayloadLength = 100 * 1024 * 1024, .idleTimeout = 16, // ... 其余配置不变 }).listen(9001, [](auto *listen_socket) { if (listen_socket) { std::cout << "监听端口 " << 9001 << std::endl; } }).run();
构建验证
- 删除原build目录,重新执行CMake配置:
mkdir build && cd build cmake .. -G "Visual Studio 17 2022" # 根据你的VS版本选择对应生成器
- 构建目标:
cmake --build . --target uwebsocketsExample1 --config Release
- 运行生成的可执行文件:
bin/Release/uwebsocketsExample1.exe
内容的提问来源于stack exchange,提问作者shashashamti2008
相关产品推荐
相关产品推荐

