diff --git a/.gitmodules b/.gitmodules
deleted file mode 100644
index 3ba065a..0000000
--- a/.gitmodules
+++ /dev/null
@@ -1,3 +0,0 @@
-[submodule "raylib"]
- path = raylib
- url = https://github.com/raysan5/raylib
diff --git a/README.md b/README.md
index c0c8870..9c50e48 100644
--- a/README.md
+++ b/README.md
@@ -26,26 +26,44 @@ For [raygui](https://github.com/raysan5/raygui) bindings see: https://github.com
## usage
-The easy way would be adding this as submodule directly in your source folder.
-Thats what I do until there is an official package manager for Zig.
-
-```sh
-cd $YOUR_SRC_FOLDER
-git submodule add https://github.com/ryupold/raylib.zig raylib
-git submodule update --init --recursive
+Add this as a dependency to your `build.zig.zon`
+```zig
+.{
+ .name = "example",
+ .version = "1.0.0",
+ .paths = ...,
+ .dependencies = .{
+ .raylib_zig = .{
+ .url = "https://github.com/ryupold/raylib.zig/archive/.tar.gz",
+ .hash = "",
+ },
+ },
+}
```
-The bindings have been prebuilt so you just need to add raylib as module
-
-build.zig:
+Then add the following setup to your `build.zig`:
```zig
-const raylib = @import("path/to/raylib.zig/build.zig");
+const std = @import("std");
+
+const raylib_zig_build = @import("raylib_zig");
-pub fn build(b: *std.Build) !void {
+pub fn build(b: *std.Build) !void
+{
const target = b.standardTargetOptions(.{});
- const mode = b.standardOptimizeOption(.{});
- const exe = ...;
- raylib.addTo(b, exe, target, mode, .{});
+ const optimize = b.standardOptimizeOption(.{});
+
+ const raylib_zig = b.dependency("raylib_zig", .{
+ .target = target,
+ .optimize = optimize,
+ });
+ const compile = try raylib_zig_build.setup(b, raylib_zig, .{
+ .name = "example",
+ .src = "src/main.zig",
+ .target = target,
+ .optimize = optimize,
+ .createRunStep = true,
+ });
+ b.installArtifact(compile);
}
```
@@ -63,7 +81,7 @@ pub fn main() void {
while (!raylib.WindowShouldClose()) {
raylib.BeginDrawing();
defer raylib.EndDrawing();
-
+
raylib.ClearBackground(raylib.BLACK);
raylib.DrawFPS(10, 10);
@@ -72,11 +90,9 @@ pub fn main() void {
}
```
-### WebGL (emscripten) builds
-
-For Webassembly builds see [examples-raylib.zig/build.zig](https://github.com/ryupold/examples-raylib.zig/blob/main/build.zig)
+### WASM / emscripten builds
-This weird workaround with `marshal.h/marshal.c` I actually had to make for Webassembly builds to work, because passing structs as function parameters or returning them cannot be done on the Zig side somehow. If I try it, I get a runtime error "index out of bounds". This happens only in WebAssembly builds. So `marshal.c` must be compiled with `emcc`. See [build.zig](https://github.com/ryupold/examples-raylib.zig/blob/main/build.zig) in the examples.
+Download and install the [emscripten SDK](https://emscripten.org/docs/getting_started/downloads.html), and then add the flags `-Dtarget=wasm32-emscripten` and `--sysroot /upstream/emscripten` to the zig build.
## custom definitions
An easy way to fix binding mistakes is to edit them in `bindings.json` and setting the custom flag to true. This way the binding will not be overriden when calling `zig build intermediate`.
diff --git a/build.zig b/build.zig
index 8eb0cca..a0d431d 100644
--- a/build.zig
+++ b/build.zig
@@ -1,26 +1,109 @@
const std = @import("std");
+const builtin = @import("builtin");
+
const generate = @import("generate.zig");
-pub fn build(b: *std.Build) !void {
- const raylibSrc = "raylib/src/";
+pub fn setup(app_builder: *std.Build, raylib_zig: *std.Build.Dependency, options: struct {
+ name: []const u8,
+ src: []const u8,
+ target: std.Build.ResolvedTarget,
+ optimize: std.builtin.OptimizeMode,
+ createRunStep: bool,
+}) !*std.Build.Step.Compile {
+ const raylib = raylib_zig.builder.dependency("raylib", .{
+ .target = options.target,
+ .optimize = options.optimize,
+ });
+
+ var compile: *std.Build.Step.Compile = undefined;
+ switch (options.target.result.os.tag) {
+ .emscripten => {
+ compile = app_builder.addStaticLibrary(.{
+ .name = options.name,
+ .root_source_file = .{ .path = options.src },
+ .target = options.target,
+ .optimize = options.optimize,
+ });
+ const link_step = try linkWithEmscripten(app_builder, &.{ compile, raylib.artifact("raylib") });
+ app_builder.getInstallStep().dependOn(&link_step.step);
+
+ if (options.createRunStep) {
+ const run_step = try emscriptenRunStep(app_builder);
+ run_step.step.dependOn(&link_step.step);
+ const run_option = app_builder.step("run", "Run");
+ run_option.dependOn(&run_step.step);
+ }
+ },
+ else => {
+ compile = app_builder.addExecutable(.{
+ .name = options.name,
+ .root_source_file = .{ .path = options.src },
+ .target = options.target,
+ .optimize = options.optimize,
+ });
+ compile.linkLibrary(raylib.artifact("raylib"));
+
+ if (options.createRunStep) {
+ const run_cmd = app_builder.addRunArtifact(compile);
+ run_cmd.step.dependOn(app_builder.getInstallStep());
+ if (app_builder.args) |args| {
+ run_cmd.addArgs(args);
+ }
+ const run_option = app_builder.step("run", "Run");
+ run_option.dependOn(&run_cmd.step);
+ }
+ },
+ }
+ compile.root_module.addImport("raylib", raylib_zig.module("raylib"));
+ return compile;
+}
+
+pub fn build(b: *std.Build) !void {
const target = b.standardTargetOptions(.{});
+ const optimize = b.standardOptimizeOption(.{});
+
+ const raylib = b.dependency("raylib", .{
+ .target = target,
+ .optimize = optimize,
+ });
+
+ // Add raylib module for use in dependencies.
+ const module = b.addModule("raylib", .{
+ .root_source_file = .{ .path = "raylib.zig" },
+ .target = target,
+ .optimize = optimize,
+ });
+ module.addIncludePath(.{ .path = "." });
+ module.addIncludePath(raylib.path("src"));
+ // TODO: relative path doesn't work here when used as a dependency, not sure why...
+ const marshal_c_path = try b.build_root.join(b.allocator, &.{"marshal.c"});
+ module.addCSourceFile(.{ .file = .{.path = marshal_c_path}, .flags = &.{} });
+ module.link_libc = true;
+ if (target.result.os.tag == .emscripten) {
+ if (b.sysroot == null) {
+ @panic("Pass '--sysroot \"$EMSDK/upstream/emscripten\"'");
+ }
+ const emscripten_include_path = try std.fs.path.join(b.allocator, &.{ b.sysroot.?, "cache", "sysroot", "include" });
+ module.addIncludePath(.{ .path = emscripten_include_path });
+ }
//--- parse raylib and generate JSONs for all signatures --------------------------------------
const jsons = b.step("parse", "parse raylib headers and generate raylib jsons");
const raylib_parser_build = b.addExecutable(.{
.name = "raylib_parser",
- .root_source_file = std.build.FileSource.relative("raylib_parser.zig"),
+ .root_source_file = .{ .path = "raylib_parser.zig" },
.target = target,
- .optimize = .ReleaseFast,
+ .optimize = optimize,
});
- raylib_parser_build.addCSourceFile(.{ .file = .{ .path = "raylib/parser/raylib_parser.c" }, .flags = &.{} });
+ raylib_parser_build.addCSourceFile(.{ .file = raylib.path("parser/raylib_parser.c"), .flags = &.{} });
raylib_parser_build.linkLibC();
//raylib
const raylib_H = b.addRunArtifact(raylib_parser_build);
+ const path_raylib_H = try b.allocator.dupe(u8, raylib.path("src/raylib.h").getPath(b));
raylib_H.addArgs(&.{
- "-i", raylibSrc ++ "raylib.h",
+ "-i", path_raylib_H,
"-o", "raylib.json",
"-f", "JSON",
"-d", "RLAPI",
@@ -29,8 +112,9 @@ pub fn build(b: *std.Build) !void {
//raymath
const raymath_H = b.addRunArtifact(raylib_parser_build);
+ const path_raymath_H = try b.allocator.dupe(u8, raylib.path("src/raymath.h").getPath(b));
raymath_H.addArgs(&.{
- "-i", raylibSrc ++ "raymath.h",
+ "-i", path_raymath_H,
"-o", "raymath.json",
"-f", "JSON",
"-d", "RMAPI",
@@ -39,8 +123,9 @@ pub fn build(b: *std.Build) !void {
//rlgl
const rlgl_H = b.addRunArtifact(raylib_parser_build);
+ const path_rlgl_H = try b.allocator.dupe(u8, raylib.path("src/rlgl.h").getPath(b));
rlgl_H.addArgs(&.{
- "-i", raylibSrc ++ "rlgl.h",
+ "-i", path_rlgl_H,
"-o", "rlgl.json",
"-f", "JSON",
"-d", "RLAPI",
@@ -51,7 +136,7 @@ pub fn build(b: *std.Build) !void {
const intermediate = b.step("intermediate", "generate intermediate representation of the results from 'zig build parse' (keep custom=true)");
var intermediateZigStep = b.addRunArtifact(b.addExecutable(.{
.name = "intermediate",
- .root_source_file = std.build.FileSource.relative("intermediate.zig"),
+ .root_source_file = .{ .path = "intermediate.zig" },
.target = target,
}));
intermediate.dependOn(&intermediateZigStep.step);
@@ -60,7 +145,7 @@ pub fn build(b: *std.Build) !void {
const bindings = b.step("bindings", "generate bindings in from bindings.json");
var generateZigStep = b.addRunArtifact(b.addExecutable(.{
.name = "generate",
- .root_source_file = std.build.FileSource.relative("generate.zig"),
+ .root_source_file = .{ .path = "generate.zig" },
.target = target,
}));
const fmt = b.addFmt(.{ .paths = &.{generate.outputFile} });
@@ -73,77 +158,52 @@ pub fn build(b: *std.Build) !void {
raylib_parser_install.dependOn(&generateBindings_install.step);
}
-// above: generate library
-// below: linking (use as dependency)
-
-fn current_file() []const u8 {
- return @src().file;
-}
+const emccOutputDir = "zig-out" ++ std.fs.path.sep_str ++ "htmlout" ++ std.fs.path.sep_str;
+const emccOutputFile = "index.html";
-const sep = std.fs.path.sep_str;
-const cwd = std.fs.path.dirname(current_file()).?;
-const dir_raylib = cwd ++ sep ++ "raylib" ++ sep ++ "src";
-
-const raylib_build = @import("raylib/src/build.zig");
-
-fn linkThisLibrary(b: *std.Build, target: std.Target.Query, optimize: std.builtin.Mode) *std.Build.Step.Compile {
- const lib = b.addStaticLibrary(.{ .name = "raylib.zig", .target = b.resolveTargetQuery(target), .optimize = optimize });
- lib.addIncludePath(.{ .path = dir_raylib });
- lib.addIncludePath(.{ .path = cwd });
- lib.linkLibC();
- lib.addCSourceFile(.{ .file = .{ .path = cwd ++ sep ++ "marshal.c" }, .flags = &.{} });
- std.log.info("include '{s}' to {s}", .{ dir_raylib, lib.name });
- std.log.info("include '{s}' to {s}", .{ cwd, lib.name });
- return lib;
-}
+fn emscriptenRunStep(b: *std.Build) !*std.Build.Step.Run {
+ const emrun_exe = switch (builtin.os.tag) {
+ .windows => "emrun.bat",
+ else => "emrun",
+ };
+ const emrun_exe_path = try std.fmt.allocPrint(b.allocator, "{s}" ++ std.fs.path.sep_str ++ "{s}", .{ b.sysroot.?, emrun_exe });
-/// add this package to exe
-pub fn addTo(b: *std.Build, exe: *std.Build.Step.Compile, target: std.Target.Query, optimize: std.builtin.Mode, raylibOptions: raylib_build.Options) void {
- exe.root_module.addAnonymousImport("raylib", .{ .root_source_file = .{ .path = cwd ++ sep ++ "raylib.zig" } });
- std.log.info("include '{s}' to {s}", .{ dir_raylib, exe.name });
- std.log.info("include '{s}' to {s}", .{ cwd, exe.name });
- exe.addIncludePath(.{ .path = dir_raylib });
- exe.addIncludePath(.{ .path = cwd });
- const lib = linkThisLibrary(b, target, optimize);
- const lib_raylib = raylib_build.addRaylib(b, b.resolveTargetQuery(target), optimize, raylibOptions) catch |err| std.debug.panic("addRaylib: {any}", .{err});
- exe.linkLibrary(lib_raylib);
- exe.linkLibrary(lib);
- std.log.info("linked raylib.zig", .{});
+ const run_cmd = b.addSystemCommand(&[_][]const u8{ emrun_exe_path, emccOutputDir ++ emccOutputFile });
+ return run_cmd;
}
-pub fn linkSystemDependencies(exe: *std.build.Step.Compile) void {
- switch (exe.target.getOsTag()) {
- .macos => {
- exe.linkFramework("Foundation");
- exe.linkFramework("Cocoa");
- exe.linkFramework("OpenGL");
- exe.linkFramework("CoreAudio");
- exe.linkFramework("CoreVideo");
- exe.linkFramework("IOKit");
- },
- .linux => {
- exe.addLibraryPath(.{ .path = "/usr/lib" });
- exe.addIncludePath(.{ .path = "/usr/include" });
- exe.linkSystemLibrary("GL");
- exe.linkSystemLibrary("rt");
- exe.linkSystemLibrary("dl");
- exe.linkSystemLibrary("m");
- exe.linkSystemLibrary("X11");
- },
- .freebsd, .openbsd, .netbsd, .dragonfly => {
- exe.linkSystemLibrary("GL");
- exe.linkSystemLibrary("rt");
- exe.linkSystemLibrary("dl");
- exe.linkSystemLibrary("m");
- exe.linkSystemLibrary("X11");
- exe.linkSystemLibrary("Xrandr");
- exe.linkSystemLibrary("Xinerama");
- exe.linkSystemLibrary("Xi");
- exe.linkSystemLibrary("Xxf86vm");
- exe.linkSystemLibrary("Xcursor");
- },
- else => {},
+fn linkWithEmscripten(
+ b: *std.Build,
+ itemsToLink: []const *std.Build.Step.Compile,
+) !*std.Build.Step.Run {
+ const emcc_exe = switch (builtin.os.tag) {
+ .windows => "emcc.bat",
+ else => "emcc",
+ };
+ const emcc_exe_path = try std.fmt.allocPrint(b.allocator, "{s}" ++ std.fs.path.sep_str ++ "{s}", .{ b.sysroot.?, emcc_exe });
+
+ // Create the output directory.
+ try b.build_root.handle.makePath(emccOutputDir);
+
+ // Link everything together with emcc.
+ // TODO: The build doesn't work on Windows if emc_exe_path and any of the item
+ // emitted bin paths have spaces.
+ const emcc_command = switch (builtin.os.tag) {
+ .windows => b.addSystemCommand(&.{ "cmd", "/C", emcc_exe_path }),
+ else => b.addSystemCommand(&.{emcc_exe_path}),
+ };
+ for (itemsToLink) |item| {
+ emcc_command.addFileArg(item.getEmittedBin());
+ emcc_command.step.dependOn(&item.step);
}
-
- exe.linkLibC();
+ emcc_command.addArgs(&[_][]const u8{
+ "-o",
+ emccOutputDir ++ emccOutputFile,
+ "-sFULL-ES3=1",
+ "-sUSE_GLFW=3",
+ "-sASYNCIFY",
+ "-O3",
+ "--emrun",
+ });
+ return emcc_command;
}
diff --git a/build.zig.zon b/build.zig.zon
new file mode 100644
index 0000000..54664b9
--- /dev/null
+++ b/build.zig.zon
@@ -0,0 +1,11 @@
+.{
+ .name = "raylib.zig",
+ .version = "0.0.0",
+ .paths = .{""},
+ .dependencies = .{
+ .raylib = .{
+ .url = "https://github.com/raysan5/raylib/archive/40f3df5b865eee0cd87a9e4e1347cb04c87841f8.tar.gz",
+ .hash = "12209bb07b3926d027de330c05d9425eaa52cc1a40eed291628370ba759653d5f961",
+ },
+ },
+}
diff --git a/emscripten/entry.c b/emscripten/entry.c
deleted file mode 100644
index 245e9e5..0000000
--- a/emscripten/entry.c
+++ /dev/null
@@ -1,24 +0,0 @@
-#include
-#include
-
-#include "emscripten/emscripten.h"
-#include "raylib.h"
-
-// Zig compiles C code with -fstack-protector-strong which requires the following two symbols
-// which don't seem to be provided by the emscripten toolchain(?)
-void *__stack_chk_guard = (void *)0xdeadbeef;
-void __stack_chk_fail(void)
-{
- exit(1);
-}
-
-
-// emsc_main() is the Zig entry function in main.zig
-extern int emsc_main(void);
-
-extern void emsc_set_window_size(int width, int height);
-
-int main()
-{
- return emsc_main();
-}
diff --git a/emscripten/minshell.html b/emscripten/minshell.html
deleted file mode 100644
index 5095ad8..0000000
--- a/emscripten/minshell.html
+++ /dev/null
@@ -1,96 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
- demo
-
-
-
-
-
-
-
-
-
-
-
-
- {{{ SCRIPT }}}
-
-
-
\ No newline at end of file
diff --git a/emscripten/shell.html b/emscripten/shell.html
deleted file mode 100644
index 3ab8c3a..0000000
--- a/emscripten/shell.html
+++ /dev/null
@@ -1,328 +0,0 @@
-
-
-
-
-
-
- raylib web game
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {{{ SCRIPT }}}
-
-
diff --git a/raylib b/raylib
deleted file mode 160000
index 40f3df5..0000000
--- a/raylib
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit 40f3df5b865eee0cd87a9e4e1347cb04c87841f8