news 2026/9/30 6:55:42

raylib CMake 项目模板实战指南:从桌面窗口到 WebAssembly 的一键构建

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
raylib CMake 项目模板实战指南:从桌面窗口到 WebAssembly 的一键构建
  • 游戏开发
  • 图形学
  • 3D渲染

【免费下载链接】raylib

A simple and easy-to-use library to enjoy videogames programming

项目地址:https://gitcode.com/GitHub_Trending/ra/raylib
点击查看免费下载

导读

本文以 raylib 官方仓库中的 projects/CMake/README.md 项目模板为核心,完整讲解如何用 CMake 搭建一个可同时面向桌面平台与Web 平台的 raylib 项目。你将学会使用cmake -B build完成桌面构建、借助 Emscripten SDK 通过emcmake交叉编译出.html网页版本,并理解模板中find_package+FetchContent自动拉取 raylib、Web 链接参数、macOS 框架链接等底层细节,最终让一个core_basic_window.c示例在你的目标平台上顺利跑起来。

一、模板定位与项目结构

该模板位于仓库的projects/CMake/目录,是一个最小可用的 raylib CMake 工程骨架,目录下只有三个文件:

  • CMakeLists.txt:核心构建脚本,负责依赖解析、目标定义与平台差异化配置;
  • core_basic_window.c:一个特意为 HTML5 平台做过适配的"基础窗口"示例(文件头注释明确说明"This example is prepared to compile for PLATFORM_WEB and PLATFORM_DESKTOP");
  • README.md:官方给出的构建说明。

它的设计意图非常清晰:同一份源码、同一个 CMake 工程,通过不同的 CMake 命令切换目标平台。这与 raylib 主工程(src/CMakeLists.txt)中通过PLATFORM变量(Desktop;Win32;Web;WebRGFW;Android;Raspberry Pi;DRM;SDL;RGFW;Memory)控制平台编译的做法一脉相承,只不过模板把平台选择收敛到了构建命令层面,让用户无需深入理解 raylib 内部的平台宏。

二、桌面平台构建:两行命令

README 给出的桌面构建命令非常简单:

cmake -B build cmake --build build
  • cmake -B build将构建目录指定为build,并在该目录中生成构建系统文件(Linux/macOS 上默认是 Makefile,Windows 上则是 Visual Studio 工程);
  • cmake --build build直接在目标平台默认的生成器上完成编译链接,最终产出可执行文件。

如果你正在仓库的projects/CMake/目录下操作,也可以把它当作独立工程直接构建。构建完成后,运行生成的可执行文件即可看到 800×450 的窗口,中央显示 "Congrats! You created your first window!"。

三、Web 平台构建:借助 Emscripten 交叉编译

Web 构建与桌面最大的不同在于:它需要一个能把 C 代码编译为 WebAssembly 的工具链——Emscripten SDK。README 中给出的完整流程如下:

mkdir build cd build emcmake cmake .. -DPLATFORM=Web -DCMAKE_BUILD_TYPE=Release -DCMAKE_EXECUTABLE_SUFFIX=".html" emmake make

逐条拆解这条命令链:

  1. mkdir build && cd build:新建并进入构建目录(模板中的-B build写法在 emcmake 场景下同样适用,这里沿用 README 的原始写法);
  2. emcmake cmake ..:用 Emscripten 的 CMake 包装器配置工程,确保编译器、链接器被替换为emcc/emar;
  3. -DPLATFORM=Web:告诉 raylib 以 Web 平台模式编译。该参数对应 raylib 主工程的 CMakeOptions.txt 中enum_option(PLATFORM "Desktop;Win32;Web;WebRGFW;Android;Raspberry Pi;DRM;SDL;RGFW;Memory" ...)的取值之一;
  4. -DCMAKE_BUILD_TYPE=Release:使用 Release 优化级别;
  5. -DCMAKE_EXECUTABLE_SUFFIX=".html":使最终产物带上.html后缀,方便直接用浏览器打开;
  6. emmake make:调用 Emscripten 包装后的 make 完成编译,产出.html+.wasm等文件。

四、模板 CMakeLists.txt 逐段解析

模板的 CMakeLists.txt 虽然只有 40 余行,却完整覆盖了依赖解析、目标定义与平台分支,是理解整个构建流程的关键。下面逐段拆解。

4.1 工程声明与 compile_commands

cmake_minimum_required(VERSION 3.11) # FetchContent is available in 3.11+ project(example) # Generate compile_commands.json set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
  • 最低要求 CMake 3.11,注释点明了原因:FetchContent 自 3.11 起可用;
  • project(example)将可执行目标命名为example;
  • CMAKE_EXPORT_COMPILE_COMMANDS ON会在构建目录生成compile_commands.json,方便 clangd、ccls 等语言服务器实现精确的代码补全与跳转。

4.2 依赖解析:find_package + FetchContent 双保险

set(RAYLIB_VERSION 6.0) find_package(raylib ${RAYLIB_VERSION} QUIET) # QUIET or REQUIRED if (NOT raylib_FOUND) # If there's none, fetch and build raylib include(FetchContent) FetchContent_Declare( raylib DOWNLOAD_EXTRACT_TIMESTAMP OFF URL https://github.com/raysan5/raylib/archive/refs/tags/${RAYLIB_VERSION}.tar.gz ) FetchContent_GetProperties(raylib) if (NOT raylib_POPULATED) # Have we downloaded raylib yet? set(FETCHCONTENT_QUIET NO) FetchContent_MakeAvailable(raylib) endif() endif()

这是模板中最核心的机制,采用"先找后拉"策略:

  • 优先查找已安装的 raylib:find_package(raylib 6.0 QUIET)会通过系统安装的raylib-config.cmake(仓库中对应文件为 cmake/raylib-config.cmake,内部include("${CMAKE_CURRENT_LIST_DIR}/raylib-targets.cmake"))定位已安装的库。若系统未安装,或版本不满足,raylib_FOUND为假;
  • 找不到则自动下载编译:进入FetchContent分支,从官方 tag 下载v6.0源码压缩包,由FetchContent_MakeAvailable(raylib)将 raylib 作为子工程直接编入你的项目。DOWNLOAD_EXTRACT_TIMESTAMP OFF避免了解压时间戳差异导致的校验失败;
  • 幂等保护:if (NOT raylib_POPULATED)确保同一个配置过程内不会重复拉取。

提示:find_package(raylib 6.0 QUIET)也可改为REQUIRED(注释里明确写着"QUIET or REQUIRED"),此时若系统没有安装 raylib,CMake 会直接报错而非自动下载,适合对依赖来源有严格要求的团队。

4.3 目标定义与链接

add_executable(${PROJECT_NAME} core_basic_window.c) #set(raylib_VERBOSE 1) target_link_libraries(${PROJECT_NAME} raylib)
  • 以core_basic_window.c为唯一源文件创建可执行目标;
  • target_link_libraries(... raylib)链接 raylib 目标。无论 raylib 来自find_package还是FetchContent,目标名都是raylib,因此这一行对两种来源都成立;
  • 被注释掉的set(raylib_VERBOSE 1)是 raylib 内部的调试开关,打开后可观察其编译细节。

4.4 Web 平台专属配置

if (${PLATFORM} STREQUAL "Web") set_target_properties(${PROJECT_NAME} PROPERTIES SUFFIX ".html") # Tell Emscripten to build an example.html file. set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s USE_GLFW=3 -s ASSERTIONS=1 -s WASM=1 -s ASYNCIFY -s GL_ENABLE_GET_PROC_ADDRESS=1") endif()

当PLATFORM=Web时:

  • SUFFIX ".html"让 Emscripten 以 HTML 外壳形式输出,即最终example.html;
  • 通过链接器标志告诉 Emscripten:使用内嵌 GLFW3(-s USE_GLFW=3)、开启断言(ASSERTIONS=1)、生成 WASM(WASM=1)、启用ASYNCIFY(用于文件预加载等异步场景)以及允许运行时获取 GL 函数地址。

这些标志与 raylib 主工程 src/CMakeLists.txt 中if (${PLATFORM} MATCHES "Web")分支的做法(target_link_options(raylib PUBLIC "-sUSE_GLFW=3" -sEXPORTED_RUNTIME_METHODS=ccall))互相印证,说明 Web 构建在 raylib 生态中是一等公民。

4.5 macOS 框架链接

if (APPLE) target_link_libraries(${PROJECT_NAME} "-framework IOKit") target_link_libraries(${PROJECT_NAME} "-framework Cocoa") target_link_libraries(${PROJECT_NAME} "-framework OpenGL") target_link_libraries(${PROJECT_NAME} "-framework QuartzCore") endif()

macOS 上 raylib 依赖的窗口/图形系统来自系统框架,因此必须显式链接 IOKit、Cocoa、OpenGL、QuartzCore 四个框架。这与 raylib 自身在静态库安装场景下向消费者传播这些框架依赖的处理(见 src/CMakeLists.txt 中APPLE AND PLATFORM STREQUAL "Desktop"分支的find_library逻辑)是一致的。

五、示例源码:一套代码,两种主循环

模板中的 core_basic_window.c 是一个刻意示范"跨平台写法"的示例。它的核心结构如下:

#include "raylib.h" #if defined(PLATFORM_WEB) #include <emscripten/emscripten.h> #endif int screenWidth = 800; int screenHeight = 450; void UpdateDrawFrame(void); int main() { InitWindow(screenWidth, screenHeight, "raylib [core] example - basic window"); #if defined(PLATFORM_WEB) emscripten_set_main_loop(UpdateDrawFrame, 0, 1); #else SetTargetFPS(60); // Set our game to run at 60 frames-per-second while (!WindowShouldClose()) // Detect window close button or ESC key { UpdateDrawFrame(); } #endif CloseWindow(); return 0; } void UpdateDrawFrame(void) { BeginDrawing(); ClearBackground(RAYWHITE); DrawText("Congrats! You created your first window!", 190, 200, 20, LIGHTGRAY); EndDrawing(); }

要点在于帧循环的分裂:

  • 桌面/原生平台:使用while (!WindowShouldClose())经典循环,配合SetTargetFPS(60)锁定 60 FPS;
  • Web 平台:浏览器不允许阻塞主线程的死循环,必须把"每帧更新+绘制"逻辑注册为emscripten_set_main_loop(UpdateDrawFrame, 0, 1)回调,由浏览器事件循环驱动;
  • 通用的UpdateDrawFrame()函数把"更新"和"绘制"逻辑抽离,保证两种平台共享同一套渲染代码。

这也解释了为什么 README 在 Web 构建时特别要求-DPLATFORM=Web:只有该宏开启,示例中的PLATFORM_WEB分支才会被激活。

六、从模板到 raylib 主工程:平台与选项的对应关系

如果你要基于该模板扩展成自己的游戏工程,理解模板与 raylib 主工程构建选项的对应关系会很有帮助。

  • PLATFORM 取值:模板中PLATFORM=Web只是 CMakeOptions.txt 中枚举(Desktop;Win32;Web;WebRGFW;Android;Raspberry Pi;DRM;SDL;RGFW;Memory)的一种。想构建其他平台,只需用对应字符串替代,例如-DPLATFORM=Android;
  • 依赖 GLFW 的方式:raylib 主工程通过 cmake/GlfwImport.cmake 决定使用内嵌 GLFW(external/glfw子目录)还是系统 GLFW。桌面平台默认编译内嵌 GLFW,并强制关闭其文档/测试/示例构建以加快编译;Web 平台的 GLFW 则由 Emscripten 的-s USE_GLFW=3链接标志提供,因此模板的 Web 分支无需额外处理 GLFW;
  • Web 示例的完整形态:如果想了解 Web 构建的完整参数组合,可参考 examples/CMakeLists.txt 的 Web 分支——它为每个示例追加-sALLOW_MEMORY_GROWTH=1、导出requestFullscreen运行时方法、使用 src/shell.html 作为 HTML 外壳,并通过--preload-file将resources目录预加载进 WASM 文件系统。这些是模板之外更精细的 Web 优化项,可按需借鉴。

七、常见问题与注意事项

  1. 桌面构建找不到 raylib?两种解决方案:先安装 raylib 到系统(使find_package命中),或保持模板默认,让FetchContent自动下载 v6.0 源码编译。后者需要网络可达 GitHub 下载源。
  2. Web 构建报emcmake: command not found?说明 Emscripten SDK 未安装或未激活环境,请先按官方文档安装并source对应环境脚本。
  3. Web 产物运行方式:emmake make产出的.html文件不能直接用file://双击打开(WASM 加载受浏览器安全策略限制),应在本地启动静态文件服务(如python3 -m http.server)后通过http://localhost访问。
  4. Web 与桌面主循环差异:移植自己的代码到 Web 时,务必像模板示例那样把帧逻辑收敛进回调函数,并保证全局状态可跨帧保持,因为emscripten_set_main_loop不再拥有普通while循环的栈上下文。
  5. OpenGL 版本与框架:在 macOS 上如果遇到链接错误,检查模板中的四个-framework参数是否完整;在 Linux 桌面端,raylib 主工程在GLFW_BUILD_X11开启时还会要求 X11 开发包(见 src/CMakeLists.txt 的find_package(X11 REQUIRED)),请确保系统已安装相关开发库。

八、总结

projects/CMake/模板用极简的工程结构,演示了 raylib 跨平台构建的标准姿势:桌面端两条命令即可完成配置与编译;Web 端借助 Emscripten 的emcmake/emmake与-DPLATFORM=Web实现源码级复用。其背后依赖解析的"find_package 优先、FetchContent 兜底"策略、平台分支的链接参数组织,以及示例中桌面/Web 双主循环的写法,都是你在自己项目中可以直接复用的成熟模式。无论是快速跑通第一个窗口,还是以此为起点搭建正式的游戏工程,这份模板都是一个可靠的地基。

  • 游戏开发
  • 图形学
  • 3D渲染

【免费下载链接】raylib

A simple and easy-to-use library to enjoy videogames programming

项目地址:https://gitcode.com/GitHub_Trending/ra/raylib
点击查看免费下载

相关推荐

上一篇:PaddleSpeech MDTC 关键词唤醒(KWS)实验模块全解析:从数据整理到 DET 评测
下一篇:Sunshine游戏串流服务器:免费开源的家庭游戏共享终极指南

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/30 6:55:28

Muse 之后又来新选手?Manus 新产品 Cue 的第一轮实测

随着 Grok Bot、Muse 的推出&#xff0c;AI 圈就掀起了一股永不掉线的个人 Agent 的狂潮。 在昨天发完 Muse 的测评之后&#xff0c;我本来就想等着今天凌晨 OpenAI 的同类产品&#xff0c;结果没想到一觉起来&#xff0c;出现了一个新的黑马&#xff1a;Cue 我们都是第一次听…

作者头像 李华
网站建设 2026/9/30 6:53:49

风险篇幅接近业务两倍,Anthropic招股书在测试什么

文 | 周易编 | 沈校Anthropic公司的IPO招股说明书警告投资者&#xff0c;其自主研发的人工智能可能对人类造成“灾难性或生存性风险”&#xff0c;包括模型可能难以关闭、隐藏信息或表现出类似勒索的行为。鲜有上市公司曾发出过这样的警告&#xff1a;其核心产品可能威胁人类灭…

作者头像 李华
网站建设 2026/9/30 6:53:17

动手学深度学习:稠密连接网络(DenseNet)原理与四框架实现指南

人工智能深度学习机器学习教程 【免费下载链接】d2l-zh 《动手学深度学习》&#xff1a;面向中文读者、能运行、可讨论。中英文版被70多个国家的500多所大学用于教学。 项目地址&#xff1a; https://gitcode.com/GitHub_Trending/d2/d2l-zh 点击查看 免费下载 本篇技术指南以…

作者头像 李华