From 834dad44ee12fa49fbe897eaa17e7bcb57ec47a5 Mon Sep 17 00:00:00 2001
From: Nathan Anderson <n8r@tuta.io>
Date: Mon, 30 Dec 2024 09:26:12 -0700
Subject: [PATCH] First window rendered, sdl here I come

---
 .envrc             |   1 +
 .gitignore         |   2 +
 build.zig          | 145 +++++++++++++++++++++++++++++++++++++++++++++
 build.zig.zon      |  16 +++++
 flake.lock         |  92 ++++++++++++++++++++++++++++
 flake.nix          |  27 +++++++++
 nix/zls/flake.lock |  26 ++++++++
 nix/zls/flake.nix  |  33 +++++++++++
 src/main.zig       |  72 ++++++++++++++++++++++
 src/root.zig       |  10 ++++
 src/zig.bmp        | Bin 0 -> 168138 bytes
 11 files changed, 424 insertions(+)
 create mode 100644 .envrc
 create mode 100644 .gitignore
 create mode 100644 build.zig
 create mode 100644 build.zig.zon
 create mode 100644 flake.lock
 create mode 100644 flake.nix
 create mode 100644 nix/zls/flake.lock
 create mode 100644 nix/zls/flake.nix
 create mode 100644 src/main.zig
 create mode 100644 src/root.zig
 create mode 100644 src/zig.bmp

diff --git a/.envrc b/.envrc
new file mode 100644
index 0000000..3550a30
--- /dev/null
+++ b/.envrc
@@ -0,0 +1 @@
+use flake
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..914e310
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+.direnv/**
+.zig-cache/**
diff --git a/build.zig b/build.zig
new file mode 100644
index 0000000..de7f030
--- /dev/null
+++ b/build.zig
@@ -0,0 +1,145 @@
+const std = @import("std");
+
+const Build = @import("std").Build;
+
+pub fn build(b: *Build) void {
+    const target = b.standardTargetOptions(.{});
+    const optimize = b.standardOptimizeOption(.{});
+
+    const exe = b.addExecutable(.{
+        .name = "zsdl",
+        .root_source_file = .{ .src_path = .{ .owner = b, .sub_path = "src/main.zig" } },
+        .target = target,
+        .optimize = optimize,
+    });
+    if (target.query.isNativeOs() and target.result.os.tag == .linux) {
+        // The SDL package doesn't work for Linux yet, so we rely on system
+        // packages for now.
+        exe.linkSystemLibrary("SDL2");
+        exe.linkLibC();
+    } else {
+        const sdl_dep = b.dependency("sdl", .{
+            .optimize = .ReleaseFast,
+            .target = target,
+        });
+        exe.linkLibrary(sdl_dep.artifact("SDL2"));
+    }
+
+    b.installArtifact(exe);
+
+    // Create Check step for zls
+    const exe_check = b.addExecutable(.{
+        .name = "zsdl",
+        .root_source_file = .{ .src_path = .{ .owner = b, .sub_path = "src/main.zig" } },
+        .target = target,
+        .optimize = optimize,
+    });
+    if (target.query.isNativeOs() and target.result.os.tag == .linux) {
+        // The SDL package doesn't work for Linux yet, so we rely on system
+        // packages for now.
+        exe_check.linkSystemLibrary("SDL2");
+        exe_check.linkLibC();
+    } else {
+        const sdl_dep = b.dependency("sdl", .{
+            .optimize = .ReleaseFast,
+            .target = target,
+        });
+        exe_check.linkLibrary(sdl_dep.artifact("SDL2"));
+    }
+    const check = b.step("check", "Check if project compiles, used by Zig Language Server");
+    check.dependOn(&exe_check.step);
+
+    const run = b.step("run", "Run the demo");
+    const run_cmd = b.addRunArtifact(exe);
+    run.dependOn(&run_cmd.step);
+}
+
+// // Although this function looks imperative, note that its job is to
+// // declaratively construct a build graph that will be executed by an external
+// // runner.
+// pub fn build(b: *std.Build) void {
+//     // Standard target options allows the person running `zig build` to choose
+//     // what target to build for. Here we do not override the defaults, which
+//     // means any target is allowed, and the default is native. Other options
+//     // for restricting supported target set are available.
+//     const target = b.standardTargetOptions(.{});
+
+//     // Standard optimization options allow the person running `zig build` to select
+//     // between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall. Here we do not
+//     // set a preferred release mode, allowing the user to decide how to optimize.
+//     const optimize = b.standardOptimizeOption(.{});
+
+//     const lib = b.addStaticLibrary(.{
+//         .name = "zsdl",
+//         // In this case the main source file is merely a path, however, in more
+//         // complicated build scripts, this could be a generated file.
+//         .root_source_file = b.path("src/root.zig"),
+//         .target = target,
+//         .optimize = optimize,
+//     });
+
+//     // This declares intent for the library to be installed into the standard
+//     // location when the user invokes the "install" step (the default step when
+//     // running `zig build`).
+//     b.installArtifact(lib);
+
+//     const exe = b.addExecutable(.{
+//         .name = "zsdl",
+//         .root_source_file = b.path("src/main.zig"),
+//         .target = target,
+//         .optimize = optimize,
+//     });
+
+//     // This declares intent for the executable to be installed into the
+//     // standard location when the user invokes the "install" step (the default
+//     // step when running `zig build`).
+//     b.installArtifact(exe);
+
+//     // This *creates* a Run step in the build graph, to be executed when another
+//     // step is evaluated that depends on it. The next line below will establish
+//     // such a dependency.
+//     const run_cmd = b.addRunArtifact(exe);
+
+//     // By making the run step depend on the install step, it will be run from the
+//     // installation directory rather than directly from within the cache directory.
+//     // This is not necessary, however, if the application depends on other installed
+//     // files, this ensures they will be present and in the expected location.
+//     run_cmd.step.dependOn(b.getInstallStep());
+
+//     // This allows the user to pass arguments to the application in the build
+//     // command itself, like this: `zig build run -- arg1 arg2 etc`
+//     if (b.args) |args| {
+//         run_cmd.addArgs(args);
+//     }
+
+//     // This creates a build step. It will be visible in the `zig build --help` menu,
+//     // and can be selected like this: `zig build run`
+//     // This will evaluate the `run` step rather than the default, which is "install".
+//     const run_step = b.step("run", "Run the app");
+//     run_step.dependOn(&run_cmd.step);
+
+//     // Creates a step for unit testing. This only builds the test executable
+//     // but does not run it.
+//     const lib_unit_tests = b.addTest(.{
+//         .root_source_file = b.path("src/root.zig"),
+//         .target = target,
+//         .optimize = optimize,
+//     });
+
+//     const run_lib_unit_tests = b.addRunArtifact(lib_unit_tests);
+
+//     const exe_unit_tests = b.addTest(.{
+//         .root_source_file = b.path("src/main.zig"),
+//         .target = target,
+//         .optimize = optimize,
+//     });
+
+//     const run_exe_unit_tests = b.addRunArtifact(exe_unit_tests);
+
+//     // Similar to creating the run step earlier, this exposes a `test` step to
+//     // the `zig build --help` menu, providing a way for the user to request
+//     // running the unit tests.
+//     const test_step = b.step("test", "Run unit tests");
+//     test_step.dependOn(&run_lib_unit_tests.step);
+//     test_step.dependOn(&run_exe_unit_tests.step);
+// }
diff --git a/build.zig.zon b/build.zig.zon
new file mode 100644
index 0000000..176bfa3
--- /dev/null
+++ b/build.zig.zon
@@ -0,0 +1,16 @@
+.{
+    .name = "zsdl",
+    .version = "0.0.1",
+    .minimum_zig_version = "0.13.0",
+    .dependencies = .{
+        .SDL = .{
+            .url = "https://github.com/allyourcodebase/SDL/archive/7e4fc30b201d266f197fef4153f7e046bd189a7c.tar.gz",
+            .hash = "1220c57b0bec66a2378e90cd7a79e36f9e7f60c02acca769ab3e6f974d4ef6766418",
+        },
+    },
+    .paths = .{
+        "build.zig",
+        "build.zig.zon",
+        "src",
+    },
+}
diff --git a/flake.lock b/flake.lock
new file mode 100644
index 0000000..762544c
--- /dev/null
+++ b/flake.lock
@@ -0,0 +1,92 @@
+{
+  "nodes": {
+    "flake-utils": {
+      "inputs": {
+        "systems": "systems"
+      },
+      "locked": {
+        "lastModified": 1731533236,
+        "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
+        "owner": "numtide",
+        "repo": "flake-utils",
+        "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
+        "type": "github"
+      },
+      "original": {
+        "owner": "numtide",
+        "repo": "flake-utils",
+        "type": "github"
+      }
+    },
+    "nixpkgs": {
+      "locked": {
+        "lastModified": 1735471104,
+        "narHash": "sha256-0q9NGQySwDQc7RhAV2ukfnu7Gxa5/ybJ2ANT8DQrQrs=",
+        "owner": "NixOS",
+        "repo": "nixpkgs",
+        "rev": "88195a94f390381c6afcdaa933c2f6ff93959cb4",
+        "type": "github"
+      },
+      "original": {
+        "owner": "NixOS",
+        "ref": "nixos-unstable",
+        "repo": "nixpkgs",
+        "type": "github"
+      }
+    },
+    "nixpkgs_2": {
+      "locked": {
+        "lastModified": 1719942202,
+        "narHash": "sha256-7sP4PzxRsUfRwN8rmFtRvU/nYqTI5YYeIG9P3KJV41g=",
+        "owner": "NixOS",
+        "repo": "nixpkgs",
+        "rev": "4b015946c99a5bbe9c7a685e66f165aa44644b7d",
+        "type": "github"
+      },
+      "original": {
+        "owner": "NixOS",
+        "repo": "nixpkgs",
+        "type": "github"
+      }
+    },
+    "root": {
+      "inputs": {
+        "flake-utils": "flake-utils",
+        "nixpkgs": "nixpkgs",
+        "zlsPkg": "zlsPkg"
+      }
+    },
+    "systems": {
+      "locked": {
+        "lastModified": 1681028828,
+        "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
+        "owner": "nix-systems",
+        "repo": "default",
+        "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
+        "type": "github"
+      },
+      "original": {
+        "owner": "nix-systems",
+        "repo": "default",
+        "type": "github"
+      }
+    },
+    "zlsPkg": {
+      "inputs": {
+        "nixpkgs": "nixpkgs_2"
+      },
+      "locked": {
+        "lastModified": 1,
+        "narHash": "sha256-40mzryp9AaDiufsbEISP5VJCEpg0DYrdMjpP16oSJj0=",
+        "path": "./nix/zls",
+        "type": "path"
+      },
+      "original": {
+        "path": "./nix/zls",
+        "type": "path"
+      }
+    }
+  },
+  "root": "root",
+  "version": 7
+}
diff --git a/flake.nix b/flake.nix
new file mode 100644
index 0000000..77e9df2
--- /dev/null
+++ b/flake.nix
@@ -0,0 +1,27 @@
+{
+  description = "Zig flake with ZLS";
+  inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
+  inputs.flake-utils.url = "github:numtide/flake-utils";
+  inputs.zlsPkg.url = "path:./nix/zls";
+  outputs = {
+    flake-utils,
+    nixpkgs,
+    zlsPkg,
+    ...
+  }:
+  flake-utils.lib.eachDefaultSystem (system: let
+    pkgs = import nixpkgs {
+      inherit system;
+    };
+    zls = zlsPkg.defaultPackage.${system};
+  in {
+    devShell = pkgs.mkShell {
+        buildInputs = with pkgs; [
+          lldb
+          SDL2
+          zig
+          zls
+        ];
+      };
+  });
+}
diff --git a/nix/zls/flake.lock b/nix/zls/flake.lock
new file mode 100644
index 0000000..188887d
--- /dev/null
+++ b/nix/zls/flake.lock
@@ -0,0 +1,26 @@
+{
+  "nodes": {
+    "nixpkgs": {
+      "locked": {
+        "lastModified": 1719942202,
+        "narHash": "sha256-7sP4PzxRsUfRwN8rmFtRvU/nYqTI5YYeIG9P3KJV41g=",
+        "owner": "NixOS",
+        "repo": "nixpkgs",
+        "rev": "4b015946c99a5bbe9c7a685e66f165aa44644b7d",
+        "type": "github"
+      },
+      "original": {
+        "owner": "NixOS",
+        "repo": "nixpkgs",
+        "type": "github"
+      }
+    },
+    "root": {
+      "inputs": {
+        "nixpkgs": "nixpkgs"
+      }
+    }
+  },
+  "root": "root",
+  "version": 7
+}
diff --git a/nix/zls/flake.nix b/nix/zls/flake.nix
new file mode 100644
index 0000000..921bf0b
--- /dev/null
+++ b/nix/zls/flake.nix
@@ -0,0 +1,33 @@
+{
+  description = "Zig language server";
+
+  inputs = {
+    nixpkgs.url = "github:NixOS/nixpkgs";
+  };
+
+  outputs = {self, nixpkgs}: {
+    defaultPackage.x86_64-linux =
+      with import nixpkgs { system = "x86_64-linux"; };
+
+      stdenv.mkDerivation rec {
+        name = "zls-${version}";
+        version = "0.13.0";
+        src = pkgs.fetchurl {
+          url =  "https://github.com/zigtools/zls/releases/download/${version}/zls-x86_64-linux.tar.xz";
+          sha256 = "sha256-7EwbRcr4jivLnrsWxnBgPMWW5PYhuWGE376DeznNhBA=";
+        };
+
+        sourceRoot = ".";
+
+        installPhase = ''
+        install -m755 -D zls $out/bin/zls
+        '';
+
+        meta = with lib; {
+          homepage = "https://github.com/zigtools/zls/releases";
+          description = "Zig language server";
+          platforms = platforms.linux;
+        };
+      };
+  };
+}
diff --git a/src/main.zig b/src/main.zig
new file mode 100644
index 0000000..05d45b8
--- /dev/null
+++ b/src/main.zig
@@ -0,0 +1,72 @@
+const c = @cImport({
+    @cInclude("SDL2/SDL.h");
+});
+
+const std = @import("std");
+const assert = std.debug.assert;
+
+pub fn main() !void {
+    if (c.SDL_Init(c.SDL_INIT_VIDEO) != 0) {
+        c.SDL_Log("Unable to initialize SDL: %s", c.SDL_GetError());
+        return error.SDLInitializationFailed;
+    }
+    defer c.SDL_Quit();
+
+    const screen = c.SDL_CreateWindow("My Game Window", c.SDL_WINDOWPOS_UNDEFINED, c.SDL_WINDOWPOS_UNDEFINED, 400, 140, c.SDL_WINDOW_OPENGL) orelse
+        {
+        c.SDL_Log("Unable to create window: %s", c.SDL_GetError());
+        return error.SDLInitializationFailed;
+    };
+    defer c.SDL_DestroyWindow(screen);
+
+    const renderer = c.SDL_CreateRenderer(screen, -1, 0) orelse {
+        c.SDL_Log("Unable to create renderer: %s", c.SDL_GetError());
+        return error.SDLInitializationFailed;
+    };
+    defer c.SDL_DestroyRenderer(renderer);
+
+    const zig_bmp = @embedFile("zig.bmp");
+    const rw = c.SDL_RWFromConstMem(zig_bmp, zig_bmp.len) orelse {
+        c.SDL_Log("Unable to get RWFromConstMem: %s", c.SDL_GetError());
+        return error.SDLInitializationFailed;
+    };
+    defer assert(c.SDL_RWclose(rw) == 0);
+
+    const zig_surface = c.SDL_LoadBMP_RW(rw, 0) orelse {
+        c.SDL_Log("Unable to load bmp: %s", c.SDL_GetError());
+        return error.SDLInitializationFailed;
+    };
+    defer c.SDL_FreeSurface(zig_surface);
+
+    const zig_texture = c.SDL_CreateTextureFromSurface(renderer, zig_surface) orelse {
+        c.SDL_Log("Unable to create texture from surface: %s", c.SDL_GetError());
+        return error.SDLInitializationFailed;
+    };
+    defer c.SDL_DestroyTexture(zig_texture);
+
+    var quit = false;
+    while (!quit) {
+        var event: c.SDL_Event = undefined;
+        while (c.SDL_PollEvent(&event) != 0) {
+            switch (event.type) {
+                c.SDL_QUIT => {
+                    quit = true;
+                },
+                else => {},
+            }
+        }
+
+        _ = c.SDL_RenderClear(renderer);
+        _ = c.SDL_RenderCopy(renderer, zig_texture, null, null);
+        c.SDL_RenderPresent(renderer);
+
+        c.SDL_Delay(17);
+    }
+}
+
+test "simple test" {
+    var list = std.ArrayList(i32).init(std.testing.allocator);
+    defer list.deinit(); // try commenting this out and see if zig detects the memory leak!
+    try list.append(42);
+    try std.testing.expectEqual(@as(i32, 42), list.pop());
+}
diff --git a/src/root.zig b/src/root.zig
new file mode 100644
index 0000000..ecfeade
--- /dev/null
+++ b/src/root.zig
@@ -0,0 +1,10 @@
+const std = @import("std");
+const testing = std.testing;
+
+export fn add(a: i32, b: i32) i32 {
+    return a + b;
+}
+
+test "basic add functionality" {
+    try testing.expect(add(3, 7) == 10);
+}
diff --git a/src/zig.bmp b/src/zig.bmp
new file mode 100644
index 0000000000000000000000000000000000000000..bfe71082824ed2ca016fb5822cabcc8443683120
GIT binary patch
literal 168138
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
Y1O&WCppa|2=|EU}_x@1@1MMO3e{(I7Y5)KL

literal 0
HcmV?d00001