odin-lang / Odin

Odin Programming Language
https://odin-lang.org
BSD 3-Clause "New" or "Revised" License
6.8k stars 597 forks source link

Spawning a process #3325

Open HumanEntity opened 7 months ago

HumanEntity commented 7 months ago

Description

I am a odin newbie so I might overlooked something but as a way of learning odin I wanted to make simple build system for odin. And when I was trying to spawn shell process I didn't find anything to do this in core.

Example solution in Odin

For example something like this:

package main

import "core:process"
import "core:fmt"

main :: proc () {
    process_handle, process_spawn_err := process.spawn({"echo", "'Hello, World"})
    if process_spawn_err != nil {
        fmt.panicf("Failed to start command: %v", process_spawn_err)
    }
    output := process.output(process_handle)
    fmt.println(output)
}

Solution in Rust

use std::process::Command;

let output = Command::new("echo")
    .arg("Hello world")
    .output()
    .expect("Failed to start command")
println!("{output}")
gordonshamway23 commented 7 months ago

There is a procedure "process_start" inside core/os/os2/process.odin. But it is not implemented yet or better the whole os2 folder is under construction. If you are on windows you could use the "CreateProcessW" procedure in core/sys/windows/kernel32.odin. If you are on linux there is a "execvp" procedure in core/os/os_linux.odin. Perhaps that helps. Maybe there are other alternatives I couldnt find.

flysand7 commented 7 months ago

This is currently being addressed by the following PR: #3310

If I'm not mistaken the code in the PR practically handles the use-case specified, though it requires a tiny bit more work before I can confidently suggest you copying the code for your own usage.

edyu commented 2 months ago

It would be great to have something similar to go's os/exec.

laytan commented 2 months ago

Like @flysand7 said, this is being worked on in the new os package, currently at core:os/os2 and not intended for general use yet.

The example provided here can be done there with the current functionality like so:

package main

import os "core:os/os2"
import    "core:fmt"

main :: proc() {
    if err := echo(); err != nil {
        os.print_error(os.stderr, err, "failed to execute echo")
    }
}

echo :: proc() -> (err: os.Error) {
    r, w := os.pipe() or_return
    defer os.close(r)

    p: os.Process; {
        defer os.close(w)

        p = os.process_start({
            command = {"echo", "Hello world"},
            stdout  = w,
        }) or_return
    }

    output := os.read_entire_file(r, context.temp_allocator) or_return

    _ = os.process_wait(p) or_return

    fmt.print(string(output))
    return
}