package host import ( "bytes" "fmt" "os/exec" "sync" ) // Builder compiles Go source to WASM. type Builder struct { sourceDir string outputPath string mu sync.Mutex building bool } // BuildResult contains the result of a build operation. type BuildResult struct { Success bool Output string Error error } // NewBuilder creates a new WASM builder. // sourceDir is the directory containing Go source files. // outputPath is the target WASM file path. func NewBuilder(sourceDir, outputPath string) *Builder { return &Builder{ sourceDir: sourceDir, outputPath: outputPath, } } // Build compiles the Go source to WASM. func (b *Builder) Build() BuildResult { b.mu.Lock() if b.building { b.mu.Unlock() return BuildResult{ Success: false, Output: "Build already in progress", Error: fmt.Errorf("build already in progress"), } } b.building = true b.mu.Unlock() defer func() { b.mu.Lock() b.building = false b.mu.Unlock() }() cmd := exec.Command("go", "build", "-o", b.outputPath, b.sourceDir) cmd.Env = append(cmd.Environ(), "GOOS=js", "GOARCH=wasm") var stdout, stderr bytes.Buffer cmd.Stdout = &stdout cmd.Stderr = &stderr err := cmd.Run() output := stdout.String() + stderr.String() if err != nil { return BuildResult{ Success: false, Output: output, Error: err, } } return BuildResult{ Success: true, Output: output, } } // IsBuilding returns true if a build is currently in progress. func (b *Builder) IsBuilding() bool { b.mu.Lock() defer b.mu.Unlock() return b.building }