GLFW 3.5 应用构建指南:头文件引入、选项宏与全平台链接配置详解
2026/9/14 4:52:45 网站建设 项目流程

GLFW 3.5 应用构建指南:头文件引入、选项宏与全平台链接配置详解

【免费下载链接】glfwA multi-platform library for OpenGL, OpenGL ES, Vulkan, window and input项目地址: https://gitcode.com/GitHub_Trending/gl/glfw

本篇指南聚焦于使用 GLFW 3.5 编写 OpenGL、OpenGL ES 与 Vulkan 应用时的编译与链接环节:如何正确引入GLFW/glfw3.h头文件、如何通过选项宏切换 API 头文件、以及如何在 Visual C++、MinGW-w64、CMake、pkg-config 和 Xcode 等不同开发环境中完成静态库或 DLL 的链接。读完本文,你将掌握一套可在 Windows、macOS 与 Linux 等平台上直接复用的构建配置方案。关于如何编译 GLFW 库本身,请参阅 docs/compile.md;关于如何编写 GLFW 应用,请从 docs/quick.md 的入门教程开始。

本文假定读者已具备基本的 C 程序编译与链接知识,能够使用所选开发环境的编译器。它并非编译或链接的通用教程。

引入 GLFW 头文件

在使用了 OpenGL 或 GLFW 的源文件中,应包含 GLFW 头文件:

#include <GLFW/glfw3.h>

该头文件定义了 GLFW API 的全部常量、类型和函数原型。默认情况下,它还会引入开发环境自带的 OpenGL 头文件(GL/gl.h,macOS 上为OpenGL/gl.h),具体行为见下文 GLFW 头文件选项宏。

GLFW 头文件还会按需定义 OpenGL 头文件所需的平台相关宏(如 Windows 下的APIENTRYWINGDIAPICALLBACK),从而让 OpenGL 头文件可以在不依赖任何窗口系统头文件的情况下被引入。在 include/GLFW/glfw3.h 中可以找到这些宏的定义逻辑,例如:

#if !defined(APIENTRY) #if defined(_WIN32) #define APIENTRY __stdcall #else #define APIENTRY #endif #define GLFW_APIENTRY_DEFINED #endif /* APIENTRY */

只有当需要时 GLFW 才会定义这些符号;如果窗口系统头文件已被提前引入,GLFW 不会重复定义这些符号。但反过来不成立——例如windows.h无法容忍 Win32 符号被提前定义。因此请遵循以下三条规则:

  • 使用 GLFW 头文件来可移植地引入 OpenGL 或 OpenGL ES 头文件;
  • 除非要直接使用窗口系统 API,否则不要引入窗口系统头文件
  • 如果确实需要这些头文件,请在 GLFW 头文件之前引入它们。

与扩展加载库(glad 等)搭配使用

如果使用 glad 这类 OpenGL 扩展加载库,扩展加载器的头文件应放在 GLFW 头文件之前引入:

#include <glad/gl.h> #include <GLFW/glfw3.h>

GLFW 会尝试检测是否已引入过任何 OpenGL、OpenGL ES 或扩展加载器头文件(通过识别它们各自的 include guard 宏),一旦检测到就会禁用默认 OpenGL 头文件的引入。大多数扩展加载库还会自行定义宏来禁用其下方的同类头文件。

上述两种机制都依赖扩展加载器头文件定义了某个已知宏。如果你的扩展加载库没有这样做,或者你无法确定用户会选用哪个,GLFW_INCLUDE_NONE宏可以显式阻止 GLFW 头文件引入 OpenGL 头文件,同时允许你以任意顺序引入两个头文件:

#define GLFW_INCLUDE_NONE #include <GLFW/glfw3.h> #include <glad/gl.h>

GLFW 头文件选项宏

以下宏必须在包含 GLFW 头文件之前定义,用于影响其行为。

GLFW_DLL:在 Windows 上使用 GLFW DLL 版本时必须定义,用于告知编译器 GLFW 函数定义在 DLL 中。

下列宏用于控制引入哪个 OpenGL 或 OpenGL ES API 头文件,同一时间只能定义其中一个

引入的头文件说明
(无)GL/gl.h(macOS 为OpenGL/gl.h默认的标准 OpenGL 头文件;除非 GLFW 检测到已引入过任何已知的 OpenGL、OpenGL ES 或扩展加载器头文件
GLFW_INCLUDE_GLCOREARBGL/glcorearb.h(macOS 为OpenGL/gl3.h现代核心 OpenGL 头文件
GLFW_INCLUDE_ES1GLES/gl.hOpenGL ES 1.x
GLFW_INCLUDE_ES2GLES2/gl2.hOpenGL ES 2.0
GLFW_INCLUDE_ES3GLES3/gl3.hOpenGL ES 3.0
GLFW_INCLUDE_ES31GLES3/gl31.hOpenGL ES 3.1
GLFW_INCLUDE_ES32GLES3/gl32.hOpenGL ES 3.2
GLFW_INCLUDE_NONE不引入任何 API 头文件与扩展加载库搭配使用

注意:GLFW不提供上述任何 API 头文件,它们来自你的开发环境或 OpenGL、OpenGL ES、Vulkan SDK。

以下宏控制额外API 头文件的引入,可与上述任一宏同时定义多个:

  • GLFW_INCLUDE_VULKAN:在已选定的 OpenGL/OpenGL ES 头文件之外,额外引入vulkan/vulkan.h。在 include/GLFW/glfw3.h 中可以看到它位于整个条件选择链的最前面:
    #if defined(GLFW_INCLUDE_VULKAN) #include <vulkan/vulkan.h> #endif /* Vulkan header */
  • GLFW_INCLUDE_GLEXT:在已选定的 OpenGL/OpenGL ES 头文件之后,额外引入对应的扩展头文件(例如GLES2/gl2ext.hGL/glext.h、macOS 上的OpenGL/gl3ext.h)。
  • GLFW_INCLUDE_GLU:额外引入 GLU 头文件。只应配合标准 OpenGL 头文件使用,且仅用于兼容遗留代码;GLU 已被弃用,新代码不应使用。

上述宏的完整组合逻辑可以对照 include/GLFW/glfw3.h 阅读:从GLFW_INCLUDE_ES1开始逐级#elif判断,默认分支还会检查GLFW_INCLUDE_NONE以及一系列 include guard 宏(__gl_h___gles2_gl2_h___gl_glcorearb_h_等),以决定是否引入默认 OpenGL 头文件。

重要提醒:以上任何宏都不得在编译 GLFW 库本身时被定义。如果你的构建同时包含 GLFW 源码,务必确保这些宏不会作用于 GLFW 的源文件。

链接正确的库

GLFW 本质上是各种平台特定 API 的封装层,因此需要链接大量不同的系统库。使用共享库/动态库/DLL版本时,这些链接由 GLFW 库自身完成;使用静态库版本时,你的可执行文件需要自行链接这些库。

在 Windows 和 macOS 上,系统库列表是固定的,可以直接写死在构建环境中(见下文各开发环境小节)。在 Linux 及其他 Unix 类系统上,该列表因发行版而异,但可以通过下文介绍的多种方式自动获取。

使用 Visual C++ 与 GLFW 二进制

如果使用下载的二进制压缩包,请先确认压缩包与你要构建的架构(32 位或 64 位)匹配,否则会出现链接错误;同时确保二进制与你所用 Visual C++ 版本对应。

二进制压缩包中包含两个静态库版本,因为它们必须与可执行文件其余部分的运行库(base run-time library)变体一致:

  • glfw3.lib:用于项目选项Runtime LibraryMulti-threaded DLLMulti-threaded Debug DLL时;
  • glfw3_mt.lib:用于项目选项Runtime LibraryMulti-threadedMulti-threaded Debug时。

path/to/glfw3.libpath/to/glfw3_mt.lib添加到项目的Additional Dependencies选项。如果静态库是你自己编译的,则只有一个glfw3.lib,你需要自行保证运行库变体一致。

DLL 版本名为glfw3.dll,但链接时使用glfw3dll.lib导入库,将其添加到Additional Dependencies。DLL 版本的所有依赖默认已列在其中,但使用 DLL 版本时还必须定义GLFW_DLL,可以在Preprocessor Definitions中设置,或在源码中包含 GLFW 头文件之前定义:

#define GLFW_DLL #include <GLFW/glfw3.h>

使用 MinGW-w64 与 GLFW 二进制

适用于在 Windows 上使用 MinGW-w64 从命令行或 makefile 构建程序。以下路径假定使用二进制压缩包(下载的或自己编译的)。

注意 GCC 中源文件和库的排列顺序:依赖项必须列在使用它的文件之后。依赖 GLFW 的源文件必须排在 GLFW 库之前,而 GLFW 又依赖gdi32,因此gdi32必须排在 GLFW 库之后。

使用静态库libglfw3.a

gcc -o myprog myprog.c -I path/to/glfw/include path/to/glfw/lib-mingw-w64/libglfw3.a -lgdi32

使用 DLL 版本glfw3.dll,需要链接导入库libglfw3dll.a

gcc -o myprog myprog.c -I path/to/glfw/include path/to/glfw/lib-mingw-w64/libglfw3dll.a -lgdi32

生成的程序运行时需要能找到glfw3.dll,通常将两者放在同一目录即可。使用 DLL 版本时还需定义GLFW_DLL宏,可在源码中定义(必须在包含头文件之前):

#define GLFW_DLL #include <GLFW/glfw3.h>

也可以在命令行定义:

gcc -o myprog myprog.c -D GLFW_DLL -I path/to/glfw/include path/to/glfw/lib-mingw-w64/libglfw3dll.a -lgdi32

使用 CMake 与 GLFW 源码一起构建

CMakeLists.txt中做少量修改,即可让 GLFW 源码树随你的应用一起构建。首先把 GLFW 源码树根目录加入项目,这会向项目添加glfw目标:

add_subdirectory(path/to/glfw)

然后让你的应用链接glfw目标。它会按当前配置附加 GLFW 库及其链接期依赖、GLFW 头文件的 include 目录,并在适用时附加GLFW_DLL宏:

target_link_libraries(myapp glfw)

注意glfw目标不依赖 OpenGL,因为 GLFW 在运行时才动态加载所需的 OpenGL、OpenGL ES 或 Vulkan 库。如果你的应用直接调用 OpenGL(而非使用现代的扩展加载库,参见 docs/context.md),请使用 OpenGL CMake 包:

find_package(OpenGL REQUIRED)

找到后项目会获得OpenGL::GL目标(包含库路径与 include 路径),像链接其他库一样链接它:

target_link_libraries(myapp OpenGL::GL)

从 src/CMakeLists.txt 可以看出,glfw目标的源文件包含平台无关的context.cinit.cinput.cmonitor.cplatform.cvulkan.cwindow.c以及各后端源文件;而 CMakeLists.txt 中的GLFW_BUILD_WIN32GLFW_BUILD_COCOAGLFW_BUILD_X11GLFW_BUILD_WAYLAND选项决定了具体编译哪个平台后端。

使用 CMake 与已安装的 GLFW 二进制

如果你已经构建并安装了 GLFW,则可以用find_package定位安装时生成的包与目标文件(对应模板 CMake/glfw3Config.cmake.in 和 CMake/glfw3Config.cmake.in 生成的glfw3Config.cmake):

find_package(glfw3 3.5 REQUIRED)

找到后链接glfw目标即可,它会附加 GLFW 库及其链接期依赖、头文件 include 目录,并在适用时附加GLFW_DLL宏:

target_link_libraries(myapp glfw)

与源码构建方式相同,glfw目标不依赖 OpenGL;直接调用 OpenGL 的应用请额外使用 OpenGL CMake 包:

find_package(OpenGL REQUIRED) target_link_libraries(myapp OpenGL::GL)

在 Unix 上使用 pkg-config 与 GLFW 二进制

适用于 macOS 或任何 Unix 类系统(Linux、FreeBSD、Cygwin)下从命令行或 makefile 构建。

GLFW 支持 pkg-config,其中Requires.privateLibs.private等内容由 src/CMakeLists.txt 在配置阶段生成。

使用静态库版本的典型编译链接命令:

cc $(pkg-config --cflags glfw3) -o myprog myprog.c $(pkg-config --static --libs glfw3)

使用共享库版本时省略--static标志:

cc $(pkg-config --cflags glfw3) -o myprog myprog.c $(pkg-config --libs glfw3)

也可以在不安装的情况下直接使用glfw3.pc,通过PKG_CONFIG_PATH环境变量指定其位置(构建目录位于源码树中的src子目录下):

env PKG_CONFIG_PATH=path/to/glfw/src cc $(pkg-config --cflags glfw3) -o myprog myprog.c $(pkg-config --libs glfw3)

依赖中不包含 OpenGL,因为 GLFW 在运行时才加载所需的 OpenGL、OpenGL ES 或 Vulkan 库。如果应用直接调用 OpenGL(而非使用扩展加载库,参见 docs/context.md),请额外添加glpkg-config 包:

cc $(pkg-config --cflags glfw3 gl) -o myprog myprog.c $(pkg-config --libs glfw3 gl)

在 macOS 上使用 Xcode

  • 使用动态库版本:将其添加到项目依赖中。
  • 使用静态库版本:将静态库以及Cocoa、OpenGL、IOKit、QuartzCore四个 framework 作为依赖添加到项目。它们都可以在/System/Library/Frameworks中找到。

这些 framework 与 src/CMakeLists.txt 中glfw目标在 macOS 上的链接参数(-framework Cocoa -framework IOKit -framework CoreFoundation -framework QuartzCore)保持一致。

在 macOS 上使用命令行或 makefile

在 macOS 命令行使用已安装的 GLFW 二进制时,推荐使用 pkg-config 方式,这样新增的依赖会自动包含。若仍要手动构建,需要使用-l-framework开关自行添加所需的 framework 和库。

使用动态库libglfw.3.dylib

cc -o myprog myprog.c -lglfw -framework Cocoa -framework OpenGL -framework IOKit -framework QuartzCore

使用静态库libglfw3.a时,把-lglfw替换为-lglfw3。命令行链接 framework 时不需要添加.framework扩展名。

注意:你的机器上可能还有libGL.*.dylib风格的 OpenGL 库,但那是为 X Window System 准备的,不适用于macOS 原生版本的 GLFW。

深入理解:GLFW 的链接依赖从何而来

从源码结构看,GLFW 在 src/CMakeLists.txt 中按平台累积链接依赖:

  • Windows (Win32)-lgdi32(src/CMakeLists.txt),并在构建 DLL 时通过target_compile_definitions(glfw INTERFACE GLFW_DLL)(src/CMakeLists.txt)把GLFW_DLL自动传给使用者,这解释了为何通过 CMake 使用 DLL 版本时无需手动定义该宏;
  • macOS (Cocoa):Cocoa、IOKit、CoreFoundation、QuartzCore 四个 framework(src/CMakeLists.txt);
  • Unix 类系统rt(实时库)、m(数学库)和dl(动态加载库)按需链接(src/CMakeLists.txt);
  • Wayland:依赖wayland-clientwayland-cursorwayland-eglxkbcommon(src/CMakeLists.txt);
  • X11:依赖 XRandR、Xinerama、Xkb、Xcursor、XInput、X Shape 等扩展(src/CMakeLists.txt)。

这些依赖会同时进入 pkg-config 的Libs.private(静态链接时需要)和 CMake 的链接接口,这正是前文各种链接方式中"GLFW 库自带链接期依赖"这一说法的实现基础。

与编译 GLFW 库本身的衔接

本文覆盖的是使用GLFW 时的构建配置。若需要把 GLFW 库本身编译出来,请阅读 docs/compile.md。二者衔接的关键点包括:

  • 通过 docs/compile.md 中的cmake -S . -B build生成构建文件,并用cmake --build buildmake完成编译;
  • 根 CMakeLists.txt 中的BUILD_SHARED_LIBS决定构建静态库还是共享库(默认 OFF,即静态库),GLFW_INSTALL(默认 ON)决定是否生成安装目标;
  • 安装后,CMake 包文件(glfw3Config.cmake)会安装在${CMAKE_INSTALL_LIBDIR}/cmake/glfw3glfw3.pc会安装在${CMAKE_INSTALL_LIBDIR}/pkgconfig(CMakeLists.txt),分别供前文的find_package(glfw3 3.5 REQUIRED)pkg-config glfw3使用。

把握了"库本身怎么编译"与"应用怎么链接"这两条主线,无论你的目标平台是 Windows、macOS、Linux 还是 Wayland/X11 环境,都能快速搭建出可运行、可维护的 GLFW 应用构建系统。

【免费下载链接】glfwA multi-platform library for OpenGL, OpenGL ES, Vulkan, window and input项目地址: https://gitcode.com/GitHub_Trending/gl/glfw

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

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询