10 Commits

Author SHA1 Message Date
Ray
dbc56a87da Update HISTORY.md 2026-04-23 00:18:40 +02:00
Ray
932558ca7a Update HISTORY.md 2026-04-22 13:41:27 +02:00
Ray
7495a77a79 Update CHANGELOG 2026-04-22 13:41:15 +02:00
Ray
a4680fc677 Update HISTORY.md 2026-04-19 20:03:35 +02:00
Ray
d6445b55d6 Update core_basic_window.c 2026-04-19 20:03:31 +02:00
Ray
d87bf55607 Update CHANGELOG 2026-04-19 20:03:29 +02:00
a32b53f4d6 [build.zig] Refactor (#5764)
* Add better structure for build.zig

Temporarily disabled the tests

* Cleanup build.zig a bit

* Fixed zemscripten and cleanup other platforms

* Make opengl_version selection more restritive

* Add traslateC to build; Renable examples

* Add raygui build to build.zig

* Deny glfw from android target

* Fix android platform includes

* Add Zig project example

* Add Zig project mention to README

* Set right name for web build in zig example

* Cleanup last parts of build.zig

* Add linking method for build.zig

* Fix lshcore link for glfw and rgfw build.zig

* Fix weird sdl linkage build.zig

* Add zig example to zig project

* Fix win32, mac build bugs in build.zig

* Rename argument lshcore to shcore build.zig
2026-04-19 13:57:58 +02:00
Ray
cc752037b9 Update rmodels.c 2026-04-19 13:54:39 +02:00
90e9145978 Making it similar to CheckCollisionSpheres to remove pow function (#5776) 2026-04-19 13:51:52 +02:00
9060ac7c95 Mouse delta calculation with scaling (#5779)
Added scaling from SetMouseScale to mouse GetMouseDelta
2026-04-19 13:50:15 +02:00
13 changed files with 880 additions and 381 deletions

View File

@ -17,7 +17,7 @@ KEY CHANGES:
- New File System API - New File System API
- New Text Management API - New Text Management API
- New tool: [rexm] raylib examples manager - New tool: [rexm] raylib examples manager
- Added +50 new examples to learn from - Added +70 new examples to learn from
Detailed changes: Detailed changes:
@ -115,6 +115,7 @@ Detailed changes:
[rcore][GLFW] REVIEWED: `GetGamepadButtonPressed()`, return GAMEPAD_BUTTON_*_TRIGGER_2 if pressed (#4742) by @whaleymar [rcore][GLFW] REVIEWED: `GetGamepadButtonPressed()`, return GAMEPAD_BUTTON_*_TRIGGER_2 if pressed (#4742) by @whaleymar
[rcore][GLFW] REVIEWED: Update `mappings.h` using `GenerateMappings.cmake` by @sleeptightAnsiC [rcore][GLFW] REVIEWED: Update `mappings.h` using `GenerateMappings.cmake` by @sleeptightAnsiC
[rcore][RGFW] ADDED: New backend option: `PLATFORM_WEB_RGFW` and update RGFW (#4480) by @colleagueRiley [rcore][RGFW] ADDED: New backend option: `PLATFORM_WEB_RGFW` and update RGFW (#4480) by @colleagueRiley
[rcore][RGFW] ADDED: Support for software rendering (#5773) by @CrackedPixel
[rcore][RGFW] REVIEWED: Added missing Right Control key by @M374LX [rcore][RGFW] REVIEWED: Added missing Right Control key by @M374LX
[rcore][RGFW] REVIEWED: Changed `RGFW_window_eventWait` timeout to -1 by @doggymangc [rcore][RGFW] REVIEWED: Changed `RGFW_window_eventWait` timeout to -1 by @doggymangc
[rcore][RGFW] REVIEWED: Duplicate entries removed from `keyMappingRGFW` (#5242) by @iamahuman1395 [rcore][RGFW] REVIEWED: Duplicate entries removed from `keyMappingRGFW` (#5242) by @iamahuman1395
@ -326,6 +327,7 @@ Detailed changes:
[rmodels] REVIEWED: `DrawSphereEx()`, normals support (#4926) by @karl-zylinski [rmodels] REVIEWED: `DrawSphereEx()`, normals support (#4926) by @karl-zylinski
[rmodels] REVIEWED: `ExportMesh()`, improve OBJ vertex data precision and lower memory usage (#4496) by @mikeemm [rmodels] REVIEWED: `ExportMesh()`, improve OBJ vertex data precision and lower memory usage (#4496) by @mikeemm
[rmodels] REVIEWED: `CheckCollisionSpheres()`, simplified using `Vector3DistanceSqr()` (#5695) by @Bigfoot71 [rmodels] REVIEWED: `CheckCollisionSpheres()`, simplified using `Vector3DistanceSqr()` (#5695) by @Bigfoot71
[rmodels] REVIEWED: `CheckCollisionBoxSphere()`, improved performance and consistency (#5776) by @maiconpintoabreu
[raudio] REVIEWED: Fix a glitch at the end of a sound (#5578) by @mackron [raudio] REVIEWED: Fix a glitch at the end of a sound (#5578) by @mackron
[raudio] REVIEWED: Improvements to device configuration (#5577) by @mackron [raudio] REVIEWED: Improvements to device configuration (#5577) by @mackron
[raudio] REVIEWED: Initialize sound alias properties as if it was a new sound (#5123) by @JeffM2501 [raudio] REVIEWED: Initialize sound alias properties as if it was a new sound (#5123) by @JeffM2501
@ -410,11 +412,12 @@ Detailed changes:
[build][CMake] REVIEWED: Set `libm` as public so it can be linked by consumer (#5193) by @brccabral [build][CMake] REVIEWED: Set `libm` as public so it can be linked by consumer (#5193) by @brccabral
[build][Cmake] REVIEWED: Expose PLATFORM_WEB_RGFW (#5579) by @crisserpl2 [build][Cmake] REVIEWED: Expose PLATFORM_WEB_RGFW (#5579) by @crisserpl2
[build][Zig] ADDED: Android target to build by @lumenkeyes [build][Zig] ADDED: Android target to build by @lumenkeyes
[build][Zig] REDESIGNED: Complete refactor of build.zig to support Zig 0.16.0 (#5764) by @HaxSam
[build][Zig] REVIEWED: Link EGL for Android by @lumenkeyes [build][Zig] REVIEWED: Link EGL for Android by @lumenkeyes
[build][Zig] REVIEWED: Approach to build for web with zig-build (#5157) by @haxsam [build][Zig] REVIEWED: Approach to build for web with zig-build (#5157) by @haxsam
[build][Zig] REVIEWED: Fix build accessing env vars (#5490) by @iisakki [build][Zig] REVIEWED: Fix build accessing env vars (#5490) by @iisakki
[build][Zig] REVIEWED: Fix emscripten building by @johnnymarler [build][Zig] REVIEWED: Fix emscripten building by @johnnymarler
[build][Zig] REVIWED: Move examples/build.zig into main build.zig by @johnnymarler [build][Zig] REVIEWED: Move examples/build.zig into main build.zig by @johnnymarler
[build][Zig] REVIEWED: Fix raygui inclusion in windows crosscompilation (#4489) by @kimierik [build][Zig] REVIEWED: Fix raygui inclusion in windows crosscompilation (#4489) by @kimierik
[build][Zig] REVIEWED: Issue on emscripten run if the user has not installed emsdk by @emilhakimov415 [build][Zig] REVIEWED: Issue on emscripten run if the user has not installed emsdk by @emilhakimov415
[build][Zig] REVIEWED: Make X11 the default display backend instead of choosing at runtime (#5168) by @Not-Nik [build][Zig] REVIEWED: Make X11 the default display backend instead of choosing at runtime (#5168) by @Not-Nik
@ -462,6 +465,7 @@ Detailed changes:
[examples] ADDED: `shapes_rlgl_triangle` example (#5353) by @robinsaviary [examples] ADDED: `shapes_rlgl_triangle` example (#5353) by @robinsaviary
[examples] ADDED: `shapes_starfield` (#5255) by @themushroompirates [examples] ADDED: `shapes_starfield` (#5255) by @themushroompirates
[examples] ADDED: `shapes_triangle_strip` (#5240) by @Jopestpe [examples] ADDED: `shapes_triangle_strip` (#5240) by @Jopestpe
[examples] ADDED: `shapes_collision_ellipses` (#5722) by @Monjaris
[examples] ADDED: `text_inline_styling` by @raysan5 [examples] ADDED: `text_inline_styling` by @raysan5
[examples] ADDED: `text_strings_management` (#5379) by @davidbuzatto [examples] ADDED: `text_strings_management` (#5379) by @davidbuzatto
[examples] ADDED: `text_words_alignment` (#5254) by @themushroompirates [examples] ADDED: `text_words_alignment` (#5254) by @themushroompirates

View File

@ -530,10 +530,10 @@ A new `raylib` release is finally ready and, again, this is the **biggest `rayli
Some astonishing numbers for this release: Some astonishing numbers for this release:
- **+320** closed issues (for a TOTAL of **+2140**!) - **+330** closed issues (for a TOTAL of **+2150**!)
- **+1950** commits since previous RELEASE (for a TOTAL of **+9700**!) - **+2000** commits since previous RELEASE (for a TOTAL of **+9760**!)
- **+20** new functions ADDED to raylib API (for a TOTAL of **600**!) - **+20** new functions ADDED to raylib API (for a TOTAL of **600**!)
- **+50** new examples to learn from (for a TOTAL of **+210**!) - **+70** new examples to learn from (for a TOTAL of **+215**!)
- **+210** new contributors (for a TOTAL of **+850**!) - **+210** new contributors (for a TOTAL of **+850**!)
Highlights for `raylib 6.0`: Highlights for `raylib 6.0`:
@ -591,14 +591,14 @@ COMMANDS:
update : Validate and update examples collection, generates report update : Validate and update examples collection, generates report
``` ```
- **`NEW` +50 new examples**: Thanks to `rexm` and the simplification on examples management, this new raylib release includes +50 new examples to leearn from, most of them contributed by community. - **`NEW` +70 new examples**: Thanks to `rexm` and the simplification on examples management, this new raylib release includes +70 new examples to learn from, most of them contributed by community. Multiple examples have also been renamed for consistency and all examples header and structure have been reviewed and unified.
Make sure to check raylib [CHANGELOG](https://github.com/raysan5/raylib/blob/master/CHANGELOG) for a detailed list of changes! Make sure to check raylib [CHANGELOG](https://github.com/raysan5/raylib/blob/master/CHANGELOG) for a detailed list of changes!
I want to **thank all the contributors (+850!**) that along the years have **greatly improved raylib** and pushed it further and better day after day. And **many thanks to raylib community and all raylib users** for supporting the library along those many years. I want to **thank all the contributors (+850!**) that along the years have **greatly improved raylib** and pushed it further and better day after day. And **many thanks to raylib community and all raylib users** for supporting the library along those many years.
Finally, I want to thank [puffer.ai](https://puffer.ai/) and [comma.ai](https://comma.ai/) for **supporting and sponsoring the project** as platinum sponsors, along many others individuals that have been sponsoring raylib along the years. Thanks to all of you for allowing me to keep working on this library! Finally, I want to thank [puffer.ai](https://puffer.ai/) and [comma.ai](https://comma.ai/) for **using raylib and supporting the project** as platinum sponsors, along many others individuals that have been sponsoring raylib along the years. Thanks to all of you for allowing me to keep working on this library!
**After +12 years of development, `raylib 6.0` is today one of the bests libraries to enjoy games/tools/graphic programming!** **After +12 years of development, `raylib 6.0` is today one of the bests libraries to enjoy games/tools/graphics programming!**
**Enjoy graphics programming with raylib!** :) **Enjoy graphics programming with raylib!** :)

772
build.zig
View File

@ -1,14 +1,11 @@
const std = @import("std"); const std = @import("std");
const builtin = @import("builtin"); const builtin = @import("builtin");
const emccOutputDir = "zig-out" ++ std.fs.path.sep_str ++ "htmlout" ++ std.fs.path.sep_str;
const emccOutputFile = "index.html";
pub const emsdk = struct { pub const emsdk = struct {
const zemscripten = @import("zemscripten"); const zemscripten = @import("zemscripten");
pub fn shell(b: *std.Build) std.Build.LazyPath { pub fn shell(raylib_dep: *std.Build.Dependency) std.Build.LazyPath {
return b.dependency("raylib", .{}).path("src/shell.html"); return raylib_dep.path("src/shell.html");
} }
pub const FlagsOptions = struct { pub const FlagsOptions = struct {
@ -30,7 +27,10 @@ pub const emsdk = struct {
pub const SettingsOptions = struct { pub const SettingsOptions = struct {
optimize: std.builtin.OptimizeMode, optimize: std.builtin.OptimizeMode,
es3: bool = true, es3: bool = false,
glfw3: bool = true,
memory_growth: bool = false,
total_memory: u32 = 134217728,
emsdk_allocator: zemscripten.EmsdkAllocator = .emmalloc, emsdk_allocator: zemscripten.EmsdkAllocator = .emmalloc,
}; };
@ -40,10 +40,24 @@ pub const emsdk = struct {
.emsdk_allocator = options.emsdk_allocator, .emsdk_allocator = options.emsdk_allocator,
}); });
if (options.es3) if (options.es3) {
emcc_settings.put("FULL_ES3", "1") catch unreachable; emcc_settings.put("FULL_ES3", "1") catch unreachable;
emcc_settings.put("MIN_WEBGL_VERSION", "2") catch unreachable;
emcc_settings.put("MAX_WEBGL_VERSION", "2") catch unreachable;
}
if (options.glfw3) {
emcc_settings.put("USE_GLFW", "3") catch unreachable; emcc_settings.put("USE_GLFW", "3") catch unreachable;
}
const total_memory = std.fmt.allocPrint(allocator, "{d}", .{options.total_memory}) catch unreachable;
emcc_settings.put("EXPORTED_RUNTIME_METHODS", "['requestFullscreen']") catch unreachable; emcc_settings.put("EXPORTED_RUNTIME_METHODS", "['requestFullscreen']") catch unreachable;
emcc_settings.put("TOTAL_MEMORY", total_memory) catch unreachable;
emcc_settings.put("FORCE_FILESYSTEM", "1") catch unreachable;
emcc_settings.put("EXPORTED_RUNTIME_METHODS", "ccall") catch unreachable;
if (options.memory_growth)
emcc_settings.put("ALLOW_MEMORY_GROWTH", "1") catch unreachable;
return emcc_settings; return emcc_settings;
} }
@ -70,45 +84,96 @@ pub const emsdk = struct {
} }
}; };
fn setDesktopPlatform(raylib: *std.Build.Step.Compile, platform: PlatformBackend) void { pub fn linkWindows(mod: *std.Build.Module, opengl: bool, comptime shcore: bool) void {
switch (platform) { if (opengl) mod.linkSystemLibrary("opengl32", .{});
.glfw => raylib.root_module.addCMacro("PLATFORM_DESKTOP_GLFW", ""), mod.linkSystemLibrary("winmm", .{});
.rgfw => raylib.root_module.addCMacro("PLATFORM_DESKTOP_RGFW", ""), mod.linkSystemLibrary("gdi32", .{});
.sdl => raylib.root_module.addCMacro("PLATFORM_DESKTOP_SDL", ""), if (shcore) mod.linkSystemLibrary("shcore", .{});
.android => raylib.root_module.addCMacro("PLATFORM_ANDROID", ""), }
else => {},
fn findWaylandScanner(b: *std.Build) void {
_ = b.findProgram(&.{"wayland-scanner"}, &.{}) catch {
std.log.err(
\\ `wayland-scanner` may not be installed on the system.
\\ You can switch to X11 in your `build.zig` by changing `Options.linux_display_backend`
, .{});
@panic("`wayland-scanner` not found");
};
}
pub fn linkLinux(mod: *std.Build.Module, comptime display_backend: LinuxDisplayBackend) void {
if (display_backend == .None) {
mod.linkSystemLibrary("GL", .{});
}
if (display_backend == .X11) {
mod.linkSystemLibrary("X11", .{});
mod.linkSystemLibrary("Xrandr", .{});
mod.linkSystemLibrary("Xinerama", .{});
mod.linkSystemLibrary("Xi", .{});
mod.linkSystemLibrary("Xcursor", .{});
}
if (display_backend == .Wayland) {
mod.linkSystemLibrary("wayland-client", .{});
mod.linkSystemLibrary("wayland-cursor", .{});
mod.linkSystemLibrary("wayland-egl", .{});
mod.linkSystemLibrary("xkbcommon", .{});
} }
} }
pub fn linkBSD(_: *std.Build, mod: *std.Build.Module) void {
mod.linkSystemLibrary("GL", .{});
}
pub fn linkMacOS(b: *std.Build, mod: *std.Build.Module) void {
// Include xcode_frameworks for cross compilation
if (b.lazyDependency("xcode_frameworks", .{})) |dep| {
mod.addSystemFrameworkPath(dep.path("Frameworks"));
mod.addSystemIncludePath(dep.path("include"));
mod.addLibraryPath(dep.path("lib"));
}
mod.linkFramework("Foundation", .{});
mod.linkFramework("CoreServices", .{});
mod.linkFramework("CoreGraphics", .{});
mod.linkFramework("AppKit", .{});
mod.linkFramework("IOKit", .{});
}
fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode, options: Options) !*std.Build.Step.Compile { fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode, options: Options) !*std.Build.Step.Compile {
const raylib = b.addLibrary(.{ const raylib_mod = b.createModule(.{
.name = "raylib",
.linkage = options.linkage,
.root_module = b.createModule(.{
.optimize = optimize, .optimize = optimize,
.target = target, .target = target,
.link_libc = true, .link_libc = true,
}),
}); });
raylib.root_module.addCMacro("_GNU_SOURCE", ""); const raylib = b.addLibrary(.{
raylib.root_module.addCMacro("GL_SILENCE_DEPRECATION", "199309L"); .name = "raylib",
.linkage = options.linkage,
.root_module = raylib_mod,
});
var raylib_flags_arr: std.ArrayList([]const u8) = .empty; raylib_mod.addCMacro("_GNU_SOURCE", "");
defer raylib_flags_arr.deinit(b.allocator); raylib_mod.addCMacro("GL_SILENCE_DEPRECATION", "199309L");
try raylib_flags_arr.append( var arena: std.heap.ArenaAllocator = .init(b.allocator);
b.allocator, defer arena.deinit();
"-std=gnu99",
); var raylib_flags_arr: std.array_list.Managed([]const u8) = .init(arena.allocator());
var c_source_files: std.array_list.Managed([]const u8) = .init(arena.allocator());
try c_source_files.append("src/rcore.c");
if (target.result.os.tag == .emscripten) {
try raylib_flags_arr.append("-std=gnu99");
} else {
try raylib_flags_arr.append("-std=c99");
}
if (options.linkage == .dynamic) { if (options.linkage == .dynamic) {
try raylib_flags_arr.append( raylib_mod.pic = true;
b.allocator, raylib_mod.addCMacro("BUILD_LIBTYPE_SHARED", "");
"-fPIC",
);
raylib.root_module.addCMacro("BUILD_LIBTYPE_SHARED", "");
} }
if (options.config.len > 0) { if (options.config.len > 0) {
@ -120,88 +185,237 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.
// Apply config flags supplied by the user // Apply config flags supplied by the user
while (config_iter.next()) |config_flag| { while (config_iter.next()) |config_flag| {
try raylib_flags_arr.append(b.allocator, config_flag); try raylib_flags_arr.append(config_flag);
} }
} }
// No GLFW required on PLATFORM_DRM raylib_mod.addCMacro("SUPPORT_MODULE_RSHAPES", &.{@as(u8, @intFromBool(options.rshapes)) + 0x30});
if (options.platform != .drm) {
raylib.root_module.addIncludePath(b.path("src/external/glfw/include"));
}
var c_source_files: std.ArrayList([]const u8) = try .initCapacity(b.allocator, 2);
c_source_files.appendSliceAssumeCapacity(&.{"src/rcore.c"});
if (options.rshapes) { if (options.rshapes) {
raylib.root_module.addCMacro("SUPPORT_MODULE_RSHAPES", "1"); try c_source_files.append("src/rshapes.c");
try c_source_files.append(b.allocator, "src/rshapes.c");
} else {
raylib.root_module.addCMacro("SUPPORT_MODULE_RSHAPES", "0");
} }
raylib_mod.addCMacro("SUPPORT_MODULE_RTEXTURES", &.{@as(u8, @intFromBool(options.rtextures)) + 0x30});
if (options.rtextures) { if (options.rtextures) {
raylib.root_module.addCMacro("SUPPORT_MODULE_RTEXTURES", "1"); try c_source_files.append("src/rtextures.c");
try c_source_files.append(b.allocator, "src/rtextures.c");
} else {
raylib.root_module.addCMacro("SUPPORT_MODULE_RTEXTURES", "0");
} }
raylib_mod.addCMacro("SUPPORT_MODULE_RTEXT", &.{@as(u8, @intFromBool(options.rtext)) + 0x30});
if (options.rtext) { if (options.rtext) {
raylib.root_module.addCMacro("SUPPORT_MODULE_RTEXT", "1"); try c_source_files.append("src/rtext.c");
try c_source_files.append(b.allocator, "src/rtext.c");
} else {
raylib.root_module.addCMacro("SUPPORT_MODULE_RTEXT", "0");
} }
raylib_mod.addCMacro("SUPPORT_MODULE_RMODELS", &.{@as(u8, @intFromBool(options.rmodels)) + 0x30});
if (options.rmodels) { if (options.rmodels) {
raylib.root_module.addCMacro("SUPPORT_MODULE_RMODELS", "1"); try c_source_files.append("src/rmodels.c");
try c_source_files.append(b.allocator, "src/rmodels.c");
} else {
raylib.root_module.addCMacro("SUPPORT_MODULE_RMODELS", "0");
} }
raylib_mod.addCMacro("SUPPORT_MODULE_RAUDIO", &.{@as(u8, @intFromBool(options.raudio)) + 0x30});
if (options.raudio) { if (options.raudio) {
raylib.root_module.addCMacro("SUPPORT_MODULE_RAUDIO", "1"); try c_source_files.append("src/raudio.c");
try c_source_files.append(b.allocator, "src/raudio.c");
} else {
raylib.root_module.addCMacro("SUPPORT_MODULE_RAUDIO", "0");
} }
if (options.opengl_version != .auto) { raylib_mod.addIncludePath(b.path("src/platforms"));
raylib.root_module.addCMacro(options.opengl_version.toCMacroStr(), "");
}
raylib.root_module.addIncludePath(b.path("src/platforms"));
switch (target.result.os.tag) {
.windows => {
switch (options.platform) { switch (options.platform) {
.glfw => try c_source_files.append(b.allocator, "src/rglfw.c"), .glfw => {
.rgfw, .sdl, .drm, .android => {}, var opengl_version: OpenglVersion = options.opengl_version;
if (opengl_version == .gl_soft) {
@panic("The opengl version is not supported by this platform");
} }
raylib.root_module.linkSystemLibrary("winmm", .{}); raylib_mod.addIncludePath(b.path("src/external/glfw/include"));
raylib.root_module.linkSystemLibrary("gdi32", .{});
raylib.root_module.linkSystemLibrary("opengl32", .{});
setDesktopPlatform(raylib, options.platform); if (target.result.os.tag != .emscripten) {
}, if (opengl_version == .auto) {
opengl_version = OpenglVersion.gl_3_3;
}
raylib_mod.addCMacro("PLATFORM_DESKTOP_GLFW", "");
try c_source_files.append("src/rglfw.c");
}
switch (target.result.os.tag) {
.windows => linkWindows(raylib_mod, true, false),
.linux => { .linux => {
if (options.platform == .drm) { if (target.result.abi.isAndroid()) {
@panic("Target is not supported with this platform");
}
linkLinux(raylib_mod, .None);
if (options.linux_display_backend == .X11 or options.linux_display_backend == .Both) {
raylib_mod.addCMacro("_GLFW_X11", "");
linkLinux(raylib_mod, .X11);
}
if (options.linux_display_backend == .Wayland or options.linux_display_backend == .Both) {
findWaylandScanner(b);
raylib_mod.addCMacro("_GLFW_WAYLAND", "");
linkLinux(raylib_mod, .Wayland);
try waylandGenerate(b, raylib, "src/external/glfw/deps/wayland/", false);
}
},
.freebsd, .openbsd, .netbsd, .dragonfly => linkBSD(b, raylib_mod),
.macos => {
// On macos rglfw.c include Objective-C files.
_ = c_source_files.pop();
try raylib_flags_arr.append("-ObjC");
raylib_mod.addCSourceFile(.{
.file = b.path("src/rglfw.c"),
.flags = raylib_flags_arr.items,
});
_ = raylib_flags_arr.pop();
linkMacOS(b, raylib_mod);
},
.emscripten => {
switch (opengl_version) {
.auto => opengl_version = OpenglVersion.gles_2,
.gles_2, .gles_3, .gl_soft => {},
else => @panic("opengl version not supported"),
}
raylib_mod.addCMacro("PLATFORM_WEB", "");
const activate_emsdk_step = emsdk.zemscripten.activateEmsdkStep(b);
raylib.step.dependOn(activate_emsdk_step);
},
else => @panic("Target is not supported with this platform"),
}
raylib_mod.addCMacro(opengl_version.toCMacroStr(), "");
},
.rgfw => {
var opengl_version: OpenglVersion = options.opengl_version;
if (target.result.os.tag != .emscripten) {
if (opengl_version == .auto) {
opengl_version = OpenglVersion.gl_3_3;
}
raylib_mod.addCMacro("PLATFORM_DESKTOP_RGFW", "");
}
switch (target.result.os.tag) {
.windows => linkWindows(raylib_mod, true, false),
.linux => {
if (target.result.abi.isAndroid()) {
@panic("Target is not supported with this platform");
}
linkLinux(raylib_mod, .None);
if (options.linux_display_backend == .X11 or options.linux_display_backend == .Both) {
raylib_mod.addCMacro("RGFW_X11", "");
raylib_mod.addCMacro("RGFW_UNIX", "");
linkLinux(raylib_mod, .X11);
}
if (options.linux_display_backend == .Wayland or options.linux_display_backend == .Both) {
findWaylandScanner(b);
if (options.linux_display_backend != .Both) {
raylib_mod.addCMacro("RGFW_NO_X11", "");
}
raylib_mod.addCMacro("RGFW_WAYLAND", "");
raylib_mod.addCMacro("EGLAPIENTRY", "");
linkLinux(raylib_mod, .Wayland);
try waylandGenerate(b, raylib, "src/external/RGFW/deps/wayland/", true);
}
},
.freebsd, .openbsd, .netbsd, .dragonfly => linkBSD(b, raylib_mod),
.macos => linkMacOS(b, raylib_mod),
.emscripten => {
switch (opengl_version) {
.auto => opengl_version = OpenglVersion.gles_2,
.gles_2, .gles_3, .gl_soft => {},
else => @panic("opengl version not supported"),
}
raylib_mod.addCMacro("PLATFORM_WEB_RGFW", "");
const activate_emsdk_step = emsdk.zemscripten.activateEmsdkStep(b);
raylib.step.dependOn(activate_emsdk_step);
},
else => @panic("Target is not supported with this platform"),
}
raylib_mod.addCMacro(opengl_version.toCMacroStr(), "");
},
.sdl, .sdl2, .sdl3 => {
if (options.opengl_version == .auto) { if (options.opengl_version == .auto) {
raylib.root_module.linkSystemLibrary("GLESv2", .{}); raylib_mod.addCMacro(OpenglVersion.gl_3_3.toCMacroStr(), "");
raylib.root_module.addCMacro("GRAPHICS_API_OPENGL_ES2", ""); } else {
raylib_mod.addCMacro(options.opengl_version.toCMacroStr(), "");
} }
if (options.opengl_version != .gl_soft) { raylib_mod.addCMacro("PLATFORM_DESKTOP_SDL", "");
raylib.root_module.linkSystemLibrary("EGL", .{});
raylib.root_module.linkSystemLibrary("gbm", .{});
}
raylib.root_module.linkSystemLibrary("libdrm", .{ .use_pkg_config = .force });
raylib.root_module.addCMacro("PLATFORM_DRM", ""); if (options.platform == .sdl2) {
raylib.root_module.addCMacro("EGL_NO_X11", ""); raylib_mod.addCMacro("USING_SDL2_PACKAGE", "");
raylib.root_module.addCMacro("DEFAULT_BATCH_BUFFER_ELEMENT", ""); }
} else if (target.result.abi.isAndroid()) { if (options.platform == .sdl3) {
raylib_mod.addCMacro("USING_SDL3_PACKAGE", "");
}
},
.memory => {
if (options.opengl_version != .auto and options.opengl_version != .gl_soft) {
@panic("The opengl version is not supported by this platform");
}
raylib_mod.addCMacro(OpenglVersion.gl_soft.toCMacroStr(), "");
raylib_mod.addCMacro("PLATFORM_MEMORY", "");
},
.win32 => {
if (target.result.os.tag != .windows) {
@panic("Target is not supported with this platform");
}
if (options.opengl_version == .auto) {
raylib_mod.addCMacro(OpenglVersion.gl_3_3.toCMacroStr(), "");
} else {
raylib_mod.addCMacro(options.opengl_version.toCMacroStr(), "");
}
raylib_mod.addCMacro("PLATFORM_DESKTOP_WIN32", "");
linkWindows(raylib_mod, options.opengl_version != .gl_soft, true);
},
.drm => {
if (target.result.os.tag != .linux) {
@panic("Target is not supported with this platform");
}
raylib_mod.addCMacro("PLATFORM_DRM", "");
raylib_mod.addCMacro("EGL_NO_X11", "");
raylib_mod.addCMacro("DEFAULT_BATCH_BUFFER_ELEMENT", "");
try raylib_flags_arr.append("-Werror=implicit-function-declaration");
raylib_mod.linkSystemLibrary("libdrm", .{ .use_pkg_config = .force });
raylib_mod.linkSystemLibrary("drm", .{});
raylib_mod.linkSystemLibrary("gbm", .{});
switch (options.opengl_version) {
.auto, .gles_2 => {
raylib_mod.addCMacro(OpenglVersion.gles_2.toCMacroStr(), "");
raylib_mod.linkSystemLibrary("GLESv2", .{});
raylib_mod.linkSystemLibrary("EGL", .{});
},
.gl_soft => {},
else => @panic("The opengl version is not supported by this platform"),
}
},
.android => {
if (!target.result.abi.isAndroid()) {
@panic("Target is not supported with this platform");
}
raylib_mod.addCMacro("PLATFORM_ANDROID", "");
raylib_mod.linkSystemLibrary("EGL", .{});
switch (options.opengl_version) {
.auto, .gles_2 => {
raylib_mod.addCMacro(OpenglVersion.gles_2.toCMacroStr(), "");
raylib_mod.linkSystemLibrary("GLESv2", .{});
},
else => @panic("The opengl version is not supported by this platform"),
}
//these are the only tag options per https://developer.android.com/ndk/guides/other_build_systems //these are the only tag options per https://developer.android.com/ndk/guides/other_build_systems
const hostTuple = switch (builtin.target.os.tag) { const hostTuple = switch (builtin.target.os.tag) {
@ -231,126 +445,30 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.
const androidAsmPath = try std.fs.path.join(b.allocator, &.{ androidIncludePath, "/asm-generic" }); const androidAsmPath = try std.fs.path.join(b.allocator, &.{ androidIncludePath, "/asm-generic" });
const androidGluePath = try std.fs.path.join(b.allocator, &.{ androidNdkPathString, "/sources/android/native_app_glue/" }); const androidGluePath = try std.fs.path.join(b.allocator, &.{ androidNdkPathString, "/sources/android/native_app_glue/" });
raylib.root_module.addLibraryPath(.{ .cwd_relative = androidLibPath }); raylib_mod.addLibraryPath(.{ .cwd_relative = androidLibPath });
raylib.root_module.addLibraryPath(.{ .cwd_relative = androidApiSpecificPath }); raylib_mod.addLibraryPath(.{ .cwd_relative = androidApiSpecificPath });
raylib.root_module.addSystemIncludePath(.{ .cwd_relative = androidIncludePath }); raylib_mod.addSystemIncludePath(.{ .cwd_relative = androidIncludePath });
raylib.root_module.addSystemIncludePath(.{ .cwd_relative = androidArchIncludePath }); raylib_mod.addSystemIncludePath(.{ .cwd_relative = androidArchIncludePath });
raylib.root_module.addSystemIncludePath(.{ .cwd_relative = androidAsmPath }); raylib_mod.addSystemIncludePath(.{ .cwd_relative = androidAsmPath });
raylib.root_module.addSystemIncludePath(.{ .cwd_relative = androidGluePath }); raylib_mod.addSystemIncludePath(.{ .cwd_relative = androidGluePath });
var libcData: std.ArrayList(u8) = .empty; const libc_data = try std.fmt.allocPrint(b.allocator,
var aw: std.Io.Writer.Allocating = .fromArrayList(b.allocator, &libcData); \\include_dir={0s}/sysroot/usr/include
try (std.zig.LibCInstallation{ \\sys_include_dir={0s}/sysroot/usr/include/aarch64-linux-android
.include_dir = androidIncludePath, \\crt_dir={0s}/sysroot/usr/lib/aarch64-linux-android/24
.sys_include_dir = androidIncludePath, \\static_lib_dir={0s}/sysroot/usr/lib/aarch64-linux-android/24
.crt_dir = androidApiSpecificPath, \\msvc_lib_dir=
}).render(&aw.writer); \\kernel32_lib_dir=
const libcFile = b.addWriteFiles().add("android-libc.txt", try libcData.toOwnedSlice(b.allocator)); \\gcc_dir=
\\
, .{androidNdkPathString});
const write_step = b.addWriteFiles();
const libcFile = write_step.add("android-libc.txt", libc_data);
raylib.setLibCFile(libcFile); raylib.setLibCFile(libcFile);
if (options.opengl_version == .auto) {
raylib.root_module.linkSystemLibrary("GLESv2", .{});
raylib.root_module.addCMacro("GRAPHICS_API_OPENGL_ES2", "");
}
raylib.root_module.linkSystemLibrary("EGL", .{});
setDesktopPlatform(raylib, .android);
} else {
switch (options.platform) {
.glfw => try c_source_files.append(b.allocator, "src/rglfw.c"),
.rgfw, .sdl, .drm, .android => {},
}
if (options.linux_display_backend == .X11 or options.linux_display_backend == .Both) {
raylib.root_module.addCMacro("_GLFW_X11", "");
raylib.root_module.linkSystemLibrary("GLX", .{});
raylib.root_module.linkSystemLibrary("X11", .{});
raylib.root_module.linkSystemLibrary("Xcursor", .{});
raylib.root_module.linkSystemLibrary("Xext", .{});
raylib.root_module.linkSystemLibrary("Xfixes", .{});
raylib.root_module.linkSystemLibrary("Xi", .{});
raylib.root_module.linkSystemLibrary("Xinerama", .{});
raylib.root_module.linkSystemLibrary("Xrandr", .{});
raylib.root_module.linkSystemLibrary("Xrender", .{});
}
if (options.linux_display_backend == .Wayland or options.linux_display_backend == .Both) {
_ = b.findProgram(&.{"wayland-scanner"}, &.{}) catch {
std.log.err(
\\ `wayland-scanner` may not be installed on the system.
\\ You can switch to X11 in your `build.zig` by changing `Options.linux_display_backend`
, .{});
@panic("`wayland-scanner` not found");
};
raylib.root_module.addCMacro("_GLFW_WAYLAND", "");
raylib.root_module.linkSystemLibrary("EGL", .{});
raylib.root_module.linkSystemLibrary("wayland-client", .{});
raylib.root_module.linkSystemLibrary("xkbcommon", .{});
waylandGenerate(b, raylib, "wayland.xml", "wayland-client-protocol");
waylandGenerate(b, raylib, "xdg-shell.xml", "xdg-shell-client-protocol");
waylandGenerate(b, raylib, "xdg-decoration-unstable-v1.xml", "xdg-decoration-unstable-v1-client-protocol");
waylandGenerate(b, raylib, "viewporter.xml", "viewporter-client-protocol");
waylandGenerate(b, raylib, "relative-pointer-unstable-v1.xml", "relative-pointer-unstable-v1-client-protocol");
waylandGenerate(b, raylib, "pointer-constraints-unstable-v1.xml", "pointer-constraints-unstable-v1-client-protocol");
waylandGenerate(b, raylib, "fractional-scale-v1.xml", "fractional-scale-v1-client-protocol");
waylandGenerate(b, raylib, "xdg-activation-v1.xml", "xdg-activation-v1-client-protocol");
waylandGenerate(b, raylib, "idle-inhibit-unstable-v1.xml", "idle-inhibit-unstable-v1-client-protocol");
}
setDesktopPlatform(raylib, options.platform);
}
},
.freebsd, .openbsd, .netbsd, .dragonfly => {
try c_source_files.append(b.allocator, "src/rglfw.c");
raylib.root_module.linkSystemLibrary("GL", .{});
raylib.root_module.linkSystemLibrary("rt", .{});
raylib.root_module.linkSystemLibrary("dl", .{});
raylib.root_module.linkSystemLibrary("m", .{});
raylib.root_module.linkSystemLibrary("X11", .{});
raylib.root_module.linkSystemLibrary("Xrandr", .{});
raylib.root_module.linkSystemLibrary("Xinerama", .{});
raylib.root_module.linkSystemLibrary("Xi", .{});
raylib.root_module.linkSystemLibrary("Xxf86vm", .{});
raylib.root_module.linkSystemLibrary("Xcursor", .{});
setDesktopPlatform(raylib, options.platform);
},
.macos => {
// Include xcode_frameworks for cross compilation
if (b.lazyDependency("xcode_frameworks", .{})) |dep| {
raylib.root_module.addSystemFrameworkPath(dep.path("Frameworks"));
raylib.root_module.addSystemIncludePath(dep.path("include"));
raylib.root_module.addLibraryPath(dep.path("lib"));
}
// On macos rglfw.c include Objective-C files.
try raylib_flags_arr.append(b.allocator, "-ObjC");
raylib.root_module.addCSourceFile(.{
.file = b.path("src/rglfw.c"),
.flags = raylib_flags_arr.items,
});
_ = raylib_flags_arr.pop();
raylib.root_module.linkFramework("Foundation", .{});
raylib.root_module.linkFramework("CoreServices", .{});
raylib.root_module.linkFramework("CoreGraphics", .{});
raylib.root_module.linkFramework("AppKit", .{});
raylib.root_module.linkFramework("IOKit", .{});
setDesktopPlatform(raylib, options.platform);
},
.emscripten => {
const activate_emsdk_step = emsdk.zemscripten.activateEmsdkStep(b);
raylib.step.dependOn(activate_emsdk_step);
raylib.root_module.addCMacro("PLATFORM_WEB", "");
if (options.opengl_version == .auto) {
raylib.root_module.addCMacro("GRAPHICS_API_OPENGL_ES3", "");
}
},
else => {
@panic("Unsupported OS");
}, },
} }
raylib.root_module.addCSourceFiles(.{ raylib_mod.addCSourceFiles(.{
.files = c_source_files.items, .files = c_source_files.items,
.flags = raylib_flags_arr.items, .flags = raylib_flags_arr.items,
}); });
@ -358,17 +476,33 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.
return raylib; return raylib;
} }
pub fn addRaygui(b: *std.Build, raylib: *std.Build.Step.Compile, raygui_dep: *std.Build.Dependency, options: Options) void { fn addRaygui(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode, raylib: *std.Build.Step.Compile) void {
const raylib_dep = b.dependencyFromBuildZig(@This(), options); if (b.lazyDependency("raygui", .{
.target = target,
.optimize = optimize,
.link_libc = true,
})) |raygui_dep| {
var gen_step = b.addWriteFiles(); var gen_step = b.addWriteFiles();
raylib.step.dependOn(&gen_step.step); raylib.step.dependOn(&gen_step.step);
const raygui_c_path = gen_step.add("raygui.c", "#define RAYGUI_IMPLEMENTATION\n#include \"raygui.h\"\n"); const raygui_c_path = gen_step.add("raygui.c", "#define RAYGUI_IMPLEMENTATION\n#include \"raygui.h\"\n");
raylib.root_module.addCSourceFile(.{ .file = raygui_c_path }); raylib.root_module.addCSourceFile(.{ .file = raygui_c_path });
raylib.root_module.addIncludePath(raygui_dep.path("src")); raylib.root_module.addIncludePath(raygui_dep.path("src"));
raylib.root_module.addIncludePath(raylib_dep.path("src")); raylib.root_module.addIncludePath(b.path("src"));
raylib.installHeader(raygui_dep.path("src/raygui.h"), "raygui.h"); raylib.installHeader(raygui_dep.path("src/raygui.h"), "raygui.h");
const c = b.addTranslateC(.{
.root_source_file = raygui_dep.path("src/raygui.h"),
.target = target,
.optimize = optimize,
.link_libc = true,
});
c.addIncludePath(b.path("src"));
const c_mod = c.createModule();
c_mod.linkLibrary(raylib);
b.modules.put(b.graph.arena, "raygui", c_mod) catch @panic("OOM");
}
} }
pub const Options = struct { pub const Options = struct {
@ -377,6 +511,7 @@ pub const Options = struct {
rshapes: bool = true, rshapes: bool = true,
rtext: bool = true, rtext: bool = true,
rtextures: bool = true, rtextures: bool = true,
raygui: bool = false,
platform: PlatformBackend = .glfw, platform: PlatformBackend = .glfw,
linkage: std.builtin.LinkMode = .static, linkage: std.builtin.LinkMode = .static,
linux_display_backend: LinuxDisplayBackend = .X11, linux_display_backend: LinuxDisplayBackend = .X11,
@ -396,6 +531,7 @@ pub const Options = struct {
.rtext = b.option(bool, "rtext", "Compile with text support") orelse defaults.rtext, .rtext = b.option(bool, "rtext", "Compile with text support") orelse defaults.rtext,
.rtextures = b.option(bool, "rtextures", "Compile with textures support") orelse defaults.rtextures, .rtextures = b.option(bool, "rtextures", "Compile with textures support") orelse defaults.rtextures,
.rshapes = b.option(bool, "rshapes", "Compile with shapes support") orelse defaults.rshapes, .rshapes = b.option(bool, "rshapes", "Compile with shapes support") orelse defaults.rshapes,
.raygui = b.option(bool, "raygui", "Include raygui") orelse defaults.raygui,
.linkage = b.option(std.builtin.LinkMode, "linkage", "Compile as shared or static library") orelse defaults.linkage, .linkage = b.option(std.builtin.LinkMode, "linkage", "Compile as shared or static library") orelse defaults.linkage,
.linux_display_backend = b.option(LinuxDisplayBackend, "linux_display_backend", "Linux display backend to use") orelse defaults.linux_display_backend, .linux_display_backend = b.option(LinuxDisplayBackend, "linux_display_backend", "Linux display backend to use") orelse defaults.linux_display_backend,
.opengl_version = b.option(OpenglVersion, "opengl_version", "OpenGL version to use") orelse defaults.opengl_version, .opengl_version = b.option(OpenglVersion, "opengl_version", "OpenGL version to use") orelse defaults.opengl_version,
@ -441,15 +577,38 @@ pub const PlatformBackend = enum {
glfw, glfw,
rgfw, rgfw,
sdl, sdl,
sdl2,
sdl3,
memory,
win32,
drm, drm,
android, android,
}; };
fn translateCMod(
comptime header: []const u8,
b: *std.Build,
target: std.Build.ResolvedTarget,
optimize: std.builtin.OptimizeMode,
raylib: *std.Build.Step.Compile,
) void {
const c = b.addTranslateC(.{
.root_source_file = b.path("src/" ++ header ++ ".h"),
.target = target,
.optimize = optimize,
.link_libc = true,
});
const c_mod = c.createModule();
c_mod.linkLibrary(raylib);
b.modules.put(b.graph.arena, header, c_mod) catch @panic("OOM");
}
pub fn build(b: *std.Build) !void { pub fn build(b: *std.Build) !void {
const target = b.standardTargetOptions(.{}); const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{}); const optimize = b.standardOptimizeOption(.{});
const options: Options = .getOptions(b);
const lib = try compileRaylib(b, target, optimize, Options.getOptions(b)); const lib = try compileRaylib(b, target, optimize, options);
lib.installHeader(b.path("src/raylib.h"), "raylib.h"); lib.installHeader(b.path("src/raylib.h"), "raylib.h");
lib.installHeader(b.path("src/rcamera.h"), "rcamera.h"); lib.installHeader(b.path("src/rcamera.h"), "rcamera.h");
@ -458,15 +617,24 @@ pub fn build(b: *std.Build) !void {
b.installArtifact(lib); b.installArtifact(lib);
const examples = b.step("examples", "Build/Install all examples"); translateCMod("raylib", b, target, optimize, lib);
examples.dependOn(try addExamples("audio", b, target, optimize, lib)); translateCMod("rcamera", b, target, optimize, lib);
examples.dependOn(try addExamples("core", b, target, optimize, lib)); translateCMod("raymath", b, target, optimize, lib);
examples.dependOn(try addExamples("models", b, target, optimize, lib)); translateCMod("rlgl", b, target, optimize, lib);
examples.dependOn(try addExamples("others", b, target, optimize, lib));
examples.dependOn(try addExamples("shaders", b, target, optimize, lib)); if (options.raygui) {
examples.dependOn(try addExamples("shapes", b, target, optimize, lib)); addRaygui(b, target, optimize, lib);
examples.dependOn(try addExamples("text", b, target, optimize, lib)); }
examples.dependOn(try addExamples("textures", b, target, optimize, lib));
const examples = b.step("examples", "build/install all examples");
examples.dependOn(try addExamples("core", b, target, optimize, lib, options.platform));
examples.dependOn(try addExamples("audio", b, target, optimize, lib, options.platform));
examples.dependOn(try addExamples("models", b, target, optimize, lib, options.platform));
examples.dependOn(try addExamples("shaders", b, target, optimize, lib, options.platform));
examples.dependOn(try addExamples("shapes", b, target, optimize, lib, options.platform));
examples.dependOn(try addExamples("text", b, target, optimize, lib, options.platform));
examples.dependOn(try addExamples("textures", b, target, optimize, lib, options.platform));
examples.dependOn(try addExamples("others", b, target, optimize, lib, options.platform));
} }
fn addExamples( fn addExamples(
@ -475,6 +643,7 @@ fn addExamples(
target: std.Build.ResolvedTarget, target: std.Build.ResolvedTarget,
optimize: std.builtin.OptimizeMode, optimize: std.builtin.OptimizeMode,
raylib: *std.Build.Step.Compile, raylib: *std.Build.Step.Compile,
platform: PlatformBackend,
) !*std.Build.Step { ) !*std.Build.Step {
const all = b.step(module, "All " ++ module ++ " examples"); const all = b.step(module, "All " ++ module ++ " examples");
const module_subpath = b.pathJoin(&.{ "examples", module }); const module_subpath = b.pathJoin(&.{ "examples", module });
@ -485,118 +654,88 @@ fn addExamples(
var iter = dir.iterate(); var iter = dir.iterate();
while (try iter.next(b.graph.io)) |entry| { while (try iter.next(b.graph.io)) |entry| {
if (entry.kind != .file) continue; if (entry.kind != .file) continue;
const extension_idx = std.mem.lastIndexOf(u8, entry.name, ".c") orelse continue;
const name = entry.name[0..extension_idx];
const filename = try std.fmt.allocPrint(b.allocator, "{s}.c", .{name});
const path = b.pathJoin(&.{ module_subpath, filename });
// zig's mingw headers do not include pthread.h const filetype = std.fs.path.extension(entry.name);
if (std.mem.eql(u8, "core_loading_thread", name) and target.result.os.tag == .windows) continue; if (!std.mem.eql(u8, filetype, ".c")) continue;
const filename = std.fs.path.stem(entry.name);
const path = b.pathJoin(&.{ module_subpath, entry.name });
const exe_mod = b.createModule(.{ const exe_mod = b.createModule(.{
.target = target, .target = target,
.optimize = optimize, .optimize = optimize,
.link_libc = true,
}); });
exe_mod.addCSourceFile(.{ .file = b.path(path), .flags = &.{} }); exe_mod.addCSourceFile(.{ .file = b.path(path) });
exe_mod.linkLibrary(raylib); exe_mod.linkLibrary(raylib);
const run_step = b.step(name, name); if (platform == .sdl) {
exe_mod.linkSystemLibrary("SDL2", .{});
exe_mod.linkSystemLibrary("SDL3", .{});
}
if (platform == .sdl2) {
exe_mod.linkSystemLibrary("SDL2", .{});
}
if (platform == .sdl3) {
exe_mod.linkSystemLibrary("SDL3", .{});
}
if (target.result.os.tag == .emscripten) { if (std.mem.eql(u8, filename, "rlgl_standalone")) {
const wasm = b.addLibrary(.{ if (platform != .glfw) continue;
.name = name,
.linkage = .static,
.root_module = exe_mod,
});
if (std.mem.eql(u8, name, "rlgl_standalone")) {
exe_mod.addIncludePath(b.path("src")); exe_mod.addIncludePath(b.path("src"));
exe_mod.addIncludePath(b.path("src/external/glfw/include")); exe_mod.addIncludePath(b.path("src/external/glfw/include"));
} }
if (std.mem.eql(u8, name, "raylib_opengl_interop")) { if (std.mem.eql(u8, filename, "raylib_opengl_interop")) {
if (platform == .drm) continue;
if (target.result.os.tag == .macos) continue;
exe_mod.addIncludePath(b.path("src/external")); exe_mod.addIncludePath(b.path("src/external"));
} }
const run_step = b.step(filename, filename);
// web exports are completely separate
if (target.query.os_tag == .emscripten) {
exe_mod.addCMacro("PLATFORM_WEB", "");
const wasm = b.addLibrary(.{
.name = filename,
.root_module = exe_mod,
});
const install_dir: std.Build.InstallDir = .{ .custom = b.fmt("web/{s}/{s}", .{ module, filename }) };
const emcc_flags = emsdk.emccDefaultFlags(b.allocator, .{ .optimize = optimize }); const emcc_flags = emsdk.emccDefaultFlags(b.allocator, .{ .optimize = optimize });
const emcc_settings = emsdk.emccDefaultSettings(b.allocator, .{ .optimize = optimize }); const emcc_settings = emsdk.emccDefaultSettings(b.allocator, .{ .optimize = optimize });
const install_dir: std.Build.InstallDir = .{ .custom = "htmlout" };
const emcc_step = emsdk.emccStep(b, raylib, wasm, .{ const emcc_step = emsdk.emccStep(b, raylib, wasm, .{
.optimize = optimize, .optimize = optimize,
.flags = emcc_flags, .flags = emcc_flags,
.settings = emcc_settings, .settings = emcc_settings,
.shell_file_path = b.path("src/shell.html"), .shell_file_path = b.path("src/shell.html"),
.embed_paths = &.{
.{
.src_path = b.pathJoin(&.{ module_subpath, "resources" }),
.virtual_path = "resources",
},
},
.install_dir = install_dir, .install_dir = install_dir,
}); });
b.getInstallStep().dependOn(emcc_step);
const html_filename = try std.fmt.allocPrint(b.allocator, "{s}.html", .{wasm.name}); const html_filename = try std.fmt.allocPrint(b.allocator, "{s}.html", .{wasm.name});
const emrun_step = emsdk.emrunStep( const emrun_step = emsdk.emrunStep(
b, b,
b.getInstallPath(install_dir, html_filename), b.getInstallPath(install_dir, html_filename),
&.{"--no_browser"}, &.{},
); );
emrun_step.dependOn(emcc_step);
emrun_step.dependOn(emcc_step);
run_step.dependOn(emrun_step); run_step.dependOn(emrun_step);
all.dependOn(emcc_step); all.dependOn(emcc_step);
} else { } else {
// special examples that test using these external dependencies directly
// alongside raylib
if (std.mem.eql(u8, name, "rlgl_standalone")) {
exe_mod.addIncludePath(b.path("src"));
exe_mod.addIncludePath(b.path("src/external/glfw/include"));
if (!hasCSource(raylib.root_module, "rglfw.c")) {
exe_mod.addCSourceFile(.{ .file = b.path("src/rglfw.c"), .flags = &.{} });
}
}
if (std.mem.eql(u8, name, "raylib_opengl_interop")) {
exe_mod.addIncludePath(b.path("src/external"));
}
switch (target.result.os.tag) {
.windows => {
exe_mod.linkSystemLibrary("winmm", .{});
exe_mod.linkSystemLibrary("gdi32", .{});
exe_mod.linkSystemLibrary("opengl32", .{});
exe_mod.addCMacro("PLATFORM_DESKTOP", ""); exe_mod.addCMacro("PLATFORM_DESKTOP", "");
},
.linux => {
exe_mod.linkSystemLibrary("GL", .{});
exe_mod.linkSystemLibrary("rt", .{});
exe_mod.linkSystemLibrary("dl", .{});
exe_mod.linkSystemLibrary("m", .{});
exe_mod.linkSystemLibrary("X11", .{});
exe_mod.addCMacro("PLATFORM_DESKTOP", "");
},
.macos => {
exe_mod.linkFramework("Foundation", .{});
exe_mod.linkFramework("Cocoa", .{});
exe_mod.linkFramework("OpenGL", .{});
exe_mod.linkFramework("CoreAudio", .{});
exe_mod.linkFramework("CoreVideo", .{});
exe_mod.linkFramework("IOKit", .{});
exe_mod.addCMacro("PLATFORM_DESKTOP", "");
},
else => {
@panic("Unsupported OS");
},
}
const exe = b.addExecutable(.{ const exe = b.addExecutable(.{
.name = name, .name = filename,
.root_module = exe_mod, .root_module = exe_mod,
.use_lld = target.result.os.tag == .windows,
}); });
b.installArtifact(exe);
const install_cmd = b.addInstallArtifact(exe, .{}); const install_cmd = b.addInstallArtifact(exe, .{ .dest_sub_path = b.fmt("{s}/{s}", .{ module, filename }) });
const run_cmd = b.addRunArtifact(exe); const run_cmd = b.addRunArtifact(exe);
run_cmd.cwd = b.path(module_subpath); run_cmd.cwd = b.path(module_subpath);
@ -606,41 +745,46 @@ fn addExamples(
all.dependOn(&install_cmd.step); all.dependOn(&install_cmd.step);
} }
} }
return all; return all;
} }
fn waylandGenerate( fn waylandGenerate(
b: *std.Build, b: *std.Build,
raylib: *std.Build.Step.Compile, raylib: *std.Build.Step.Compile,
comptime protocol: []const u8, comptime waylandDir: []const u8,
comptime basename: []const u8, comptime source: bool,
) void { ) !void {
const waylandDir = "src/external/glfw/deps/wayland"; const dir = try b.build_root.handle.openDir(b.graph.io, waylandDir, .{ .iterate = true });
const protocolDir = b.pathJoin(&.{ waylandDir, protocol }); defer dir.close(b.graph.io);
const clientHeader = basename ++ ".h";
const privateCode = basename ++ "-code.h";
var iter = dir.iterate();
while (try iter.next(b.graph.io)) |entry| {
if (entry.kind != .file) continue;
const protocolDir = b.pathJoin(&.{ waylandDir, entry.name });
const filename = std.fs.path.stem(entry.name);
const clientHeader = b.fmt("{s}-client-protocol.h", .{filename});
const client_step = b.addSystemCommand(&.{ "wayland-scanner", "client-header" }); const client_step = b.addSystemCommand(&.{ "wayland-scanner", "client-header" });
client_step.addFileArg(b.path(protocolDir)); client_step.addFileArg(b.path(protocolDir));
raylib.root_module.addIncludePath(client_step.addOutputFileArg(clientHeader).dirname()); raylib.root_module.addIncludePath(client_step.addOutputFileArg(clientHeader).dirname());
raylib.step.dependOn(&client_step.step);
if (comptime source) {
const privateCode = b.fmt("{s}-client-protocol-code.c", .{filename});
const private_step = b.addSystemCommand(&.{ "wayland-scanner", "private-code" }); const private_step = b.addSystemCommand(&.{ "wayland-scanner", "private-code" });
private_step.addFileArg(b.path(protocolDir)); private_step.addFileArg(b.path(protocolDir));
raylib.root_module.addIncludePath(private_step.addOutputFileArg(privateCode).dirname()); raylib.root_module.addCSourceFile(.{
.file = private_step.addOutputFileArg(privateCode),
raylib.step.dependOn(&client_step.step); .flags = &.{ "-std=c99", "-O2" },
});
raylib.step.dependOn(&private_step.step); raylib.step.dependOn(&private_step.step);
} } else {
const privateCodeHeader = b.fmt("{s}-client-protocol-code.h", .{filename});
fn hasCSource(module: *std.Build.Module, name: []const u8) bool { const private_head_step = b.addSystemCommand(&.{ "wayland-scanner", "private-code" });
for (module.link_objects.items) |o| switch (o) { private_head_step.addFileArg(b.path(protocolDir));
.c_source_file => |c| if (switch (c.file) { raylib.root_module.addIncludePath(private_head_step.addOutputFileArg(privateCodeHeader).dirname());
.src_path => |s| std.ascii.endsWithIgnoreCase(s.sub_path, name), raylib.step.dependOn(&private_head_step.step);
.generated, .cwd_relative, .dependency => false, }
}) return true, }
.c_source_files => |s| for (s.files) |c| if (std.ascii.endsWithIgnoreCase(c, name)) return true,
else => {},
};
return false;
} }

View File

@ -11,6 +11,11 @@
.hash = "N-V-__8AALShqgXkvqYU6f__FrA22SMWmi2TXCJjNTO1m8XJ", .hash = "N-V-__8AALShqgXkvqYU6f__FrA22SMWmi2TXCJjNTO1m8XJ",
.lazy = true, .lazy = true,
}, },
.raygui = .{
.url = "git+https://github.com/raysan5/raygui#3b2855842ab578a034f827c38cf8f62c042fc983",
.hash = "N-V-__8AAHvybwBw1kyBGn0BW_s1RqIpycNjLf_XbE-fpLUF",
.lazy = true,
},
.emsdk = .{ .emsdk = .{
.url = "git+https://github.com/emscripten-core/emsdk#4.0.9", .url = "git+https://github.com/emscripten-core/emsdk#4.0.9",
.hash = "N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ", .hash = "N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ",

View File

@ -22,7 +22,7 @@
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
* BSD-like license that allows static linking with closed source software * BSD-like license that allows static linking with closed source software
* *
* Copyright (c) 2013-2025 Ramon Santamaria (@raysan5) * Copyright (c) 2013-2026 Ramon Santamaria (@raysan5)
* *
********************************************************************************************/ ********************************************************************************************/

View File

@ -13,6 +13,7 @@ IDE | Platform(s) | Source | Example(s)
[SublimeText](https://www.sublimetext.com/) | Windows, Linux, macOS | ✔️ | ✔️ [SublimeText](https://www.sublimetext.com/) | Windows, Linux, macOS | ✔️ | ✔️
[VS2019](https://www.visualstudio.com) | Windows | ✔️ | ✔️ [VS2019](https://www.visualstudio.com) | Windows | ✔️ | ✔️
[VSCode](https://code.visualstudio.com/) | Windows, macOS | ❌ | ✔️ [VSCode](https://code.visualstudio.com/) | Windows, macOS | ❌ | ✔️
[Zig](https://ziglang.org) | Windows, Linux, macOS, Web | ✔️ | ✔️
scripts | Windows, Linux, macOS | ✔️ | ✔️ scripts | Windows, Linux, macOS | ✔️ | ✔️
*New IDEs config files are welcome!* *New IDEs config files are welcome!*

84
projects/Zig/README.md Normal file
View File

@ -0,0 +1,84 @@
# Starting your raylib project with Zig (0.16.0)
## How to compile and run it
To compile the project:
```sh
zig build
```
To run the project:
```sh
zig build run
```
## Compile with different optimization
To change from debug to release build you can do it with the `-Doptimze=` flag.
```
Debug
ReleaseSafe
ReleaseFast
ReleaseSmall
```
## Choose a different platform
To compile with a different platform you can use the `-Dplatform=` flag.
Here all the options:
```
glfw
rgfw
sdl
sdl2
sdl3
memory
win32
drm
android
```
In this example the platform `sdl` and `sdl2` are not supported
Important for the android platform you also have to compile for the right target
## Compile for a different target
To compile for a different [target](https://ziglang.org/download/0.16.0/release-notes.html#Support-Table) you can use the `-Dtarget=` flag.
Not all targets are supported
## Example: Compile for web and run it
To compile for the web we use emscripten and you run it like that:
```sh
zig build -Dtarget=wasm32-emscripten
```
To run it we do:
```sh
zig build run -Dtarget=wasm32-emscripten
```
And to make a relase build we do:
```sh
zig build -Dtarget=wasm32-emscripten -Doptimize=ReleaseFast
```
If we want to use rgfw for the web build we could do:
```sh
zig build -Dplatform=rgfw -Dtarget=wasm32-emscripten -Doptimize=ReleaseFast
```
## Compiling the Zig code? Just add `-Dzig` and try out zig ;)
## More Resources
See [Zig Build System](https://ziglang.org/learn/build-system/)

87
projects/Zig/build.zig Normal file
View File

@ -0,0 +1,87 @@
const std = @import("std");
const rl = @import("raylib");
pub fn build(b: *std.Build) !void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
const platform = b.option(rl.PlatformBackend, "platform", "select the platform") orelse rl.PlatformBackend.glfw;
const zig = b.option(bool, "zig", "compile zig code") orelse false;
const raylib_dep = b.dependency("raylib", .{
.target = target,
.optimize = optimize,
.platform = platform,
});
const raylib_artifact = raylib_dep.artifact("raylib");
if (platform == .sdl3) {
if (b.lazyDependency("sdl3", .{ .optimize = optimize, .target = target })) |dep| {
raylib_artifact.root_module.linkLibrary(dep.artifact("SDL3"));
}
}
var exe_mod: *std.Build.Module = undefined;
if (zig) {
exe_mod = b.createModule(.{
.root_source_file = b.path("src/core_basic_window.zig"),
.target = target,
.optimize = optimize,
});
exe_mod.addImport("raylib", raylib_dep.module("raylib"));
} else {
exe_mod = b.createModule(.{
.target = target,
.optimize = optimize,
.link_libc = true,
});
exe_mod.addCSourceFile(.{ .file = b.path("src/core_basic_window.c") });
exe_mod.linkLibrary(raylib_artifact);
}
const run_step = b.step("run", "Run the app");
// web exports are completely separate
if (target.query.os_tag == .emscripten) {
const emsdk = rl.emsdk;
const wasm = b.addLibrary(.{
.name = "core_basic_window_web",
.root_module = exe_mod,
});
const install_dir: std.Build.InstallDir = .{ .custom = "web" };
const emcc_flags = emsdk.emccDefaultFlags(b.allocator, .{ .optimize = optimize });
const emcc_settings = emsdk.emccDefaultSettings(b.allocator, .{ .optimize = optimize });
const emcc_step = emsdk.emccStep(b, raylib_artifact, wasm, .{
.optimize = optimize,
.flags = emcc_flags,
.settings = emcc_settings,
.shell_file_path = emsdk.shell(raylib_dep),
.install_dir = install_dir,
});
b.getInstallStep().dependOn(emcc_step);
const html_filename = try std.fmt.allocPrint(b.allocator, "{s}.html", .{wasm.name});
const emrun_step = emsdk.emrunStep(
b,
b.getInstallPath(install_dir, html_filename),
&.{},
);
emrun_step.dependOn(emcc_step);
run_step.dependOn(emrun_step);
} else {
const exe = b.addExecutable(.{
.name = "core_basic_window",
.root_module = exe_mod,
.use_lld = target.result.os.tag == .windows,
});
b.installArtifact(exe);
const run_cmd = b.addRunArtifact(exe);
run_cmd.step.dependOn(b.getInstallStep());
run_step.dependOn(&run_cmd.step);
}
}

View File

@ -0,0 +1,23 @@
.{
.name = .example,
.version = "0.0.1",
.minimum_zig_version = "0.16.0",
.paths = .{""},
.dependencies = .{
.raylib = .{
.path = "../../",
},
.emsdk = .{
.url = "git+https://github.com/emscripten-core/emsdk?ref=4.0.9#3bcf1dcd01f040f370e10fe673a092d9ed79ebb5",
.hash = "N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ",
},
.sdl3 = .{
.url = "git+https://codeberg.org/7Games/zig-sdl3?ref=master#6d418ef3ddae99098414a96a88bf5e5fdb41785e",
.hash = "sdl3-0.1.9-NmT1QwiEJwByePqkmArtppCHQn8Y7kiSWcncT_Mop8ie",
.lazy = true,
},
},
.fingerprint = 0x6eec9b9f1a9d7aca,
}

View File

@ -0,0 +1,83 @@
/*******************************************************************************************
*
* raylib [core] example - Basic window (adapted for HTML5 platform)
*
* This example is prepared to compile for PLATFORM_WEB and PLATFORM_DESKTOP
* As you will notice, code structure is slightly different to the other examples...
* To compile it for PLATFORM_WEB just uncomment #define PLATFORM_WEB at beginning
*
* This example has been created using raylib 1.3 (www.raylib.com)
* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
*
* Copyright (c) 2015 Ramon Santamaria (@raysan5)
*
********************************************************************************************/
#include "raylib.h"
#if defined(PLATFORM_WEB)
#include <emscripten/emscripten.h>
#endif
//----------------------------------------------------------------------------------
// Global Variables Definition
//----------------------------------------------------------------------------------
int screenWidth = 800;
int screenHeight = 450;
//----------------------------------------------------------------------------------
// Module Functions Declaration
//----------------------------------------------------------------------------------
void UpdateDrawFrame(void); // Update and Draw one frame
//----------------------------------------------------------------------------------
// Program main entry point
//----------------------------------------------------------------------------------
int main()
{
// Initialization
//--------------------------------------------------------------------------------------
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
//--------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
{
UpdateDrawFrame();
}
#endif
// De-Initialization
//--------------------------------------------------------------------------------------
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}
//----------------------------------------------------------------------------------
// Module Functions Definition
//----------------------------------------------------------------------------------
void UpdateDrawFrame(void)
{
// Update
//----------------------------------------------------------------------------------
// TODO: Update your variables here
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
DrawText("Congrats! You created your first window!", 190, 200, 20, LIGHTGRAY);
EndDrawing();
//----------------------------------------------------------------------------------
}

View File

@ -0,0 +1,73 @@
//*******************************************************************************************
//*
//* raylib [core] example - Basic window (adapted for HTML5 platform)
//*
//* This example is prepared to compile for PLATFORM_WEB and PLATFORM_DESKTOP
//* As you will notice, code structure is slightly different to the other examples...
//* To compile it for PLATFORM_WEB just uncomment #define PLATFORM_WEB at beginning
//*
//* This example has been created using raylib 6.0 (www.raylib.com)
//* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
//*
//* Copyright (c) 2015 Ramon Santamaria (@raysan5)
//* Rewrite in Zig by HaxSam (@haxsam)
//*
//*******************************************************************************************
const rl = @import("raylib");
const std = @import("std");
const builtin = @import("builtin");
//----------------------------------------------------------------------------------
// Global Variables Definition
//----------------------------------------------------------------------------------
const screenWidth: c_int = 800;
const screenHeight: c_int = 450;
//----------------------------------------------------------------------------------
// Program main entry point
//----------------------------------------------------------------------------------
pub fn main() void {
// Initialization
//--------------------------------------------------------------------------------------
rl.InitWindow(screenWidth, screenHeight, "raylib [core] example - basic window");
if (builtin.os.tag == .emscripten) {
std.os.emscripten.emscripten_set_main_loop(UpdateDrawFrame, 0, 1);
} else {
rl.SetTargetFPS(60); // Set our game to run at 60 frames-per-second
//--------------------------------------------------------------------------------------
// Main game loop
while (!rl.WindowShouldClose()) // Detect window close button or ESC key
{
UpdateDrawFrame();
}
}
// De-Initialization
//--------------------------------------------------------------------------------------
rl.CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
}
//----------------------------------------------------------------------------------
// Module Functions Definition
//----------------------------------------------------------------------------------
fn UpdateDrawFrame() callconv(.c) void {
// Update
//----------------------------------------------------------------------------------
// TODO: Update your variables here
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
rl.BeginDrawing();
rl.ClearBackground(rl.RAYWHITE);
rl.DrawText("Congrats! You created your first window!", 190, 200, 20, rl.LIGHTGRAY);
rl.EndDrawing();
//----------------------------------------------------------------------------------
}

View File

@ -4125,8 +4125,8 @@ Vector2 GetMouseDelta(void)
{ {
Vector2 delta = { 0 }; Vector2 delta = { 0 };
delta.x = CORE.Input.Mouse.currentPosition.x - CORE.Input.Mouse.previousPosition.x; delta.x = (CORE.Input.Mouse.currentPosition.x - CORE.Input.Mouse.previousPosition.x)*CORE.Input.Mouse.scale.x;
delta.y = CORE.Input.Mouse.currentPosition.y - CORE.Input.Mouse.previousPosition.y; delta.y = (CORE.Input.Mouse.currentPosition.y - CORE.Input.Mouse.previousPosition.y)*CORE.Input.Mouse.scale.y;
return delta; return delta;
} }

View File

@ -4105,7 +4105,7 @@ bool CheckCollisionSpheres(Vector3 center1, float radius1, Vector3 center2, floa
// Check for distances squared to avoid sqrtf() // Check for distances squared to avoid sqrtf()
float radSum = radius1 + radius2; float radSum = radius1 + radius2;
if (Vector3DistanceSqr(center1, center2) <= radSum*radSum) collision = true; if (Vector3DistanceSqr(center1, center2) <= (radSum*radSum)) collision = true;
return collision; return collision;
} }
@ -4131,18 +4131,13 @@ bool CheckCollisionBoxSphere(BoundingBox box, Vector3 center, float radius)
{ {
bool collision = false; bool collision = false;
float dmin = 0; Vector3 closestPoint = {
Clamp(center.x, box.min.x, box.max.x),
Clamp(center.y, box.min.y, box.max.y),
Clamp(center.z, box.min.z, box.max.z)
};
if (center.x < box.min.x) dmin += powf(center.x - box.min.x, 2); if (Vector3DistanceSqr(center, closestPoint) <= (radius*radius)) collision = true;
else if (center.x > box.max.x) dmin += powf(center.x - box.max.x, 2);
if (center.y < box.min.y) dmin += powf(center.y - box.min.y, 2);
else if (center.y > box.max.y) dmin += powf(center.y - box.max.y, 2);
if (center.z < box.min.z) dmin += powf(center.z - box.min.z, 2);
else if (center.z > box.max.z) dmin += powf(center.z - box.max.z, 2);
if (dmin <= (radius*radius)) collision = true;
return collision; return collision;
} }