From 9ead998a3bb670393163d611950761c9b97fe484 Mon Sep 17 00:00:00 2001 From: Riyyi Date: Mon, 28 Sep 2026 00:43:30 +0200 Subject: [PATCH] Change build scripts to Odin via brokkr --- .gitignore | 9 +- README.md | 12 +- build.ps1 | 57 +--- build.sh | 57 +--- compile/build.odin | 630 +++++++++++++++++++++++++++++++++++++++ fmt.sh | 6 - scripts/pre-commit | 17 +- scripts/wgpu-init.ps1 | 100 ------- scripts/wgpu-init.sh | 100 ------- src/base/hot_reload.odin | 2 +- vendor/brokkr | 2 +- 11 files changed, 661 insertions(+), 331 deletions(-) create mode 100644 compile/build.odin delete mode 100755 fmt.sh delete mode 100644 scripts/wgpu-init.ps1 delete mode 100755 scripts/wgpu-init.sh diff --git a/.gitignore b/.gitignore index d61eaf3..b651211 100644 --- a/.gitignore +++ b/.gitignore @@ -2,7 +2,12 @@ .DS_Store +build +build.exe +build.exe.old +build.old + # Directories -build -vendor/wgpu +out/ +vendor/wgpu/ diff --git a/README.md b/README.md index 80a25bd..f864cbc 100644 --- a/README.md +++ b/README.md @@ -10,14 +10,18 @@ Game engine. ### Dependencies +- `git` - `odin` -- `sh` a POSIX compatible shell +- `unzip` on macOS or Linux ### Building ```sh -./build.sh -./build.sh debug +./build.sh # debug game and engine (default) +./build.sh -debug # debug game and engine +./build.sh -release # build game and engine +./build.sh -run # run game +./build.sh -fmt # format sources ``` ## Contributing @@ -35,7 +39,7 @@ vendor - miniaudio - microui (temp) - box3d? -- build.sh -> build.odin +- build.sh -> bootstrap shim for `compile/build.odin` ## Hot Reload diff --git a/build.ps1 b/build.ps1 index b0a7016..4b790f4 100644 --- a/build.ps1 +++ b/build.ps1 @@ -1,57 +1,12 @@ $ErrorActionPreference = "Stop" -$PROJECT = "sindri" -$COMMIT = git rev-parse --short HEAD -$VERSION = "dev-$(Get-Date -Format 'yyyy-MM-dd')-$COMMIT" +Set-Location $PSScriptRoot -$OPTION = $args[0] -if ($args) { $args = $args[1..($args.Length - 1)] } else { $args = @() } - -# ------------------------------------------ - -# Setup compiled wgpu binary -& (Join-Path $PSScriptRoot "scripts\wgpu-init.ps1") - -# ------------------------------------------ -# Game compile - -New-Item -ItemType Directory -Force -Path build | Out-Null - -# Game.dll -odin build game/ -show-timings ` - -collection:sindri=src ` - -build-mode:dynamic ` - -out:build/game_tmp.dll -microarch:native "-define:VERSION=$VERSION-debug" -debug @args - -# Need to use a temp file on Windows because it first writes an empty file, -# which the engine will load before it is actually fully written. -if (-not (Test-Path "build/game_tmp.dll")) { - Write-Error "error: build produced no game lib.dll" - exit 1 -} -Move-Item -Force "build/game_tmp.dll" "build/game.dll" - -# ------------------------------------------ -# Engine compile - -# If the executable is already running, then don't try to build and start it. -$proc = Get-Process -Name $PROJECT -ErrorAction SilentlyContinue -if ($proc) { - Write-Output "Hot reloading..." - exit 0 +$exe = Join-Path $PSScriptRoot "build.exe" +if (-not (Test-Path $exe)) { + & odin build compile/build.odin -file ("-out:" + $exe) } -if ($OPTION -eq "debug") { - odin build src/ -show-timings ` - -collection:sindri=src ` - -collection:gram=vendor/gram/src ` - -collection:wgpu=vendor ` - -out:build/$PROJECT.exe -microarch:native -use-separate-modules "-define:VERSION=$VERSION-debug" -debug @args - exit 0 -} +& $exe @args -odin build src/ -show-timings ` - -collection:sindri=src ` - -collection:gram=vendor/gram/src ` - -collection:wgpu=vendor ` - -out:build/$PROJECT.exe -microarch:native -o:speed "-define:VERSION=$VERSION" @args +Set-Location - diff --git a/build.sh b/build.sh index 32fea5b..d003c0f 100755 --- a/build.sh +++ b/build.sh @@ -2,59 +2,12 @@ set -eu -PROJECT="sindri" -VERSION="dev-$(date -u '+%Y-%m-%d')-$(git rev-parse --short HEAD)" +cd -- "$(dirname -- "$0")" -OPTION="${1:-}" -shift - -# ------------------------------------------ - -# Setup compiled wgpu binary -./scripts/wgpu-init.sh - -# ------------------------------------------ -# Game compile - -mkdir -p build - -# Game.dll -odin build game/ -show-timings \ - -collection:sindri=src \ - -collection:gram=vendor/gram/src \ - -collection:wgpu=vendor \ - -build-mode:dynamic \ - -out:build/game_tmp -microarch:native -o:minimal -use-separate-modules -define:VERSION="$VERSION-debug" -debug "$@" - -# Need to use a temp file on Linux/macOS because it first writes an empty file, -# which the engine will load before it is actually fully written. -[ "$(uname -s)" = "Darwin" ] && LIB_EXT="dylib" || LIB_EXT="so" -[ -f "build/game_tmp.$LIB_EXT" ] || { - echo "error: build produced no game lib.$LIB_EXT" >&2 - exit 1 -} -mv -f "build/game_tmp.$LIB_EXT" "build/game.$LIB_EXT" - -# ------------------------------------------ -# Engine compile - -# If the executable is already running, then don't try to build and start it. -if pgrep -x $PROJECT >/dev/null; then - echo "Hot reloading..." - exit 0 +if [ ! -x ./build ]; then + odin build compile/build.odin -file -out:build fi -if [ "$OPTION" = "debug" ]; then - odin build src/ -show-timings \ - -collection:sindri=src \ - -collection:gram=vendor/gram/src \ - -collection:wgpu=vendor \ - -out:build/$PROJECT -microarch:native -o:minimal -use-separate-modules -define:VERSION="$VERSION-debug" -debug "$@" - exit 0 -fi +./build "$@" -odin build src/ -show-timings \ - -collection:sindri=src \ - -collection:gram=vendor/gram/src \ - -collection:wgpu=vendor \ - -out:build/$PROJECT -microarch:native -o:speed -define:VERSION="$VERSION" "$@" +cd - > /dev/null diff --git a/compile/build.odin b/compile/build.odin new file mode 100644 index 0000000..f21321b --- /dev/null +++ b/compile/build.odin @@ -0,0 +1,630 @@ +package build + +import "core:flags" +import "core:fmt" +import "core:log" +import "core:os" +import "core:path/filepath" +import "core:slice" +import "core:strings" +import "core:time" + +import "../vendor/brokkr" + +when ODIN_OS == .Windows { + LIB_EXT :: ".dll" + OS_NAME :: "windows" +} else when ODIN_OS == .Darwin { + LIB_EXT :: ".dylib" + OS_NAME :: "macos" +} else { + LIB_EXT :: ".so" + OS_NAME :: "linux" +} + +when ODIN_ARCH == .amd64 { + ARCH_NAME :: "x86_64" +} else when ODIN_ARCH == .arm64 { + ARCH_NAME :: "aarch64" +} + +PROJECT_NAME :: "sindri" +BUILD_DIRECTORY :: "out/" + +GAME_SRC_DIR :: "game/" +GAME_LIB_PATH :: BUILD_DIRECTORY + "game" + LIB_EXT +GAME_LIB_TMP_PATH :: BUILD_DIRECTORY + "game_tmp" + LIB_EXT + +ENGINE_DIR :: "src/" +ENGINE_OUTPUT :: BUILD_DIRECTORY + PROJECT_NAME + +BUILD_INPUT_FILES :: []string{"compile/build.odin"} + +// ----------------------------------------- +// Types + +Options :: struct { + debug: bool `args:"optional" usage:"Build project in debug-mode."`, + release: bool `args:"optional" usage:"Build project in release-mode."`, + run: bool `args:"optional" usage:"Run project."`, + wgpu_init: bool `args:"optional" usage:"Prepare wgpu-native."`, + wgpu_version: string `args:"optional" usage:"Override the wgpu release version to init."`, + fmt: bool `args:"optional" usage:"Run odinfmt."`, + pre_commit: bool `args:"optional" usage:"Run git pre-commit hook."`, + overflow: [dynamic]string `args:"manifold" usage:"Extra arguments passed through to the odin build calls."`, +} + +// ----------------------------------------- +// Main + +main :: proc() { + // Create logger + context.logger = log.create_console_logger( + .Warning, + {.Level, .Terminal_Color}, + "build", + ) + defer log.destroy_console_logger(context.logger) + + // Change working directory + chdir_project_root() + + brokkr.auto_rebuild(..BUILD_INPUT_FILES) + + opts: Options + flags.parse_or_exit(&opts, os.args, .Unix) + + if opts.debug do build_project(true, opts.overflow[:]) + if opts.release do build_project(false, opts.overflow[:]) + if opts.run do run_project(opts.overflow[:]) + if opts.wgpu_init do wgpu_init(opts.wgpu_version) + if opts.fmt do format_source() + if opts.pre_commit do pre_commit() + + // Fallback to building project, if no option provided + if len(os.args) - 1 == len(opts.overflow) { + build_project(true, opts.overflow[:]) + } +} + +// ----------------------------------------- +// Build project + +// Build the game library ('game/') and the engine ('src/') +build_project :: proc(debug: bool, odin_extra_args: []string) { + version := project_version() + + // Setup compiled wgpu binary + wgpu_init() + + // ---------------------------------------- + // Game compile + + build_game(debug, version, odin_extra_args) + + // ---------------------------------------- + // Engine compile + + // If the executable is already running, don't try to build and start it + if engine_is_running() { + fmt.println("Hot reloading...") + return + } + + build_engine(debug, version, odin_extra_args) +} + +// Shared builder between game/engine +build_common :: proc( + dir: string, + debug: bool, + version: string, + extra_args: []string, +) -> brokkr.Builder { + b := brokkr.builder_make() + brokkr.build(&b, dir) + brokkr.append(&b, "-show-timings") + brokkr.collection(&b, PROJECT_NAME, "src") + brokkr.collection(&b, "gram", "vendor/gram/src") + brokkr.collection(&b, "wgpu", "vendor") + brokkr.append(&b, "-microarch:native") + brokkr.opt(&b, debug ? .Minimal : .Speed) + brokkr.define( + &b, + "VERSION", + debug ? fmt.tprintf("%v-debug", version) : version, + ) + if debug { + brokkr.debug(&b) + brokkr.append(&b, "-use-separate-modules") + } + for arg in extra_args { + brokkr.append(&b, arg) + } + return b +} + +// Build the game as a dynamic library loaded by the engine +build_game :: proc(debug: bool, version: string, extra_args: []string) { + b := build_common(GAME_SRC_DIR, debug, version, extra_args) + defer brokkr.builder_destroy(&b) + brokkr.mode(&b, .Dynamic) + // Use a temp file because it first writes an empty file, which the engine + // would load before it is actually fully written + brokkr.out(&b, GAME_LIB_TMP_PATH) + if err := brokkr.execute(&b); err != nil { + os.exit(1) + } + + if !os.is_file(GAME_LIB_TMP_PATH) { + die("build produced no game lib %q", GAME_LIB_TMP_PATH) + } + os.rename(GAME_LIB_TMP_PATH, GAME_LIB_PATH) +} + +// Build the engine executable +build_engine :: proc(debug: bool, version: string, extra_args: []string) { + b := build_common(ENGINE_DIR, debug, version, extra_args) + defer brokkr.builder_destroy(&b) + brokkr.out(&b, output_path(ENGINE_OUTPUT)) + if err := brokkr.execute(&b); err != nil { + os.exit(1) + } +} + +run_project :: proc(extra_args: []string) { + // Build project if it wasnt already + if !os.exists(ENGINE_OUTPUT) || + !os.exists(GAME_LIB_PATH) { build_project(true, {}) } + + cmd := []string{output_path(ENGINE_OUTPUT)} + line := slice.concatenate( + [][]string{cmd, extra_args}, + context.temp_allocator, + ) + + process, s_err := os.process_start( + { + command = line, + stdin = os.stdin, + stdout = os.stdout, + stderr = os.stderr, + }, + ) + if s_err != nil { + die("failed to start project process: %v", os.error_string(s_err)) + } + + res, w_err := os.process_wait(process) + if w_err != nil { + die("failed to wait for project process: %v", os.error_string(w_err)) + } + if !res.success { + die("project process failed with exit code: %v", res.exit_code) + } + + os.exit(res.exit_code) +} + +// ----------------------------------------- +// wgpu setup + +// Prepare wgpu for usage: download, unzip, copy vendor code +wgpu_init :: proc(version_override := "") { + when ODIN_OS == .Windows { + target_name := + "wgpu-" + OS_NAME + "-" + ARCH_NAME + "-msvc" + "-release" + } else { + target_name := "wgpu-" + OS_NAME + "-" + ARCH_NAME + "-release" + } + + target := join_path({"vendor", "wgpu", "lib", target_name}) + + // ---------------------------------------- + // wgpu version detection + + // Detect the wgpu-native version the bundled bindings expect + odin_root, ok, _ := exec([]string{"odin", "root"}) + if !ok do os.exit(1) + defer delete(odin_root) + + wgpu_version := version_override + if len(wgpu_version) == 0 { + v, found := bindings_version_from_file( + join_path({odin_root, "vendor", "wgpu", "wgpu_native_types.odin"}), + ) + if !found { + die("wgpu setup: could not detect the wgpu-native version") + } + wgpu_version = fmt.tprintf("v%v", v) + } + + // Detect the version of the vendored wgpu bindings + current := "" + if wgpu_types_path := join_path( + {"vendor", "wgpu", "wgpu_native_types.odin"}, + ); os.is_file(wgpu_types_path) { + if ver, found := bindings_version_from_file(wgpu_types_path); found { + current = fmt.tprintf("v%v", ver) + } + } + + // Check if the vendored wgpu is already up to date + if current == wgpu_version && os.is_dir(target) { + return + } + + // ---------------------------------------- + // Copy vendor/wgpu + + // Remove any stale copy. + os.remove_all("vendor/wgpu") + + // Copy wgpu from the odin installation. + os.copy_directory_all( + "vendor/wgpu", + join_path({odin_root, "vendor", "wgpu"}), + ) + chmod_recursively("vendor/wgpu") + + // Point imports at the copied vendor wgpu package. + rewrite_imports("vendor/wgpu", `"vendor:wgpu"`, `"wgpu:wgpu"`) + + // ---------------------------------------- + // Download + + if !os.is_dir(target) { + url := fmt.tprintf( + "https://github.com/gfx-rs/wgpu-native/releases/download/%v/%v.zip", + wgpu_version, + target_name, + ) + fmt.println("wgpu setup: downloading", url) + + tmp_dir, err := os.make_directory_temp( + "", + "out-tmp-*", + context.temp_allocator, + ) + if err != nil { + die( + "wgpu setup: failed to create a temporary directory: %v", + os.error_string(err), + ) + } + defer os.remove_all(tmp_dir) + zip_path := join_path({tmp_dir, "wgpu.zip"}) + + when ODIN_OS == .Windows { + if dl_err := brokkr.execute_command( + []string { + "powershell", + "-NoProfile", + "-Command", + fmt.tprintf( + "$ProgressPreference='SilentlyContinue'; Invoke-WebRequest -UseBasicParsing -Uri %q -OutFile %q", + url, + zip_path, + ), + }, + ); dl_err != nil { + die("wgpu setup: failed to download wgpu-native release") + } + } else { + if dl_err := brokkr.execute_command( + []string{"curl", "-fL", "--retry", "3", "-o", zip_path, url}, + ); dl_err != nil { + die("wgpu setup: failed to download wgpu-native release") + } + } + + when ODIN_OS == .Windows { + // Uses the PowerShell cmdlet the same way scripts/wgpu-init.ps1 did. + if ex_err := brokkr.execute_command( + []string { + "powershell", + "-NoProfile", + "-Command", + fmt.tprintf( + "Expand-Archive -Force -Path %q -DestinationPath %q", + zip_path, + target, + ), + }, + ); ex_err != nil { + die("wgpu setup: failed to extract wgpu-native release") + } + } else { + // Matches scripts/wgpu-init.sh. + if ex_err := brokkr.execute_command( + []string{"unzip", "-o", "-q", zip_path, "-d", target}, + ); ex_err != nil { + die("wgpu setup: failed to extract wgpu-native release") + } + } + } +} + +// Extracts the wgpu-native version from BINDINGS_VERSION_STRING +bindings_version_from_file :: proc( + path: string, +) -> ( + version: string, + found: bool, +) { + if !os.is_file(path) do return + + data, err := os.read_entire_file(path, context.temp_allocator) + if err != nil do return + + s := string(data) + id := strings.index(s, "BINDINGS_VERSION_STRING") + if id == -1 do return + + quote_start := strings.index(s[id:], `"`) + if quote_start == -1 do return + quote_start += id + + quote_end := strings.index(s[quote_start + 1:], `"`) + if quote_end == -1 do return + quote_end += quote_start + 1 + + version = s[quote_start + 1:quote_end] + found = len(version) != 0 + return +} + +// 'chmod -R +w' equivalent: makes everything under 'path' writable, +// keeping every other permission bit +chmod_recursively :: proc(path: string) { + when ODIN_OS == .Windows { + return + } else { + info, err := os.stat(path, context.temp_allocator) + if err != nil { + die( + "wgpu setup: failed to stat %q: %v", + path, + os.error_string(err), + ) + } + + // Add writable (+w) + if err := os.change_mode(path, info.mode + os.Permissions_Write_All); + err != nil { + die("wgpu setup: chmod %q failed: %v", path, os.error_string(err)) + } + + // Recurse into directories + if info.type == .Directory { + entries, read_err := os.read_directory_by_path( + path, + -1, + context.temp_allocator, + ) + if read_err != nil { + die( + "wgpu setup: failed to read %q: %v", + path, + os.error_string(read_err), + ) + } + for entry in entries { + if entry.name == "." || entry.name == ".." do continue + chmod_recursively(join_path({path, entry.name})) + } + } + } +} + +// Replaces 'old_import' with 'new_import' in every '.odin' file under 'path' +rewrite_imports :: proc(path: string, old_import, new_import: string) { + info, err := os.stat(path, context.temp_allocator) + if err != nil { + die("wgpu setup: failed to stat %q: %v", path, os.error_string(err)) + } + + // Recurse into directories + if info.type == .Directory { + entries, read_err := os.read_directory_by_path( + path, + -1, + context.temp_allocator, + ) + if read_err != nil { + die( + "wgpu setup: failed to read %q: %v", + path, + os.error_string(read_err), + ) + } + for entry in entries { + if entry.name == "." || entry.name == ".." do continue + rewrite_imports( + join_path({path, entry.name}), + old_import, + new_import, + ) + } + return + } + + if info.type != .Regular || !strings.ends_with(info.name, ".odin") do return + + data, read_err := os.read_entire_file(path, context.temp_allocator) + if read_err != nil { + die( + "wgpu setup: failed to read %q: %v", + path, + os.error_string(read_err), + ) + } + + replacement, was_allocation := strings.replace_all( + string(data), + old_import, + new_import, + context.temp_allocator, + ) + if was_allocation { + if write_err := os.write_entire_file(path, replacement); + write_err != nil { + die( + "wgpu setup: failed to write %q: %v", + path, + os.error_string(write_err), + ) + } + } +} + +// ----------------------------------------- +// Formatting + +// Run `odinfmt -w` on source directory +format_source :: proc() { + for dir in ([]string{GAME_SRC_DIR, ENGINE_DIR}) { + err := brokkr.execute_command([]string{"odinfmt", "-w", dir}) + if err != nil do os.exit(1) + } +} + +// ----------------------------------------- +// Git pre-commit hook + +pre_commit :: proc() { + err := brokkr.execute_command( + []string{"git", "stash", "push", "--keep-index", "--quiet"}, + ) + if err != nil do os.exit(1) + + format_source() + + err = brokkr.execute_command([]string{"git", "diff", "--quiet"}) + if err != nil { + log.error("formatting changed staged files; commit aborted") + _ = brokkr.execute_command([]string{"git", "checkout", "--", "."}) + _ = brokkr.execute_command([]string{"git", "stash", "pop", "--quiet"}) + os.exit(1) + } + + err = brokkr.execute_command([]string{"git", "stash", "pop", "--quiet"}) + if err != nil do os.exit(1) +} + +// ----------------------------------------- +// Helpers + +// Log an error and exit(1) +die :: proc(fmt_str: string, args: ..any, loc := #caller_location) -> ! { + log.errorf(fmt_str, ..args, location = loc) + os.exit(1) +} + +// Change working directory to project root +chdir_project_root :: proc() { + // Get full path + binary_path, abs_err := filepath.abs(os.args[0]) + if abs_err != nil { + die( + "failed to get absolute binary path %q: %v", + os.args[0], + os.error_string(abs_err), + ) + } + + // Set working directory to project root + project_root_dir := filepath.dir(binary_path) + if err := os.set_working_directory(project_root_dir); err != nil { + die( + "failed to change working directory to %q: %v", + project_root_dir, + os.error_string(err), + ) + } + + // Set program argument to the full path of the binary + os.args[0] = binary_path +} + +// Check if engine (executable named `Project_Name`) is already running +engine_is_running :: proc() -> bool { + when ODIN_OS == .Windows { + out, ok := exec( + []string { + "tasklist", + "/FI", + ("IMAGENAME eq " + PROJECT_NAME + ".exe"), + "/NH", + }, + ) + if !ok do return false + return strings.contains(string(out), PROJECT_NAME + ".exe") + } else { + _, ok, code := exec([]string{"pgrep", "-x", PROJECT_NAME}, false) + if !ok do return false + return code == 0 + } +} + +// Runs a command. Use this over brokkr.execute_command when you need to +// capture the contents of stdout, or the return code +exec :: proc( + cmd: []string, + print_error := true, +) -> ( + out: string, + ok: bool, + code: int, +) { + state, stdout, stderr, err := os.process_exec( + {command = cmd}, + context.temp_allocator, + ) + defer delete(stdout, context.temp_allocator) + defer delete(stderr, context.temp_allocator) + + if err != nil { + log.errorf("exec failed %v: %v", cmd, os.error_string(err)) + return "", false, 1 + } + if state.exit_code != 0 { + if print_error { + log.errorf("exec failed %v: %s", cmd, stderr) + } + return "", false, state.exit_code + } + + str, a_err := strings.clone_from_bytes(stdout) + if a_err != nil { + return "", false, 1 + } + return strings.trim_space(str), true, 0 +} + +// Joins segments into a full path, ex: {"a", "b", "c"} -> a/b/c +join_path :: proc(elems: []string) -> string { + joined, err := filepath.join(elems, context.temp_allocator) + if err != nil { + die("failed to join path %v: %v", elems, os.error_string(err)) + } + return joined +} + +output_path :: proc(binary_path: string) -> string { + when ODIN_OS == .Windows { + return binary_path + ".exe" + } + return binary_path +} + +// Get project version, example: `dev-2026-09-23-a4084b3` +project_version :: proc() -> string { + commit, ok, _ := exec([]string{"git", "rev-parse", "--short", "HEAD"}) + if !ok do os.exit(1) + defer delete(commit) + + buf: [time.MIN_YYYY_DATE_LEN]u8 + date := time.to_string_yyyy_mm_dd(time.now(), buf[:]) + return fmt.tprintf("dev-%v-%v", date, commit) +} diff --git a/fmt.sh b/fmt.sh deleted file mode 100755 index 888ef0e..0000000 --- a/fmt.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/sh - -set -e - -odinfmt -w src/ > /dev/null -# odinfmt -w tests/ > /dev/null diff --git a/scripts/pre-commit b/scripts/pre-commit index 5038022..69137eb 100755 --- a/scripts/pre-commit +++ b/scripts/pre-commit @@ -1,18 +1,7 @@ #!/bin/sh +set -eu + SCRIPT_DIR=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) -git stash push --keep-index --quiet - -"$SCRIPT_DIR/../fmt.sh" - -if ! git diff --quiet; then - echo "Formatting changed staged files; commit aborted." - git checkout -- "$SCRIPT_DIR/.." - git stash pop --quiet - exit 1 -fi - -# "$SCRIPT_DIR/../test.sh" - -git stash pop --quiet +exec "$SCRIPT_DIR/../build.sh" -pre-commit diff --git a/scripts/wgpu-init.ps1 b/scripts/wgpu-init.ps1 deleted file mode 100644 index 19259b3..0000000 --- a/scripts/wgpu-init.ps1 +++ /dev/null @@ -1,100 +0,0 @@ -$ErrorActionPreference = "Stop" - -$VENDOR_DIR = Join-Path $PSScriptRoot "..\vendor" | Resolve-Path - -# ------------------------------------------ -# Platform detection (target dir name, only used for the up-to-date check) - -# Windows PowerShell 5.1 doesn't define $IsWindows/$IsMacOS/$IsLinux -if (-not (Test-Path variable:IsWindows)) { $IsWindows = $env:OS -eq "Windows_NT" } -if (-not (Test-Path variable:IsMacOS)) { $IsMacOS = $false } -if (-not (Test-Path variable:IsLinux)) { $IsLinux = $false } - -if ($IsWindows) { - $os = "windows" - $extra = "-msvc" -} elseif ($IsMacOS) { - $os = "macos" - $extra = "" -} elseif ($IsLinux) { - $os = "linux" - $extra = "" -} else { - Write-Error "wgpu setup: unsupported OS" - exit 1 -} - -$procArch = [System.Runtime.InteropServices.RuntimeInformation]::OSArchitecture -$arch = if ($procArch -eq [System.Runtime.InteropServices.Architecture]::Arm64) { "aarch64" } else { "x86_64" } - -$odinRoot = (odin root).Trim() -$name = "wgpu-$os-$arch$extra-release" -$target = Join-Path $VENDOR_DIR "wgpu\lib\$name" - -# ------------------------------------------ -# WGPU version detection - -if ($args.Count -gt 0 -and $args[0]) { - $WGPU_VERSION = $args[0] -} else { - $odinTypes = Join-Path $odinRoot "vendor\wgpu\wgpu_native_types.odin" - $typesContent = Get-Content $odinTypes -Raw - if ($typesContent -match 'BINDINGS_VERSION_STRING :: "([^"]*)"') { - $WGPU_VERSION = "v" + $Matches[1] - } -} - -if (-not $WGPU_VERSION -or $WGPU_VERSION -eq "v") { - Write-Error "wgpu setup: could not detect the wgpu-native version" - exit 1 -} - -# Detect the version of the vendored wgpu bindings -$currentTypes = Join-Path $VENDOR_DIR "wgpu\wgpu_native_types.odin" -$current = $null -if (Test-Path $currentTypes) { - $cur = Get-Content $currentTypes -Raw - if ($cur -match 'BINDINGS_VERSION_STRING :: "([^"]*)"') { - $current = "v" + $Matches[1] - } -} - -# Check if the vendored wgpu is already up to date -if ($current -eq $WGPU_VERSION -and (Test-Path $target)) { - exit 0 -} - -# ------------------------------------------ -# Copy vendor/wgpu - -# Remove any stale copy -if (Test-Path (Join-Path $VENDOR_DIR "wgpu")) { - Remove-Item -Recurse -Force (Join-Path $VENDOR_DIR "wgpu") -} - -# Copy wgpu -$wgpuPath = Join-Path $odinRoot "vendor\wgpu" -Copy-Item -Recurse $wgpuPath $VENDOR_DIR - -# Point imports at the copied vendor wgpu package -Get-ChildItem -Path (Join-Path $VENDOR_DIR "wgpu") -Recurse -Filter *.odin | ForEach-Object { - (Get-Content $_.FullName -Raw) -replace '"vendor:wgpu"', '"wgpu:wgpu"' | Set-Content $_.FullName -NoNewline -} - -# ------------------------------------------ -# Download - -$assetBase = "https://github.com/gfx-rs/wgpu-native/releases/download/$WGPU_VERSION" - -if (-not (Test-Path $target)) { - $url = "$assetBase/$name.zip" - Write-Output "wgpu setup: downloading $url" - $tmp = Join-Path ([System.IO.Path]::GetTempPath()) ([System.Guid]::NewGuid().ToString()) - New-Item -ItemType Directory -Path $tmp | Out-Null - try { - Invoke-WebRequest -MaximumRedirection 5 -Uri $url -OutFile (Join-Path $tmp "wgpu.zip") - Expand-Archive -Force -Path (Join-Path $tmp "wgpu.zip") -DestinationPath $target - } finally { - Remove-Item -Recurse -Force $tmp - } -} diff --git a/scripts/wgpu-init.sh b/scripts/wgpu-init.sh deleted file mode 100755 index 8c2522f..0000000 --- a/scripts/wgpu-init.sh +++ /dev/null @@ -1,100 +0,0 @@ -#!/bin/sh - -SCRIPT_DIR=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) -VENDOR_DIR="$SCRIPT_DIR/../vendor" - -# ------------------------------------------ -# Platform detection - -# OS detection -case "$(uname -s)" in -Darwin) - os="macos" - ;; -Linux) - os="linux" - ;; -MINGW* | MSYS* | CYGWIN*) - os="windows" - extra="-msvc" - ;; -*) - echo "wgpu setup: unsupported OS '$(uname -s)'" >&2 - exit 1 - ;; -esac - -# Arch detection -case "$(uname -m)" in -arm64 | aarch64) - arch="aarch64" - ;; -x86_64 | amd64) - arch="x86_64" - ;; -*) - echo "wgpu setup: unsupported arch '$(uname -m)'" >&2 - exit 1 - ;; -esac - -# Download filename -name="wgpu-${os}-${arch}${extra:-}-release" - -# Compiler filename: lib/wgpu-macos-aarch64-release/lib/libwgpu_native.a -target="$VENDOR_DIR/wgpu/lib/$name" - -# ------------------------------------------ -# WGPU version detection - -# Detect the wgpu-native version the bundled bindings expect, can be overridden -if [ "$1" != "" ]; then - WGPU_VERSION="$1" -else - WGPU_VERSION="v$(sed -n 's/.*BINDINGS_VERSION_STRING :: "\([^"]*\)".*/\1/p' "$(odin root)/vendor/wgpu/wgpu_native_types.odin")" -fi - -if [ "$WGPU_VERSION" = "v" ]; then - echo "wgpu setup: could not detect the wgpu-native version" >&2 - exit 1 -fi - -# Detect the version of the vendored wgpu bindings -current="v$(sed -n 's/.*BINDINGS_VERSION_STRING :: "\([^"]*\)".*/\1/p' "$VENDOR_DIR/wgpu/wgpu_native_types.odin" 2> /dev/null)" - -# Check if the vendored wgpu is already up to date -if [ "$current" = "$WGPU_VERSION" ] && [ -d "$target" ]; then - exit 0 -fi - -# ------------------------------------------ -# Copy vendor/wgpu - -# Remove any stale copy -rm -rf "$VENDOR_DIR/wgpu" - -# Copy wgpu -wgpu_path="$(odin root)/vendor/wgpu" -cp -r "$wgpu_path" "$VENDOR_DIR" -chmod -R +w "$VENDOR_DIR/wgpu" - -# Point imports at the copied vendor wgpu package -grep -rl '"vendor:wgpu"' "$VENDOR_DIR/wgpu" --include='*.odin' | - while IFS= read -r file; do - sed 's|"vendor:wgpu"|"wgpu:wgpu"|g' "$file" >"$file.tmp" && mv "$file.tmp" "$file" - done - -# ------------------------------------------ -# Download - -ASSET_BASE="https://github.com/gfx-rs/wgpu-native/releases/download/${WGPU_VERSION}" - -# Download -if [ ! -d "$target" ]; then - url="${ASSET_BASE}/${name}.zip" - echo "wgpu setup: downloading $url" - tmp=$(mktemp -d) - trap 'rm -rf "$tmp"' EXIT - curl -fL --retry 3 -o "$tmp/wgpu.zip" "$url" - unzip -o -q "$tmp/wgpu.zip" -d "$target" -fi diff --git a/src/base/hot_reload.odin b/src/base/hot_reload.odin index 4e8aecd..4d33440 100644 --- a/src/base/hot_reload.odin +++ b/src/base/hot_reload.odin @@ -14,7 +14,7 @@ when ODIN_OS == .Windows { LIB_EXT :: ".so" } -GAME_LIB_DIR :: "build/" +GAME_LIB_DIR :: "out/" GAME_LIB_PATH :: GAME_LIB_DIR + "game" + LIB_EXT // ----------------------------------------- diff --git a/vendor/brokkr b/vendor/brokkr index 9ba6fd8..154ced7 160000 --- a/vendor/brokkr +++ b/vendor/brokkr @@ -1 +1 @@ -Subproject commit 9ba6fd83e67c24e77e641789c9dae862500656ff +Subproject commit 154ced730e1906ee47c3d5fea4e3dd046d2ec872