You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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();

构建验证

  1. 删除原build目录,重新执行CMake配置:
mkdir build && cd build
cmake .. -G "Visual Studio 17 2022" # 根据你的VS版本选择对应生成器
  1. 构建目标:
cmake --build . --target uwebsocketsExample1 --config Release
  1. 运行生成的可执行文件:
bin/Release/uwebsocketsExample1.exe

内容的提问来源于stack exchange,提问作者shashashamti2008

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 11:44:51