I ran into some issues getting a sample OpenGL application with GLFW working with Zig on Windows, so I figured I’d write a short post outlining what’s needed to get it working.
Download GLFW and build it from source. The pre-built windows static libraries available for download are compiled with a flag that is incompatible with the way Zig builds libraries. I discovered this by opening an issue on the Zig repo.
After you’ve cloned the source from https://github.com/glfw/glfw, build it using CMake. If you don’t know how to do that using Visual Studio, here’s what I did:
cd
to the directory where you cloned glfwmkdir build && cd build
cmake .. -DUSE_MSVC_RUNTIME_LIBRARY_DLL=OFF
GLFW.sln
in Visual Studio and build it. I set the Configuration to Release
. The static library glfw3.lib
was generated at build/src/Release/glfw3.lib
.In your build.zig
, add the GLFW includes and lib folder:
exe.addIncludeDir("/path/to/glfw/include");
exe.addLibPath("/path/to/glfw/build/src/Release");
Link against the following system libraries:
exe.linkSystemLibrary("glfw3");
exe.linkSystemLibrary("c");
exe.linkSystemLibrary("user32");
exe.linkSystemLibrary("gdi32");
exe.linkSystemLibrary("shell32");
After all these steps, linking should succeed. Here’s a complete trivial sample that also includes the OpenGL lib:
const Builder = @import("std").build.Builder;
const builtin = @import("builtin");
pub fn build(b: *Builder) void {
const mode = b.standardReleaseOptions();
const exe = b.addExecutable("main", "src/main.zig");
exe.setBuildMode(mode);
exe.addIncludeDir("/path/to/glfw/include");
exe.addLibPath("/path/to/glfw/build/src/Release");
exe.linkSystemLibrary("glfw3");
exe.linkSystemLibrary("c");
exe.linkSystemLibrary("opengl32");
exe.linkSystemLibrary("user32");
exe.linkSystemLibrary("gdi32");
exe.linkSystemLibrary("shell32");
exe.install();
const run_cmd = exe.run();
run_cmd.step.dependOn(b.getInstallStep());
const run_step = b.step("run", "Run the app");
run_step.dependOn(&run_cmd.step);
}
const c = @cImport({
@cInclude("GLFW/glfw3.h");
});
const std = @import("std");
const warn = std.debug.warn;
const panic = std.debug.panic;
var window: *c.GLFWwindow = undefined;
export fn errorCallback(err: c_int, description: [*c]const u8) void {
panic("Error: {}\n", .{description});
}
pub fn main() u8 {
_ = c.glfwSetErrorCallback(errorCallback);
if (c.glfwInit() == c.GL_FALSE) {
warn("Failed to initialize GLFW\n", .{});
return 1;
}
return 0;
}