Something is broken with run_cmd when trying to build physfs...

This commit is contained in:
sergeypdev 2025-05-23 18:52:31 +04:00
parent 55d6de8eb9
commit 1b3d2641e2
5 changed files with 102 additions and 60 deletions

11
.vscode/launch.json vendored
View File

@ -36,6 +36,17 @@
"cwd": "${workspaceFolder}"
},
// Linux / Mac configs
{
"type": "lldb",
"request": "launch",
"name": "Debug Builder",
"args": [
"run",
"./builder"
],
"cwd": "${workspaceFolder}",
"program": "odin",
},
{
"type": "lldb",
"request": "launch",

17
.vscode/tasks.json vendored
View File

@ -66,6 +66,23 @@
"kind": "build",
"isDefault": true
},
},
{
"label": "Build Builder",
"type": "shell",
"command": "odin build ./builder -debug",
"presentation": {
"echo": true,
"reveal": "always",
"focus": false,
"panel": "shared",
"showReuseMessage": false,
"clear": true
},
"group": {
"kind": "build",
"isDefault": false
},
}
]
}

View File

@ -1,3 +1,3 @@
#!/usr/bin/env bash
odin run ./builder -- $@
odin run ./builder -sanitize:address -- $@

View File

@ -35,8 +35,9 @@ build_deps :: proc(opts: Options) {
{
cwd := "./libs/raylib"
out_dir := shared ? "zig-out-shared" : "zig-out-static"
if force {
remove_all(fmt.tprintf("./libs/raylib/%s", out_dir))
if force {
remove_all("./libs/raylib/.zig-cache")
}
target := opts.variant == .Web ? "wasm32-emscripten" : "native"
@ -71,7 +72,6 @@ build_deps :: proc(opts: Options) {
"./physfs",
}
build_cmd := []string{"cmake", "--build", "build", "--config", "MinSizeRel"}
if !is_built || force {
if opts.variant == .Web {
run_cmd(temp_concat({"emcmake"}, prepare_cmd), cwd)
run_cmd(temp_concat({"emmake"}, build_cmd), cwd)
@ -80,7 +80,6 @@ build_deps :: proc(opts: Options) {
run_cmd(build_cmd, cwd)
}
}
}
// Tracy
if opts.tracy {

View File

@ -8,7 +8,6 @@ import "core:log"
import os "core:os/os2"
import "core:path/filepath"
import "core:strings"
import "core:thread"
Process_Error :: enum {
OK,
@ -40,8 +39,9 @@ run_cmd_internal :: proc(
log.infof("running: %s", strings.join(cmd, " ", context.temp_allocator), location = loc)
}
r, w := os.pipe() or_return
defer os.close(r)
r, w := handle_error2(os.pipe())
defer handle_error(os.close(r))
desc := os.Process_Desc {
command = cmd,
working_dir = cwd,
@ -49,55 +49,44 @@ run_cmd_internal :: proc(
stdout = w,
}
Read_Context :: struct {
r: ^os.File,
result: ^string,
process: os.Process
{
defer handle_error(os.close(w))
process = handle_error1(os.process_start(desc))
}
read_ctx := Read_Context {
r = r,
result = &result,
}
state: os.Process_State
thread_ctx := context
thread_ctx.user_ptr = &read_ctx
read_thread := thread.create_and_start(
proc() {
ctx := cast(^Read_Context)context.user_ptr
b := strings.builder_make(context.temp_allocator)
builder: strings.Builder
string_writer := strings.to_writer(&builder)
defer io.destroy(string_writer)
mw: io.Multi_Writer
w := io.multi_writer_init(&mw, string_writer, os.to_writer(os.stderr))
tee: io.Tee_Reader
reader := io.tee_reader_init(&tee, os.to_reader(ctx.r), w)
buf: [1024]u8
err: io.Error
for {
has_data, pipe_err := os.pipe_has_data(r)
if pipe_err != .Broken_Pipe {
handle_error(pipe_err)
}
n: int
n, err = io.read(reader, buf[:], nil)
if err == .EOF {
buf: [1024]u8
if has_data {
n = handle_error1(os.read(r, buf[:]))
handle_error1(os.write(os.stderr, buf[0:n]))
}
if state.exited {
break
}
handle_error(err)
wait_for_kill := false
if pipe_err == .Broken_Pipe {
handle_error(os.process_kill(process))
wait_for_kill = true
}
wait_err: os.Error
state, wait_err = os.process_wait(process, wait_for_kill ? os.TIMEOUT_INFINITE : 0)
if wait_err != .Timeout {
handle_error(wait_err)
}
}
// NOTE: mem leak, but who cares
ctx.result^ = strings.clone(strings.to_string(builder))
},
thread_ctx,
)
process := os.process_start(desc) or_return
os.close(w)
state := os.process_wait(process) or_return
thread.join(read_thread)
if !state.success {
return "", .Crash
@ -133,6 +122,32 @@ handle_error :: proc(
}
}
handle_error1 :: proc(
val: $V,
err: $E,
msg: string = "",
expr := #caller_expression,
loc := #caller_location,
) -> V {
handle_error(err, msg, expr, loc)
return val
}
handle_error2 :: proc(
val1: $V1,
val2: $V2,
err: $E,
msg: string = "",
expr := #caller_expression,
loc := #caller_location,
) -> (
V1,
V2,
) {
handle_error(err, msg, expr, loc)
return val1, val2
}
remove_file :: proc(path: string, expr := #caller_expression, loc := #caller_location) {
log.infof("remove(%s)", path, location = loc)
err := os.remove(path)