« Back to Index

Go: compile Rust program via shell to Cargo

View original Gist on GitHub

Tags: #go #rust #compiler

Go compile Rust program via shell to Cargo.go

package main

import (
	"bytes"
	"fmt"
	"io"
	"os"
	"os/exec"
	"strings"
)

func main() {
    // just testing to see if there are problems with spaces.
	os.Setenv("TEST_WITH_SPACE", os.Getenv("DOES_NOT_EXIST")+` -C debuginfo=2`)

	args := []string{
		"+1.49.0",
		"build",
		"--release",
		"--target",
		"wasm32-wasi",
		"--color",
		"always",
		"--verbose",
	}

	// Execute the `cargo build` commands with the Wasm WASI target, release
	// flags and env vars.
	cmd := NewStreamingExec("cargo", args, os.Environ(), true, os.Stdout)
	if err := cmd.Exec(); err != nil {
		fmt.Println("%s", err)
	}
}

// StreamingExec models a generic command execution that consumers can use to
// execute commands and stream their output to an io.Writer. For example
// compute commands can use this to standardize the flow control for each
// compiler toolchain.
type StreamingExec struct {
	command string
	args    []string
	env     []string
	verbose bool
	output  io.Writer
}

// NewStreamingExec constructs a new StreamingExec instance.
func NewStreamingExec(cmd string, args, env []string, verbose bool, out io.Writer) *StreamingExec {
	return &StreamingExec{
		cmd,
		args,
		env,
		verbose,
		out,
	}
}

// Exec executes the compiler command and pipes the child process stdout and
// stderr output to the supplied io.Writer, it waits for the command to exit
// cleanly or returns an error.
func (s StreamingExec) Exec() error {
	cmd := exec.Command(s.command, s.args...)
	cmd.Env = append(os.Environ(), s.env...)

	// Pipe the child process stdout and stderr to our own output writer.
	var stderrBuf bytes.Buffer
	cmd.Stdout = s.output
	cmd.Stderr = io.MultiWriter(s.output, &stderrBuf)

	if err := cmd.Run(); err != nil {
		if !s.verbose && stderrBuf.Len() > 0 {
			return fmt.Errorf("error during execution process:\n%s", strings.TrimSpace(stderrBuf.String()))
		}
		return fmt.Errorf("error during execution process")
	}

	return nil
}